Creating a REST API in Apache Camel

Updated:

You’ve learned the basics of Apache Camel. You now know how to process an incoming message. (That’s all you need to do, isn’t it? Job done! K thanks bye! 👋)

Of course, receiving a message is probably not all you’ll need to do.

You’ll probably want to work with web services. Perhaps you want to consume a REST API. Or you need to integrate with some old SOAP system (don’t worry, SOAP lovers, Camel has got your back too).

In this tutorial, you’ll learn how to use Camel to create a REST service.

Related reading - If you’re not familiar with Apache Camel, then I encourage you to read the first part of my Apache Camel Tutorial

How do you create a REST service with Camel?

There are, perhaps confusingly, a gazillion different ways of creating a REST service with Camel.

You can choose to either add Camel to your existing web services app, or you can let Camel do the work, and drive the whole REST thing.

However the most common ways of creating REST services in Camel are:

  • Integrating with JAX-RS: If you’ve already built a REST service with the JAX-RS specification (for example, using a framework like Apache CXF), then you can use Camel to implement the logic behind your web services.
  • Deploying a REST service as a Java servlet: This deploys your REST service using Camel’s servlet component, which means your service runs in a container like Tomcat or Wildfly.
  • Camel’s Restlet component: This is a Camel component for the Restlet framework for Java, which is a REST library in its own right. Restlet spins up its own internal web server to do this.

So how do you configure your REST service? You can use Camel’s REST DSL.

The REST DSL

Camel introduced a REST DSL in Camel 2.14. It’s an extension to Camel’s existing DSL, but specifically for describing REST services. It’s easy to write and configure.

rest("/api/customers")
    .post().to("file:output/customers");

The REST DSL is like syntactic sugar on top of the other components listed above. It makes it easy to create REST services, without having to know too much of the underlying detail, or any complicated wiring.

It sits on top of other components that actually host your REST service. You don’t need to worry about those details for now, as Camel will set you up with most of the defaults.

The REST DSL is a good place to start when creating new REST services in Camel. So let’s have a look at how you set it up.

Example - Creating a RESTful service in Camel using Restlet, and the REST DSL

In the following steps you’re going to create a RESTful service in Camel, using the REST DSL. Underneath it’s going to use Restlet to actually provide the REST service.

  1. Create a new Camel project.

  2. In your Maven POM, add camel-restlet as a dependency.

    <dependency>
      <groupId>org.apache.camel</groupId>
      <artifactId>camel-restlet</artifactId>
      <!-- Also define the Camel version here if you need to -->
    </dependency>
    
  3. In the RouteBuilder of your new project, add a restConfiguration() element.

    This initialises the component that will provide your REST service. We do this first before defining any endpoints for the service.

    In this example we’re using the Restlet framework to implement the service.

    Wherever you define your Camel routes, add a restConfiguration instruction:

    Java DSL

    public void configure() throws Exception {
        restConfiguration()
            .component("restlet")
            .host("localhost").port("8080");
        // Endpoints will be defined here
    }
    

    XML DSL

    <camelContext xmlns="http://camel.apache.org/schema/spring">
        <restConfiguration component="restlet"
                           host="localhost" port="8080"/>
        <!-- Endpoints will be defined here -->
    </camelContext>
    

    As you can see, this service is going to be hosted on localhost, port 8080.

  4. Define a REST endpoint, and add skeletons for each of your operations - GET, POST, etc.

    First, define a REST endpoint, using rest, with the path (URI) of your service. Then append each of your operations - these are your HTTP verbs.

    The syntax for a REST verb/operation looks just like a familiar Camel route. However, instead of from, we start each operation with the HTTP verb you want to use, such as get, post and delete.

    Like this:

    Java DSL

    rest("/api/customers")
        .get().to("...")
        .post().to("...")
        .delete().to("...");
    

    XML DSL

    <rest path="/api/customers">
        <get>
            <to uri="..."/>
        </get>
        <post>
            <to uri="..."/>
        </post>
        <delete>
            <to uri="..."/>
        </delete>
    </rest>
    

    A note about REST HTTP verbs - Remember that REST architecture encourages the use of HTTP verbs to describe the action you’re taking on a resource. See the end of this article for a quick guide on which verb should be used when.

  5. Now build your Camel routes for your REST operations. Here’s an example of a REST service that’s been filled out:

    Java DSL

    rest("/customers")
        .get().to("bean:customerService?method=listCustomers")
        .post().to("jms:queue:CUSTOMERS");
    

    XML DSL

    <rest path="/customers">
        <get>
            <to uri="bean:customerService?method=listCustomers"/>
        </get>
        <post>
            <to uri="direct:post"/>
        </post>
    </rest>
    

    As you can see, the GET operation passes the request to be serviced by a bean, customerService. But the POST operation passes the request to a Direct component, direct:post.

  6. That’s it! Now keep building up your REST API with as many endpoints and operations as you need.

Getting parameters

At some point your REST API will need to accept parameters. It’s easy to do this, whether you’re taking parameters in the URL, or in the query string.

URL parameters

When you need to read a parameter from the URL – like a Customer ID, or Product ID – then you need to:

  • Define a placeholder in the URI of your operation, e.g. /customers/{id}
  • Fetch your variable later from a Header of the same name - e.g. ${header.id}

Here’s a full example - a REST delete operation which takes a customer ID. The parameter {id} is declared in the uri - e.g. /customers/12345. It can then be retrieved using ${header.id}:

Java DSL

rest("/customers")
    .delete("{id}").to("bean:customer?method=delete(${header.id})");

XML DSL

<rest path="/customers">
    <delete uri="{id}">
        <to uri="bean:customer?method=delete(${header.id})"/>
    </delete>
</rest>

In this example, I could implement a method like this in my customer bean, which would use my id value:

public String delete(String id) {
    // Your code would get the `id` value here
    return "Deleting customer " + id;
}

Query string parameters

Reading query string parameters is very similar to reading parameters inside a URI path.

To read a parameter from the query string (for example, from a GET request):

  • Define a placeholder in the URI of your operation, in query string format - e.g. /search?city={city}
  • Fetch your variable later from a Header of the same name - e.g. ${header.city}

Here’s an example of a REST GET operation which takes parameters in the query string. The query string parameter {city} is declared in the uri - e.g. /search?city=London. It can then be retrieved using ${header.city}:

Java DSL

rest("/api/apartments")
    .get("/search?country={country}")
    .to("bean:searchBean?method=byCountry(${header.country})");

XML DSL

<rest path="/api/apartments">
    <get uri="/search?country={country}">
        <to uri="bean:searchBean?method=byCountry(${header.country})"/>
    </get>
</rest>

Full working demo

Want to see a fully-functioning demo REST service, implemented in Camel? Click on the button below to see a full example:

Get the example code on GitHub

Comments? Please leave your thoughts below!

Leave a Comment

You can use Markdown in your comment. To write code, indent lines by 4 spaces.