Tom Donohue Tom Donohue

Calling a RESTful service from Apache Camel

The most interesting part of integration is when we’re integrating with other services.

For example, you might need to integrate with the Stripe API to process payments. Or you might have a company internal REST API that you need to talk to. Most modern APIs now use the REST style, which is great as it’s fairly lightweight and easy to use.

So how do you invoke a REST service from Camel? Which component should you use?

In this article I’ll tell you what I think is the easiest way to call an external web service from Camel, and share some example code that you can use.

Let’s go!

What do we need from our Camel kit bag?

Figuring out how to implement something in Apache Camel can be a bit overwhelming when you’re a beginner. Where do you even begin?

We want to invoke a REST API. So let’s take a look at what we need to do, step-by-step:

  • First, we need something to trigger the REST request. In Camel, we’re always responding to a trigger, event or request. A Camel route always starts with a component which acts as the trigger.

    So… I’ll use a Timer component to start the route, which will fire the route immediately. But you could start your route with something else, like a Direct component or a JMS component.

  • We need to build up a URL dynamically. We might need to modify some parts of the REST API URL, depending on values that we know about. For example, the URL of the REST API might change, depending on the username of the requester, or the Product ID that you’re trying to retrieve.

    So… I’ll use the ToD EIP in Camel, which is one way to send a message to an endpoint, if the URL needs to be dynamic. It’s useful if the URL can only be known at runtime. You can also use the Recipient List pattern for this.

  • We need to make an HTTP request. Calling a REST service is basically just making a simple HTTP request, and there are lots of different ways to do this in Camel. We just need to use a component which can be used as an HTTP client.

    So… I’ll use Camel’s HTTP component (previously called the “HTTP4” component). It’s a simple HTTP client, that we can use to make GET requests, POST requests, or anything we want.

By the way, if you’re just getting started with Apache Camel, then make sure you download the first chapters of my book for beginners. It’s free! Check it out below:

Invoking a REST service from Camel - step-by-step

Let’s do it! Let’s invoke a REST service using Apache Camel.

To follow the steps in this tutorial with your own service, you need to have Apache Camel already set up in your project.

Don’t have a Camel project yet? If you don’t have Camel added into your project, go to the Spring Initializr to create a new Spring Boot app with Camel support, or create a new Camel project from a Maven archetype.

This code has been verified with Apache Camel 3.0.0.

  1. Let’s add our Maven dependencies. In the section above, I said we’re going to use the HTTP component. It’s a simple HTTP client, which is perfect for us.

    To use it, you need to add the camel-http dependency to your Maven POM:

    <dependency>
      <groupId>org.apache.camel</groupId>
      <artifactId>camel-http</artifactId>
    </dependency>
    

    Using a version of Camel prior to 3.0? You’ll need to use the dependency camel-http4. The component was renamed in Camel 3 and the number 4 was dropped.

  2. Let’s add a new Camel route to our RouteBuilder class. This route will call the external web service.

    I’m going to start the route with a Timer, just to make it easy to run.

    from("timer:mytimer?repeatCount=1")
      //....the rest of the route will go here.
    

    Notice how I’m setting the repeat counter to 1, so that it only executes once.

    Depending on your app, you might want to start this route with a Direct component instead, or perhaps a JMS component if you’re reading from a queue.

  3. Set the body of the request. We do this using the setBody step. The contents of the Body will be used when making the HTTP request.

    I’m going to send some arbitrary JSON, just some information about a cat: 🐈

    .setBody(simple("{ \"cat\": \"Milo\" }"))
    

    If you’re making a GET request to your REST API, you shouldn’t need this step. So you can set the body to null if you prefer:

    .setBody(simple("${null}"))
    
  4. Set anything else dynamic you might need in the request. In this example, I’m calling a Cat API (yes I like cats) and it will expect a cat name in the URL.

    I’m using constant to set a constant value – but you might use something dynamic here to set the value you need:

    .setHeader("catName", constant("Bernice"))
    
  5. Using Camel’s toD pattern to create a dynamic URI, we build the target URL which we want to invoke. The URL begins with http, which will use the HTTP component we added above.

    Here I also show you how you could include something dynamic in the URL. Dynamic values in Camel that are part of the message being processed will usually be stored in a header, or in the body. Earlier, I stored a value in a header, catName, so I’m using ${header.catName} to reference it:

    .toD("http://www.examplecat.com/cats/${header.catName}" +
        "?httpMethod=POST")
    

    We add httpMethod, to tell the HTTP component which HTTP action (verb) we want to use. If you need to use GET, PUT, or something else, you should update this property.

  6. Now do something with the response from the RESTful service. Once we’ve made the request, we can access the response in the Camel Exchange Body, e.g.:

    .log("The body was - ${body}");
    

Adding authentication (optional)

If you need to provide a username and password to the REST request, you can use the auth parameters, like this:

.toD("http://www.examplecat.com/cats/${header.catName}" +
    "?httpMethod=GET" +
    "&authMethod=Basic" +
    "&authUsername=" +
    "&authPassword=" +
    "&authenticationPreemptive=true")

This will send credentials to the service, using Basic HTTP authentication.

A complete example and sample code

Let’s put it all together.

The following example Camel route calls a RESTful service. It uses the GitHub API to create a new private Gist in your account.

from("direct:create-gist")
    .log("Creating a Gist on GitHub...")

    // Set the body to null, because it is required by the GitHub API.
    // But you can set the body here to anything you like.

    // This is the content of our Gist.
    // See: https://docs.github.com/en/rest/reference/gists#create-a-gist
    .transform(simple("{\"files\":{\"README.md\":{\"content\":\"Hello from Camel!\"}}}"))

    // Now invoke the GitHub API with the Gist JSON in the body
    // POST /gists
    .to("https://api.github.com/gists" +
            "?httpMethod=POST" +
            "&authMethod=Basic" +
            "&authUsername=" +
            "&authPassword=" +
            "&authenticationPreemptive=true")

    .log("Response code from the Create Gist operation was: ${header.CamelHttpResponseCode}")
    .log("Response body from the Create Gist operation was: ${body}");

If you want to run this demo, set up a Personal Access Token in your GitHub account and then grab the source code from GitHub. See the link below:

See the example code on GitHub

Icons made by Smashicons on Flaticon  

Comments

What do you think? You can use Markdown in your comment.

To write code, indent each line with 4 spaces. Or, to paste a lot of code, you can put it in pastebin.com and share the link in your comment.