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.
Components supporting Rest DSL
The following Camel components supports the Rest DSL. See the bottom of this page for how to integrate a component with the Rest DSL.
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
A simple REST service can be define as follows, where we use rest() to define the services as shown below:
This defines a REST service with the following url mappings:
|Base Path||Uri template||Verb||Consumes|
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.
Rest DSL with XML
The REST DSL supports the XML DSL also using either Spring or Blueprint. The example above can be define in XML as shown below:
Using base path
The REST DSL allows to define base path to make the DSL a bit more DRY. For example to define a customer path, we can set the base path in rest("/customer") and then provide the uri templates in the verbs, as shown below:
And using XML DSL it becomes:
It is not required to use both base path and uri templates. You can omit the bast path and define the base path and uri template in the verbs only. The example above can be defined as:
Embedding Camel routes
Each of the rest service becomes a Camel route, so in the first example we have 2 x get and 1 x post REST service, which each become a Camel route. And we have 2 regular Camel routes, meaning we have 3 + 2 = 5 routes in total.
There are two route modes with the Rest DSL
- mini using a singular to
- embedding a Camel route using route
The first example is using the former with a singular to. And that is why we end up with 3 + 2 = 5 total routes.
The same example could use embedded Camel routes, which is shown below:
In the example above, we are embedding routes directly in the rest service using .route(). Notice we need to use .endRest() to tell Camel where the route ends, so we can go back to the Rest DSL and continue defining REST services.
Managing Rest services
Each of the rest service becomes a Camel route, so in the first example we have 2 x get and 1 x post REST service, which each become a Camel route. This makes it the same from Camel to manage and run these services - as they are just Camel routes. This means any tooling and API today that deals with Camel routes, also work with the REST services.
This means you can use JMX to stop/start routes, and also get the JMX metrics about the routes, such as number of message processed, and their performance statistics.
There is also a Rest Registry JMX MBean that contains a registry of all REST services which has been defined.
Binding to POJOs using
The Rest DSL supports automatic binding json/xml contents to/from POJOs using Camels Data Format. By default the binding mode is off, meaning there is no automatic binding happening for incoming and outgoing messages.
You may want to use binding if you develop POJOs that maps to your REST services request and response types. This allows you as a developer to work with the POJOs in Java code.
The binding modes are:
|off||Binding is turned off. This is the default option.|
|auto||Binding is enabled and Camel is relaxed and support json, xml or both if the needed data formats are included in the classpath. Notice that if for example |
camel-jaxb is not on the classpath, then XML binding is not enabled.
|json||Binding to/from json is enabled, and requires a json capabile data format on the classpath. By default Camel will use |
json-jackson as the data format.
|xml||Binding to/from xml is enabled, and requires |
camel-jaxb on the classpath.
|json_xml||Biding to/from json and xml is enabled and requires both data formats to be on the classpath.|
To use binding you must include the necessary data formats on the classpath, such as
camel-jackson. And then enable the binding mode. You can configure the binding mode globally on the rest configuration, and then override per rest service as well.
To enable binding you configure this in Java DSL as shown below
And in XML DSL
When binding is enabled Camel will bind the incoming and outgoing messages automatic, accordingly to the content type of the message. If the message is json, then json binding happens; and so if the message is xml then xml binding happens. The binding happens for incoming and reply messages. The table below summaries what binding occurs for incoming and reply messages.
|Message Body||Direction||Binding Mode||Message Body|
When using binding you must also configure what POJO type to map to. This is mandatory for incoming messages, and optional for outgoing.
For example to map from xml/json to a pojo class
UserPojo you do this in Java DSL as shown below:
Notice we use
type to define the incoming type. We can optionally define an outgoing type (which can be a good idea, to make it known from the DSL and also for tooling and JMX APIs to know both the incoming and outgoing types of the REST services.). To define the outgoing type, we use
outType as shown below:
UserPojo is just a plain pojo with getter/setter as shown:
UserPojo only supports json, as XML requires to use JAXB annotations, so we can add those annotations if we want to support XML also
By having the JAXB annotations the POJO supports both json and xml bindings.
Configuring Rest DSL
The Rest DSL allows to configure the following options using a builder style
|component|| ||The Camel Rest component to use for the REST transport, such as restlet, spark-rest. If no component has been explicit configured, then Camel will lookup if there is a Camel component that integrates with the Rest DSL, or if a |
org.apache.camel.spi.RestConsumerFactory is registered in the registry. If either one is found, then that is being used.
|scheme||http||The scheme to use for exposing the REST service. Usually http or https is supported|
|hostname|| ||The hostname to use for exposing the REST service.|
|port|| ||The port number to use for exposing the REST service. Notice if you use servlet component then the port number configured here does not apply, as the port number in use is the actual port number the servlet component is using. eg if using Apache Tomcat its the tomcat http port, if using Apache Karaf its the HTTP service in Karaf that uses port 8181 by default etc. Though in those situations setting the port number here, allows tooling and JMX to know the port number, so its recommended to set the port number to the number that the servlet engine uses.|
|contextPath|| ||Sets a leading context-path the REST services will be using. This can be used when using components such as SERVLET where the deployed web application is deployed using a context-path.|
|restHostNameResolver||localHostName||If no hostname has been explicit configured, then this resolver is used to compute the hostname the REST service will be using. The resolver supports |
|bindingMode||off||Whether binding is in use. See further above for more details.|
|skipBindingOnCustomError||true||Camel 2.14.1: Whether to skip binding on output if there is a custom HTTP error code header. This allows to build custom error messages that do not bind to json / xml etc, as success messages otherwise will do. See further below for an example.|
|enableCORS||false||Camel 2.14.1: Whether to enable CORS headers in the HTTP response.|
|jsonDataFormat|| ||Name of specific json data format to use. By default |
json-jackson will be used. Important: This option is only for setting a custom name of the data format, not to refer to an existing data format instance. Notice: Currently Jackson is what we recommend and are using for testing.
|xmlDataFormat|| ||Name of specific XML data format to use. By default |
jaxb will be used. Important: This option is only for setting a custom name of the data format, not to refer to an existing data format instance. Notice: Currently only
jaxb is supported.
|componentProperty|| ||Allows to configure as many additional properties. This is used to configure component specific options such as for Restlet / Spark-Rest etc.|
|endpointProperty|| ||Allows to configure as many additional properties. This is used to configure endpoint specific options for Restlet / Spark-Rest etc.|
|consumerProperty|| ||Allows to configure as many additional properties. This is used to configure consumer specific options for Restlet / Spark-Rest etc.|
Allows to configure as many additional properties. This is used to configure the data format specific options. For example set property prettyPrint to true to have json outputted in pretty mode. From Camel 2.14.1 onwards the keys can be prefixed with either
to denote that the option is only for either JSON or XML data format, and only for either the in or the out going. For example a key with value "xml.out.mustBeJAXBElement" is only for the XML data format for the outgoing. A key without a prefix is a common key for all situations.
|corsHeaderProperty|| ||Allows to configure custom CORS headers.|
For example to configure to use the spark-rest component on port 9091, then we can do as follows
And with XML DSL
You can configure properties on these levels.
- component - Is used to set any options on the Component class. You can also configure these directly on the component.
- endpoint - Is used set any option on the endpoint level. Many of the Camel components has many options you can set on endpoint level.
- consumer - Is used to set any option on the consumer level. Some components has consumer options, which you can also configure from endpoint level by prefixing the option with "consumer."
- data format - Is used to set any option on the data formats. For example to enable pretty print in the json data format.
- cors headers - If cors is enabled, then custom CORS headers can be set. See below for the default values which are in used. If a custom header is set then that value takes precedence over the default value.
You can set multiple options of the same level, so you can can for example configure 2 component options, and 3 endpoint options etc.
Available as of Camel 2.14.1
If CORS is enabled then the follow headers is in use by default. You can configure custom CORS headers which takes precedence over the default value.
|Access-Control-Allow-Methods||GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, CONNECT, PATCH|
|Access-Control-Allow-Headers||Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers|
Defining a custom error message as-is
If you want to define custom error messages to be sent back to the client with a HTTP error code (eg such as 400, 404 etc.) then from Camel 2.14.1 onwards you just set a header with the key
Exchange.HTTP_RESPONSE_CODE to the error code (must be 300+) such as 404. And then the message body with any reply message, and optionally set the content-type header as well. There is a little example shown below:
In this example if the input id is a number that is below 100, we want to send back a custom error message, using the UserErrorService bean, which is implemented as shown:
In the UserErrorService bean we build our custom error message, and set the HTTP error code to 400. This is important, as that tells rest-dsl that this is a custom error message, and the message should not use the output pojo binding (eg would otherwise bind to CountryPojo).
Catching JsonParserException and returning a custom error message
From Camel 2.14.1 onwards you return a custom message as-is (see previous section). So we can leverage this with Camel error handler to catch JsonParserException, handle that exception and build our custom response message. For example to return a HTTP error code 400 with a hardcoded message, we can do as shown below:
Integration a Camel component with Rest DSL
Any Apache Camel component can integrate with the Rest DSL if they can be used as a REST service (eg as a REST consumer in Camel lingo). To integrate with the Rest DSL, then the component should implement the
org.apache.camel.spi.RestConsumerFactory. The Rest DSL will then invoke the
createConsumer method when it setup the Camel routes from the defined DSL. The component should then implement logic to create a Camel consumer that exposes the REST services based on the given parameters, such as path, verb, and other options. For example see the source code for camel-restlet, camel-spark-rest.
The Rest DSL supports Swagger by the
camel-swagger module. See more details at Swagger and the
camel-example-servlet-rest-tomcat example from the Apache Camel distribution.