Skip to main content

Unit 13: Implement Agent

๐ŸŽฏOverview

In this course you will learn how to implement an agent within the domain namespace using your local IDE.

Outlineโ€‹

The next part of implementing the domain namespace is to provide an agent with code. As explained in Unit 5: Design Agent and Event, you can configure an agent for an event that e.g. is published by another service. Publishing the respective event then triggers the agent and executes its code. Similar to domain services an agent performs logic independent from root entities and can be used for various purposes. But the difference to it is that an agent takes the payload of the trigger event as its input and has no output.

Prerequisitesโ€‹

โ—๏ธAlternative starting point for your training

If you rather want to use this course as a starting point of your training, you can use a different asset where all courses for designing are already completed.
In this case - depending on the chosen implementation language - use either asset "Order_Java_Code_0.1" or "Order_TypeScript_Code_0.1" to create a new project and to continue your training.
You can look up how to create a new project from the Order assets in the Preparation section in the Course Introduction.

Exerciseโ€‹

Estimated time: 15 minutes
Exercise goal: After completing this course you will know how to implement an agent that is part of the communication between services via events.
Supported languages: Java and TypeScript

In this exercise we will implement the CustomerLifecycleEventAgent which gets triggered when the CustomerLifecycleEvent is published from another microservice. If the event indicates the deactivation or deletion of a customer, its not yet processed orders do not have to be processed anymore. Therefore all these customer orders will be cancelled.

Step 1: Implement the agentโ€‹

The steps in our agents are going to be as follows:

  • Check the received event if a customer is deactivated or deleted, otherwise do no further actions
  • Call the CancelAllOrdersOfCustomer domain service with the customerReferenceId from the event payload
  • If necessary, log the error message of the service call
  1. Open the file /src/main/java/<package-name>/domain/ord/agent/CustomerLifecycleEventAgent.java.
    You will see an auto-generated stub in which you can start your implementation.

    <package-name>: The package name of the Java project (e.g. com.knowis.orderjfinal)

    @Service("ord_CustomerLifecycleEventAgent")
    public class CustomerLifecycleEventAgent extends CustomerLifecycleEventAgentBase {

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

    public CustomerLifecycleEventAgent(DomainEntityBuilder entityBuilder, Repository repo) {
    super(entityBuilder, repo);
    }

    @Override
    public void onMessage(
    TrainingCustomerLifecycleEvent1x0Schema payload,
    MessageHeaders headers
    ) {
    log.info("Agent CustomerLifecycleEventAgent received event cust:CustomerLifecycleEvent");
    // TODO: Add your agent implementation logic
    }
    }
  2. To reuse the implemented domain service CancelAllOrdersOfCustomer, we have to create a private field for the respective class. Additionally we have to add a constructor parameter that is then assigned to the private field.

    private final CancelAllOrdersOfCustomer cancelAllOrdersOfCustomer;

    public CustomerLifecycleEventAgent(
    DomainEntityBuilder entityBuilder,
    Repository repo,
    CancelAllOrdersOfCustomer cancelAllOrdersOfCustomer
    ) {
    super(entityBuilder, repo);
    this.cancelAllOrdersOfCustomer = cancelAllOrdersOfCustomer;
    }

    Please use the auto-import function of your IDE to import the missing classes (and repeat this for the following steps). If you are not very familiar with imports, go back to Course 11 - Step 3: Import missing Classes for detailed information on class imports. Furthermore, you are free to compare your current imports with the recommended list of imports at the end of this section. Therefore, click here.

  3. After injecting the field, we will extend the onMessage method in the following steps.
    First, we will check the status property of the event payload. If it is not "DELETED" or "DEACTIVATED", the method has to stop.

    // Step 1: Check the property for the new customer status in the payload
    // If not DEACTIVATED or DELETED, return early
    if (payload.getCustomerNewStatus().equals(TrainingCustomerLifecycleEvent1x0Schema.CustomerNewStatus.DEACTIVATED)
    || payload.getCustomerNewStatus().equals(TrainingCustomerLifecycleEvent1x0Schema.CustomerNewStatus.DELETED)) {
    return;
    }

    payload: provides type-safe access

  4. Then we will call the domain service to cancel all orders of the customer with the provided customer reference id. If the domain service throws a business error, we have to log its error message.

    // Step 2: Cancel all orders of the customer via the CancelAllOrdersOfReference domain service
    // Create the domain service input
    CancelAllOrdersOfCustomerInput domainServiceInput = this.entityBuilder.getOrd().getCancelAllOrdersOfCustomerInput()
    .setCustomerReferenceId(payload.getCustomerId())
    .build();

    // Execute the domain service
    try {
    this.cancelAllOrdersOfCustomer.execute(domainServiceInput);
    } catch (NoMatchingOrdersFound e) {
    log.error("No matching orders found to cancel!", e);
    }
โ„น๏ธRecommended List of Imports

The provided list supports you to compare your current imports with the recommended list, especially if your IDE complains about errors in the code at this stage of the course.

List of Imports - File CustomerLifecycleEventAgent.java
// Fundamental 1: Generated classes based on design
import com.knowis.orderjfinal.sdk.domain.facade.DomainEntityBuilder;
import com.knowis.orderjfinal.sdk.domain.facade.Repository;
import com.knowis.orderjfinal.sdk.domain.ord.agent.CustomerLifecycleEventAgentBase;
import com.knowis.orderjfinal.sdk.domain.ord.entity.CancelAllOrdersOfCustomerInput;
import com.knowis.orderjfinal.sdk.domain.ord.error.NoMatchingOrdersFound;
import com.knowis.orderjfinal.sdk.domain.schemas.TrainingCustomerLifecycleEvent1x0Schema;

// Fundamental 3: Built-in Java classes
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.messaging.MessageHeaders;
import org.springframework.stereotype.Service;

// Fundamental 4: Classes from other implementation files
import com.knowis.orderjfinal.domain.ord.service.CancelAllOrdersOfCustomer;

The package name of the provided code is com.knowis.orderjfinal. All occurrences of this phrase have to be replaced with the package name of your project.

๐ŸŒŸCongratulations!

You have successfully implemented an agent and worked with events! Now you are able to define and implement the communication between services via events with the IBM DevOps Solution Workbench.

What's Next?โ€‹

In the next course you will learn how to implement an integration service that calls an external API to send an email notification when an order is created.