Event Notifier in Apache Camel Route
Apache Camel is an open-source, lightweight integration library. In this article, I will demonstrate the concept of events it allows and how to use them.
Join the DZone community and get the full member experience.
Join For FreeIntroduction
Each step of an Apache Camel Application triggers an event that allows us to read or edit data while the message travels on the "Route." The provided mechanism to access these events is the EventNotifierSupport
class.
Apache Camel's route is a sequence of steps, executed in order by Camel, that consumes and processes a message. The initial point of this sequence is represented by the method from()
. A route may have many processing components that modify a message or send it to an endpoint.
To send a message to an endpoint, we use the method to()
, so the basic structure of an Apache Camel Route will be:
Between two points, like a from()-> to()
or to() -> to()
, many other steps occur that we cannot avoid. We call these steps "events."
Events are essential for us because we can interact with them to enrich our application's behavior.
Interaction With Events
To capture events in Apache Camel, we need to create a class that extends the abstract class EventNotifierSupport
. In this class, we will specify a method called isEnabled
to activate the event capture.
In the example below, there are two methods: the method isEnable
tells Apache Camel that we will capture the events. If the isEnabled
method returns true, the notify
method receives the event, and then we can interact with them.
xxxxxxxxxx
public class CamelEvents extends EventNotifierSupport {
private Integer eventSequence = 1;
public void notify(EventObject event) throws Exception {
}
public boolean isEnabled(EventObject event) {
return true;
}
}
The notify
method receives an object of type EventObject
that contains the event that occurred at the moment. We can verify what event was started by checking the instance of the object.
xxxxxxxxxx
public void notify(EventObject event) throws Exception {
if (event instanceof ExchangeCreatedEvent) {
...
}
...
After capturing the event, we can interact with it to read or edit data in the message trafficked on the route. For example, we can implement an automatic log of all content trafficked on the route at each stage, or we can apply rules to validate the data or enrich it.
We can make life easier for developers by creating generic components that remove the need to develop repetitive or common block codes.
I posted an event capture example on GitHub. Inspect the class com.consulting.fuse.poc.event.CamelEvents.java
and notice the notify
method capturing a lot of events.
Also notice the below route:
xxxxxxxxxx
from("file:trigger/?fileName=test-a.txt&noop=false")
.routeId("route-a")
.to("bean:processorA")
.log("### :: The step to(\"bean:processorA\") was executed")
This route reads a file called "test-a.txt" in a specific folder and sends the content to a process named processorA
using the to()
method.
In this flow, the following events occur in sequence:
ExchangeCreatedEvent
ExchangeSendingEvent
ExchangeSentEvent
ExchangeCompletedEvent
When the route is executing, each event is sent to the Event Notifies implementation in the class CamelEvents
.
In this example, we printed each event in the log with the sequence number of execution.
In each event, we can manipulate or only get the values of Exchange to use. The following block changes the content received from the file for an upper case value-added the prefix "EDITED:"
So if we include other steps in our route, the trafficked content will always be in capital letters. The programmer doesn't need to worry about it because the event does it for all routes.
if (event instanceof ExchangeSentEvent) {
String body = ((ExchangeSentEvent) event).getExchange().getIn().getBody(String.class);
body = "EDITED: " + body.toUpperCase();
((ExchangeSentEvent) event).getExchange().getIn().setBody(body);
LOGGER.info("### [EVENT] ExchangeSentEvent executed " + eventSequence + " :: Body content edited to UPPERCASE");
}
Something important to say is that Exceptions also launch events. Take, for example, the route-non-handled-exception route that exists in our sample. When we force an Exception, an event called ExchangeFailedEvent
occurs regardless of whether we treat or not the Exception.
xxxxxxxxxx
from("file:trigger/?fileName=test-b.txt&noop=false&moveFailed=failed")
.routeId("route-non-handled-exception")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
if (null == exchange.getIn().getHeader("fooHeader")) {
throw new NonHandledException("Exception throwed to test"); }
}
})
.log("NonHandledException occur ")
Conclusion
Events are potent resources on our routes. As shown in our example, several events happen during the execution of our Camel routes. Explore our example application and watch the events occurring from the application's initialization to completing a route.
Unfortunately, there isn't extensive documentation on these events, but here we have a good starting point.
Opinions expressed by DZone contributors are their own.
Comments