For keeping code maintainable, it is wise to make a clear division between different tasks in a project. The GX WebManager architecture allows such separations to be made in a very clear way: using separate WCBs. However, in practice it might sometimes be difficult to decide in what way to split up functionality and how to keep the code connected. In this post I describe one way of keeping the code connected: the EventManagerService.
The services offered by the EventManagerService are pretty straightforward: services can subscribe to specific events they’re interested in, while other services can publish events when they occur. The EventManagerService makes sure that all services that have subscribed to particular events will be informed when they are published. To illustrate how this works, I’m going to use an example where an external WCB is used to generate PDF files of products as soon as they are updated using the maintenance panel or a periodic synchronization task.
To start, I create a class that holds the information that needs to be sent out when the event occurs. The event must implement the Event interface, such that the EventManagerService can route the events to the correct subscribers. Within my project a generic ValueObject class is used and it is extended for each entity within the domain model. Therefore, I create a generic ValueObjectEvent class that can be used for events regarding any entity type. The implementation of the class is pretty straightforward, so I’ll just leave the ValueObjectEvent.java file up for download.
As said before, for each entity type there is a class that extends the ValueObject class. This allowed us in the past to create a single DAOHelper class that is used for persistence. I didn’t want to modify this class, as it’s already pretty complex and focuses on the actual persistence, I decided to extend it, such that I only need to override the methods that are actually making changes to the persistent storage.
The overridden methods publish two events for each operation: one event before the persistence operation and one event after. Again, everything is pretty straightforward and I’ve just put up the EventPublishingDAOHelper.java file up for download. At this moment, any change of any entity that is handled by our service can be monitored through by other WCBs through the EventManagementService.
The only thing left is implementing the service that acts on the interesting events. I wanted to implement this in a separate WCB, because I didn’t want to add a dependency from the product maintenance service WCB to a PDF manipulation library.
In the new WCB, I create a service that overrides the onStart() and onStop() methods and implements the EventHandler interface to subscribe and unsubscribe to the interesting events:
/**
* {@inheritDoc}
*/
@Override
public void onStart() {
super.onStart();
if (myJcrRepository.isReadOnly()) {
LOG.info("Not starting the PDF generator on a read-only node");
return;
}
myEventManagerService.subscribe(this, Event.Type.POST, Product.class);
}
/**
* {@inheritDoc}
*/
@Override
public void onStop() {
super.onStop();
if (myJcrRepository.isReadOnly()) {
LOG.info("Not stopping the PDF generator on a read-only node");
return;
}
myEventManagerService.unsubscribe(this, Event.Type.POST, Product.class);
}
Notice that the Product class extends the ValueObject class. Now, any time a product is changed, the onEvent method is fired in my service and again a pretty straightforward implementation determines the correct moments to generate the PDF files, obtains the product object and starts the generation process:
/**
* {@inheritDoc}
*/
public void onEvent(Event anEvent) {
try {
if (anEvent instanceof ValueObjectEvent) {
ValueObjectEvent event = (ValueObjectEvent) anEvent;
if (ValueObjectEvent.CREATE.equals(event.getEventAction())
|| ValueObjectEvent.UPDATE.equals(event.getEventAction())) {
Object entity = event.getEntity();
if (entity instanceof Product) {
Product product = (Product) entity;
generatePdf(product);
}
}
}
} catch (IOException e) {
LOG.log(Level.SEVERE, e.getMessage(), e);
}
}
Mark is software engineer with a special interest in Security and Digital WebTV. Mark writes about daily engineering with GX WebManager
Other blog entries: