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 modeled 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 is comprised of 2 functions: create 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 and loads 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;
  }