Rest DSL
Available as of Camel 2.14
Apache Camel offers a REST styled DSL which can be used with Java or XML. The intention is to allow end users to define REST services using a REST style with verbs such as get, post, delete etc.
How it works
The Rest DSL is a facade that builds Rest endpoints as consumers for Camel routes. The actual REST transport is leveraged by using Camel REST components such as Restlet, Spark-rest, and others that has native REST integration.
Rest DSL with Java
To use the Rest DSL in Java then just do as with regular Camel routes by extending the RouteBuilder
and define the routes in the configure
method.
A simple REST service can be define as follows, where we use rest() to define the services as shown below:
protected RouteBuilder createRouteBuilder() throws Exception { return new RouteBuilder() { @Override public void configure() throws Exception { rest("/say/hello") .get().to("direct:hello"); rest("/say/bye") .get().consumes("application/json").to("direct:bye") .post().to("mock:update"); from("direct:hello") .transform().constant("Hello World"); from("direct:bye") .transform().constant("Bye World"); } }; }
This defines a REST service with the following url mappings:
Uri template | Verb | Consumes |
---|---|---|
/say/hello | get | all |
/say/bye | get | application/json |
/say/bye | post | all |
Notice that in the REST service we route directly to a Camel endpoint using the to(). This is because the Rest DSL has a short-hand for routing directly to an endpoint using to(). An alternative is to embed a Camel route directly using route() - there is such an example further below.
The example below defines a single REST service which offers a GET operation that accepts 3 different types: plain text, json, and xml.
public class MySparkRouteBuilder extends RouteBuilder { @Override public void configure() throws Exception { // configure we want to use spark-rest as the component for the rest DSL restConfiguration().component("spark-rest"); // use the rest DSL to define rest services, and use embedded routes rest("/hello/{me}") .get().consumes("text/plain") .route() .to("log:input") .transform().simple("Hello ${header.me}").endRest() .get().consumes("application/json") .route() .to("log:input") .transform().simple("{ \"message\": \"Hello ${header.me}\" }").endRest() .get().consumes("text/xml") .route() .to("log:input") .transform().simple("<message>Hello ${header.me}</message>"); } }
To define the REST services we use the rest
method, where we can setup the path, which is "/hello/{me}". Where me refers the a wildcard that is mapped to Camel message header with the same key. Notice how we can refer to this header in the embedded Camel routes where we do message transformation. And because we used embedded routes, we need to define this using .route(), and to denote the end of the route, we use .endRest() to go back to the Rest DSL, where we can then add the 2nd, and 3rd get service.
Routes
Camel supports the definition of routing rules using a Java DSL (domain specific language) which avoids the need for cumbersome XML using a RouteBuilder.
For example a simple route can be created as follows.
RouteBuilder builder = new RouteBuilder() { public void configure() { errorHandler(deadLetterChannel("mock:error")); from("direct:a").to("direct:b"); } };
As you can see from the above Camel uses URIs to wire endpoints together.
URI String formatting
Available as of Camel 2.0
If you have endpoint URIs that accept options and you want to be able to substitute the value, e.g. build the URI by concat the strings together, then you can use the java.lang.String.format
method. But in Camel 2.0 we have added two convenient methods in the Java DSL so you can do fromF
and toF
that uses String formatting to build the URI.
from("direct:start").toF("file://%s?fileName=%s", path, name); fromF("file://%s?include=%s", path, pattern).toF("mock:%s", result);
Filters
You can combine simple routes with filters which can be arbitrary Predicate implementations.
RouteBuilder builder = new RouteBuilder() { public void configure() { errorHandler(deadLetterChannel("mock:error")); from("direct:a") .filter(header("foo").isEqualTo("bar")) .to("direct:b"); } };
Choices
With a choice you provide a list of predicates and outcomes along with an optional default otherwise clause which is invoked if none of the conditions are met.
RouteBuilder builder = new RouteBuilder() { public void configure() { errorHandler(deadLetterChannel("mock:error")); from("direct:a") .choice() .when(header("foo").isEqualTo("bar")) .to("direct:b") .when(header("foo").isEqualTo("cheese")) .to("direct:c") .otherwise() .to("direct:d"); } };
Using a custom processor
Here is an example of using a custom Processor
myProcessor = new Processor() { public void process(Exchange exchange) { log.debug("Called with exchange: " + exchange); } }; RouteBuilder builder = new RouteBuilder() { public void configure() { errorHandler(deadLetterChannel("mock:error")); from("direct:a") .process(myProcessor); } };
You can mix and match custom processors with filters and choices.
RouteBuilder builder = new RouteBuilder() { public void configure() { errorHandler(deadLetterChannel("mock:error")); from("direct:a") .filter(header("foo").isEqualTo("bar")) .process(myProcessor); } };