You override parent class methods to define a Java™ agent that meets your needs.
About this task
The Java Agent Project wizard creates
a .java class, and a MANIFEST.MF file
that locates the Java interfaces
of your model. The .java file is a template class
that extends the public
EntityAgent
class,
and has an empty process method that you must override
to handle an event type that is processed by the Java agent and exists in your model.
The EntityAgent class is an agent that is bound to an entity. You can extend
ScoringEntityAgent
to start a scoring
service, and you can also write a Java agent that is not bound
to an entity by using the base
Agent
class.
Tip: To use a third-party library (JAR) in your Java agent, add the JAR to the lib folder inside your Java agent project, and then add it to the
Bundle-Classpath entry in the MANIFEST.MF file.
Use a combination of the following
methods to complete the logic within your Java agent:
Procedure
-
getBoundEntity()
to
retrieve the entity of interest, and cast the result to the interface
that defines the bound entity.
The bound entity is generated
automatically from your model.
-
If the entity does not exist, create the entity by using
the
createBoundEntity()
method.
For example:
Player player = (Player) getBoundEntity();
if (player == null) {
player = createBoundEntity();
}
-
Use the time stamp from an event or the current system time to set the date and time.
For example, if the business definitions contained the following entry:
a player has a last transaction time (date & time).
You can write the following line of code:
player.setLastTransactionTime(thisEvent.get$Timestamp());
The value that is returned by
get$Timestamp() is the time when the
event is fired.
get$Timestamp() is similar to the value of
now
used in a rule agent.
The
ZonedDateTime
class is used to represent all of the time stamps in the system. If
you save a time stamp in an entity, or emit an event, you must use the
ZonedDateTime class to manipulate the time stamp of the event that is being
processed.
-
emit(Event event)
to
emit a new event to do something.
For example:
if (player.getBankroll() > 1000) {
CashBonus cashBonus = getConceptFactory(ConceptFactory.class).createCashBonus(null);
cashBonus.setAmount(100);
emit(cashBonus);
}
-
Use the Java interfaces
get methods
to get a value from an event or the bound entity.
For
example:
PlayerDetails pd = playerDetailsService.getPlayerDetails(player.getPlayerId());
Status status = Status.valueOf(pd.getAccountStatus());
player.setStatus(status);
-
You can also use
instanceof tests to
cast the event that is handled by the process method
to one of the generated interfaces from your model.
-
updateBoundEntity(Entity)
to
update the bound entity after it is created or modified.
Call this method when a bound entity is modified so that entity changes are saved to the object
grid. You must verify that the bound entity is successfully updated. If more than one agent is bound
to an entity, the entity is passed to each agent that reads from or writes to the object grid.
Therefore, if the updateBoundEntity method is not called, agents that use the
entity might not receive the most current version.
For example:
updateBoundEntity(player);
-
Schedule callbacks to the agent by using the
schedule
method.
-
Override the
process(String, String)
method
to handle scheduled notifications.
-
Call
getGlobalValue(String)
to
retrieve the value of a global event or entity aggregate.
-
Call
getJobService()
to
programmatically request updates to the values of global event or
entity aggregates.
-
Run geospatial calculations by calling
getSpatialService()
.
You must get a geospatial service, a geometry factory from that service, and then
instantiate instances of any geospatial type from that factory. All coordinates are by default in
the decimal representation of world coordinates in latitude/longitude pairs, unless you define a
different coordinate reference system. The following example instantiates a polygon with three
points.
@Override
public void process(Event event) throws AgentException {
if(event instanceof Transaction) {
Transaction transaction = (Transaction)event;
GeoSpatialService geometryService = GeoSpatialService.getService();
GeometryFactory geometryFactory = geometryService.getGeometryFactory();
Polygon poly = geometryFactory.getPolygon(
geometryFactory.coordsToPoints(new double[][]{
{1.0, 1.1},
{1.2, 1.3},
{1.4, 1.5}
})
);
transaction.setPolygon(poly);
}
}
Results
Warning:
If a Java agent uses an excessive amount of time to complete, it can be stopped by the run time.
In such cases, a CWMBD0122W message is returned. Examine the associated agent for
issues that might prevent timely execution, for example, an infinite loop.
Example
There are a number of reasons why you might want to choose
to create a Java agent. One
example might be that you want to retrieve data from a relational
database when an event arrives because the data does not exist in
the grid. A Java agent can be
used to initialize the data. Java is
useful to map between the integers and strings in the database and
the domains that are modeled for writing rules.
A solution that
retrieves data from a relational database might use the following
logic:
- An OSGi service retrieves the data from a primary key. The service
uses JDBC to call the relational database.
- A Java agent subscribes
to all relevant events. A
process method checks whether
the bound entity is null. If the entity is null,
it calls the OSGi service to retrieve the data and creates the bound
entity and sets properties that are based on the results from JDBC.
The updateBoundEntity method is called.
- The priority of the Java agent is set to
HIGH to ensure that it runs before all other agents.
- Rule agents that are bound to entities, which are modified by Java agents, are given a priority
of
LOW.
- Rule agents know that the data is initialized from the relational
data store and do not have to check for
null.
Remember: When multiple agents use the same event
to modify the same entity, agent priorities are used to define which
agent processes the event first. For more information, see
Completing the agent descriptor.