General Implementation Examples

This page gives an overview of the most common use cases and how to implement them with a Low-Code Project based on Java Spring Boot.

Factory Commands

The main purpose of a factory command* is to set values to the properties of a root entity and then persist those changes to the database, thus, creating a new instance.

The factory command to create an instance of a root entity called MasterCard is the following:

    @Service
    public class MasterCardCommand extends MasterCardCommandBase {

      @Override
      public void createCreditCard(MasterCard instance, CreateCreditCardInput createCreditCardInput) {
      
        // Fill instance with values from input entity
        instance.setBankName(createCreditCardInput.getBankName());
        
        // save entity to repository
        repo.cc.masterCard.save(instance);
      }
    }

Instance Commands

The implementation of an instance command called ActivateCard which manipulates the state of an instance of the root entity MasterCard is shown below:

    @Service
    public class MasterCardCommand extends MasterCardCommandBase {

      @Override
      public void activateCard(MasterCard instance) {
      
        // Change root entity data
        instance.setActive(true);
        
        // Save to repository
        repo.cc.masterCard.save(instance);
      }

Events

Within stub classes (commands, services, agents) that are modelled to publish events, a dedicated event publish function will be available from the base class.

    @Service
    public class MasterCardCommand extends MasterCardCommandBase {

      @Override
      public void activateCard(MasterCard instance) {
      
        // Change root entity data
        instance.setActive(true);
        
        // Save to repository
        repo.cc.masterCard.save(instance);

        // Create payload entity
        SuccessEventPayload  payloadEntity = entityBuilder.cc.successEventPayload().build();

        // Create domain event
        SucessEvent event = eventBuilder.cc.sucessEvent().setPayload(payloadEntity).build();

        // Publish event via publishSucessEvent() that exists defined in MasterCardCommandBase class.
        publishSucessEvent(event);
      }

An event can also be published by using the structure of the following code:

    // Declare event builder
    @Autowired
    EventBuilder eventBuilder;  

    // Declare entity builder
    @Autowired
    EntityBuilder entityBuilder;  

    // Declare Event Prodcuer Service
    @Autowired
    EventProducerService eventProdcuer;

    // Create payload entity
    SuccessEventPayload payloadEntity = entityBuilder.cc.successEventPayload().build();

    // Create domain event
    SucessEvent event = eventBuilder.cc.sucessEvent().setPayload(payloadEntity).build();

    // Publish a domain event.
    eventProdcuer.publish(event);

Agents

When an event was triggered, it will call any agent that is bound to this event. This agent will receive the payload of the event as input and then it can call a service or publish another event.

    public class SucessEventAgent extends SucessEventAgentBase {

      private static Logger log = LoggerFactory.getLogger(SucessEventAgent.class);

      @Override
      public void onMessage(SucessEventPayload sucessEventPayload) {
        log.info("Agent SucessEventAgent received event cc:SucessEvent");

        // call service to notify customer passing the sucessEventPayload to the service as input
        service.cc.notifyCustomer(sucessEventPayload);
      }
    }

Domain services

The implementation of a domain service called GetCustomer is shown below:

    @Service
    public class GetCustomer extends GetCustomerBase {
      
      @NewSpan
      @Override
      public Customer execute(GetCustomerInputEntity input){
      
        // Call repository to get all customers
        return repo.cc.customer.findById(input.getCustomerId());
      }
    }
Tip: The @NewSpan annotation creates a new span which will be a child of the existing span via the underneath springframework.cloud.sleuth that helps with microservice tracing.

External Entity Service

The external entity service comprises 3 functions: create, load and validate.

Create

The create function is used to construct a local instance of the External Entity and initialize the associated properties with certain pre-specified values that are provided as input parameters.

The input parameters are also used to identify and load external entity from external system.

    @Service
    public class AmexCardService extends AmexCardServiceBase {

      @Override
      public AmexCard create(String amexCardId, String customerId) {

        // Call your external system and use parameters to identify and load external entity
        // Create external entity instance and set its properties
        
        AmexCard amexCard = new AmexCard(amexCardId, "Card type retrieved from external entity");
        
        return amexCard;
      }

Validate

The validate function gives information regarding the existence of a specific instance of an external entity within external system.

It usually returns

  • the external entity's instance if the external instance exists in the external system

  • null if it does not exist

The validator can also be used for updating the local instance of an external entity if the update flag is set to true.

Tip: In a validator it is recommended to try to load the instance. If the instance is returned successfully, then update and return the external entity instance.
    /**
    * validate the existence of the external entity in the external system.
    *
    * @param externalEntity instance of AmexCard.
    * @param update          flag to indicate whether should an updated
    *                        AmexCard instance be created and returned or not.
    * @return Optional AmexCard instance to indicate whether
    *         external entity still exists in external system
    */
    @Override
    public Optional<AmexCard> validate(AmexCard externalEntity, boolean update) {

      // Call external system to validate existence of external entity in external system
      // Also you can update external entity properties
      
      AmexCard amexCard = new AmexCard(externalEntity.getAmexCardId(),
        "Updated Card type info retrieved from external entity");

      return Optional.of(amexCard);
    }

Load

The load function implements logic to call external system and loads the full external entity data.

A local external entity instance is used to provide identifier properties needed to call external systems and fully load the external entity's data. You can build an entity, fill it with data coming from external system and return that entity for further usages.

  /**
    * Load external Entity and return as an Entity
    *
    * @param externalEntity instance of AmexCard
    * @return class that extends base type Entity
    */
    @Override
    public Entity load(AmexCard externalEntity) {

      // Call external system to load external entity(for example make a REST call)
      
      // Build a card entity and fill with data from external entity
      Card card = entityBuilder.cc.card().build();

      return card;
    }