DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Low-Code Development: Leverage low and no code to streamline your workflow so that you can focus on higher priorities.

DZone Security Research: Tell us your top security strategies in 2024, influence our research, and enter for a chance to win $!

Launch your software development career: Dive head first into the SDLC and learn how to build high-quality software and teams.

Open Source Migration Practices and Patterns: Explore key traits of migrating open-source software and its impact on software development.

Related

  • How To Get Cell Data From an Excel Spreadsheet Using APIs in Java
  • 8 Strategies To Accelerate Web Portal Development
  • Flex for J2EE Developers: The Case for Granite Data Services
  • Enterprise RIA With Spring 3, Flex 4 and GraniteDS

Trending

  • GenAI: Spring Boot Integration With LocalAI for Code Conversion
  • How To Compare DOCX Documents in Java
  • LLM Orchestrator: The Symphony of AI Services
  • Mastering Serverless Debugging
  1. DZone
  2. Data Engineering
  3. Data
  4. Apache Camel Content Enricher Example

Apache Camel Content Enricher Example

A simple self-contained example of using Apache Camel to route and transform data.

By 
Alan Hohn user avatar
Alan Hohn
·
Aug. 26, 16 · Tutorial
Like (5)
Save
Tweet
Share
19.9K Views

Join the DZone community and get the full member experience.

Join For Free

In a previous article, I discussed why Apache Camel is a useful tool for building small modules to perform integration independent of any of the pieces being integrated. With that out of the way, I can go straight into showing an example of using Apache Camel's content enricher.

The basic flow of our Camel route is to listen for data to come in via a publish-subscribe messaging destination and send it back out in a format that another consumer is expecting. However, the incoming data does not have all the information required to complete the outgoing message. So the content enricher is going to fetch that data from somewhere else to fully populate the outgoing message.

To illustrate all of this, I've created an example on GitHub. In order to create a self-contained example, I've included an embedded REST service that will be the source of our "extra" data, and a data generator to replace the initial publish-subscribe message from the first producer.

Embedded REST Web Service

The embedded REST web service is based on one I built last year using Jersey and Jetty. I wrote that up at the time, so no need to go into too much detail. I'll just show the key part of the service so we can see what it's doing with the data it gets:

@POST
@Path("/lookup")
@Consumes({"application/json"})
@Produces({"application/json"})
public OrderInfo fillIn(OrderInfo info) {
    info.setCustomerName("Johannes Smythe");
    info.setOrderTotal(r.nextDouble() * 100.0);
    return info;
}


The great thing about JAX-RS is how simple it makes this kind of thing. The OrderInfo class is a data transport object (DTO) that just stores information related to an order. This method takes whatever data is passed in and populates a couple additional fields. When we run this via the embedded Jetty server (see GitHub and the article for details) we can see the following output (using httpie):

$ http :8680/rest/order/lookup orderNumber=123
HTTP/1.1 200 OK
Content-Type: application/json
Server: Jetty(9.1.1.v20140108)
Transfer-Encoding: chunked

{
    "customerName": "Johannes Smythe",
    "orderNumber": 123,
    "orderTotal": 55.91403903011334,
    "timestamp": null
}


Camel Route

So we have our external "resource" ready. Now we need to supply the Camel route that will use it. I'm electing to use the Java DSL, mostly because I have a lot more experience with using either Spring or Blueprint XML. To build a Camel route using the Java DSL, we create a route builder:

public class EnrichRoutePost extends RouteBuilder {

    @Override
    public void configure() throws Exception {
        from("timer://ordergen").bean(new OrderGenerator(), "generate")
                .marshal().json(JsonLibrary.Jackson)
                .setHeader(Exchange.CONTENT_TYPE, constant("application/json"))
                .enrich("http://localhost:8680/rest/order/lookup").log("${body}");
    }

}


By extending the RouteBuilder class, we get access to lots of useful chaining methods. Under the covers, when the route is built, Camel creates objects representing each stage of the route, and gives each stage a reference to the next stage. As a result, at runtime executing the route is making a series of method calls, where possible directly from one step in the route to the next. This is done for performance reasons.

The method calls between steps in the route include a parameter called an Exchange, which Camel uses to hold an "incoming" and an "outgoing" message. Each message includes headers and a body. The header names are strings; the header value and body can be of any type. When building and debugging Camel routes, it is critical to think about the state of the exchange at each step in the route, as this will directly affect the behavior of the next step.

The most generic route building methods are from() and to(); with these methods we can provide any URI that Camel understands and configure using path and query parameters in the URI. The URI schemes that Camel understands are dynamic based on what Camel components are on the classpath; this extensibility is a big reason for Camel's success.

In this case, we are starting with a timer; for recent versions of Camel it defaults to once per second after one second, so we don't need to do any configuration. At this point, the exchange has no usable data, and we want it to contain an object of type OrderInfo, so we use a bean() to call an arbitrary method on a Java class that creates an object of the type we want. These two steps together simulate the publish-subscribe message we might receive in a real system.

Now that we have an object of type OrderInfo we want it to become the input to the REST web service. For this to work, we need to convert it to JSON. We do this with amarshal(), specifying JSON as the target using the Jackson library. This works without any configuration as long as the camel-jackson library is on the classpath. The exchange now contains a string form of the order info in JSON format.

The next step does the content enriching by calling the web service. The enrich() processor takes a URI, similar to from() and to(). Based on the URI, it routes the incoming message to a component, and sets the outgoing message based on what returns from the component. (Headers are copied over.) In our case, this means that the enricher uses the HTTP component to POST to the supplied URL, sending the JSON data as the POST body. The JSON data that comes back becomes the outgoing message body.

To run this route, we need to embed it in a Camel context and start that context:

RouteBuilder builder = new EnrichRoutePost();
CamelContext context = new DefaultCamelContext();
context.addRoutes(builder);
context.start();


We then see output like this:

[Camel (camel-1) thread #0 - timer://ordergen] INFO route1 - {"timestamp":1472045595996,"orderNumber":308,"customerName":"Johannes Smythe","orderTotal":36.50952697279789}


The output contains data from both the original generator and the REST web service.

Wrapping Up

Using a content enricher this way, we're really just using enrich() as syntactic sugar in place of to(); the behavior would be exactly the same. But the content enricher is capable of more complex behavior, and we'll need that in the next article in order to deal with some use cases that aren't quite this simple.

Apache Camel Data (computing) Web Service

Opinions expressed by DZone contributors are their own.

Related

  • How To Get Cell Data From an Excel Spreadsheet Using APIs in Java
  • 8 Strategies To Accelerate Web Portal Development
  • Flex for J2EE Developers: The Case for Granite Data Services
  • Enterprise RIA With Spring 3, Flex 4 and GraniteDS

Partner Resources


Comments

ABOUT US

  • About DZone
  • Send feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: