Unit 13: Implement Agent
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โ
- You have successfully completed Unit 10: Set up Project for Implementation.
- You have successfully completed Unit 5: Design Agent and Event.
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
CancelAllOrdersOfCustomerdomain service with the customerReferenceId from the event payload - If necessary, log the error message of the service call
- Java
- TypeScript
-
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
}
} -
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.
-
After injecting the field, we will extend the
onMessagemethod 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 -
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);
}
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.
-
Open the file
/src-impl/domain/ord/agents/CustomerLifecycleEventAgent.ts.
You will see an auto-generated stub with a methodexecutein which we will provide the implementation of the domain service.export default class extends agents.ord_CustomerLifecycleEventAgent {
public async execute(): Promise<void> {
const log = this.util.log;
log.debug('ord_CustomerLifecycleEventAgent.execute()');
}
} -
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 (this.input.customerNewStatus === 'DEACTIVATED' || this.input.customerNewStatus === 'DELETED') {
return;
} -
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 CancelAllOrdersOfCustomer domain service
// Create the domain service input
const serviceInput = this.factory.entity.ord.CancelAllOrdersOfCustomer_Input();
serviceInput.customerReferenceId = this.input.customerId;
// Execute the domain service
try {
await this.services.ord.CancelAllOrdersOfCustomer(serviceInput);
} catch(e) {
log.error("No matching orders found to cancel!", e);
}this.services: allows to call any service modelled within a domain or integration namespace.
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.