== REST DSL Component

*Available as of Camel version 2.16*

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-component,Rest>> endpoints as
consumers for Camel routes. The actual REST transport is leveraged by
using Camel REST components such
as <<restlet-component,Restlet>>, <<restlet-component,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.

* <<netty-http-component,camel-netty-http>> (also
supports Swagger Java)
* <<netty4-http-component,camel-netty4-http>> (also
supports Swagger Java)
* <<jetty-component,camel-jetty>> (also
supports Swagger Java)
* <<restlet-component,camel-restlet>> (also
supports Swagger Java)
* <<servlet-component,camel-servlet>> (also
supports Swagger Java)
* <<spark-rest-component,camel-spark-rest>> (also
supports Swagger Java from Camel 2.17 onwards)
* <<undertow-component,camel-undertow>> (also
supports Swagger Java from Camel 2.17 onwards)

=== 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:

[source,java]
----
protected RouteBuilder createRouteBuilder() throws Exception {
    return new RouteBuilder() {
        @Override
        public void configure() throws Exception {
            rest("/say")
                .get("/hello").to("direct:hello")
                .get("/bye").consumes("application/json").to("direct:bye")
                .post("/bye").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:

[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Base Path |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.

=== 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:

[source,xml]
----
<camelContext xmlns="http://camel.apache.org/schema/spring">
  <rest path="/say">
    <get uri="/hello">
      <to uri="direct:hello"/>
    </get>
    <get uri="/bye" consumes="application/json">
      <to uri="direct:bye"/>
    </get>
    <post uri="/bye">
      <to uri="mock:update"/>
    </post>
  </rest>
  <route>
    <from uri="direct:hello"/>
    <transform>
      <constant>Hello World</constant>
    </transform>
  </route>
  <route>
    <from uri="direct:bye"/>
    <transform>
      <constant>Bye World</constant>
    </transform>
  </route>
</camelContext>
----

=== 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:

[source,java]
----
rest("/customers/")
    .get("/{id}").to("direct:customerDetail")
    .get("/{id}/orders").to("direct:customerOrders")
    .post("/neworder").to("direct:customerNewOrder");
----

And using XML DSL it becomes:

[source,xml]
----
<rest path="/customers/">
  <get uri="/{id}">
    <to uri="direct:customerDetail"/>
  </get>
  <get uri="/{id}/orders">
    <to uri="direct:customerOrders"/>
  </get>
  <post uri="/neworder">
    <to uri="direct:customerNewOrder"/>
  </post>
</rest>
----

TIP:The REST DSL will take care of duplicate path separators when using base
path and uri templates. In the example above the rest base path ends
with a slash ( / ) and the verb starts with a slash ( / ). But Apache
Camel will take care of this and remove the duplicated slash.

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:

[source,xml]
----
<rest>
  <get uri="/customers/{id}">
    <to uri="direct:customerDetail"/>
  </get>
  <get uri="/customers/{id}/orders">
    <to uri="direct:customerOrders"/>
  </get>
  <post uri="/customers/neworder">
    <to uri="direct:customerNewOrder"/>
  </post>
</rest>
----

=== Using Dynamic To in Rest DSL

*Available as of Camel 2.16*

The Rest DSL supports the new .toD <toD> as dynamic
to in the rest-dsl. For example to do a request/reply
over <<jms-component,JMS>> where the queue name is dynamic defined

[source,java]
----
 public void configure() throws Exception {
   rest("/say")
     .get("/hello/{language}").toD("jms:queue:hello-${header.language}");
}
----

=== And in XML DSL

[source,xml]
----
<rest uri="/say">
  <get uri="/hello//{language}">
    <toD uri="jms:queue:hello-${header.language}"/>
  </get>
<rest>
----

See more details at Message Endpoint about
the dynamic to, and what syntax it supports. By default it uses
the <<simple-language,Simple>> language, but it has more power than so.

=== 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:

[source,java]
----
protected RouteBuilder createRouteBuilder() throws Exception {
    return new RouteBuilder() {
        @Override
        public void configure() throws Exception {
            rest("/say/hello")
                .get().route().transform().constant("Hello World");
            rest("/say/bye")
                .get().consumes("application/json").route().transform().constant("Bye World").endRest()
                .post().to("mock:update");
    };
}
----

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.

=== Configuring route options

In the embedded route you can configure the route settings such as
routeId, autoStartup and various other options you can set on routes
today.

[source,java]
----
.get()
  .route().routeId("myRestRoute").autoStartup(false)
  .transform().constant("Hello World");
----


=== 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:

[width="100%",cols="10%,90%",options="header",]
|===
|Binding Mode |Description

|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. See the INFO box below for more details.

|xml |Binding to/from xml is enabled, and requires `camel-jaxb` on the
classpath. See the INFO box below for more details.

|json_xml |Binding to/from json and xml is enabled and requires both data formats to
be on the classpath. See the INFO box below for more details.
|===

TIP: From *Camel 2.14.1* onwards when using camel-jaxb for xml bindings, then
you can use the option `mustBeJAXBElement` to relax the output message
body must be a class with JAXB annotations. You can use this in
situations where the message body is already in XML format, and you want
to use the message body as-is as the output type. If that is the case,
then set the dataFormatProperty option `mustBeJAXBElement` to `false`
value.

NOTE: From *Camel 2.16.3* onwards the binding from POJO to JSon/JAXB will only
happen if the `content-type` header includes the
word `json` or `xml` representatively. This allows you to specify a
custom content-type if the message body should not attempt to be
marshalled using the binding. For example if the message body is a
custom binary payload etc.

To use binding you must include the necessary data formats on the
classpath, such as `camel-jaxb` and/or `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

[source,java]
----
restConfiguration().component("restlet").host("localhost").port(portNum).bindingMode(RestBindingMode.auto);
----

And in XML DSL

[source,xml]
----
<restConfiguration bindingMode="auto" component="restlet" port="8080"/>
----

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. 

[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Message Body |Direction |Binding Mode |Message Body

|XML |Incoming |auto,
xml,
json_xml |POJO

|POJO |Outgoing |auto,
xml, json_xml |XML

|JSON |Incoming |auto,
json,
json_xml |POJO

|POJO |Outgoing |auto,
json,
json_xml |JSON
|===
 
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:

[source,java]
----
// configure to use restlet on localhost with the given port
// and enable auto binding mode
restConfiguration().component("restlet").host("localhost").port(portNum).bindingMode(RestBindingMode.auto);

// use the rest DSL to define the rest services
rest("/users/")
    .post().type(UserPojo.class)
        .to("direct:newUser");
----

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:

[source,java]
----
// configure to use restlet on localhost with the given port
// and enable auto binding mode
restConfiguration().component("restlet").host("localhost").port(portNum).bindingMode(RestBindingMode.auto);

// use the rest DSL to define the rest services
rest("/users/")
    .post().type(UserPojo.class).outType(CountryPojo.class)
        .to("direct:newUser");
----

To specify input and/or output using an array, append `[]` to the end
of the canonical class name as shown in the following Java DSL:

[source,java]
----
// configure to use restlet on localhost with the given port
// and enable auto binding mode
restConfiguration().component("restlet").host("localhost").port(portNum).bindingMode(RestBindingMode.auto);

// use the rest DSL to define the rest services
rest("/users/")
    .post().type(UserPojo[].class).outType(CountryPojo[].class)
        .to("direct:newUser");
----

The `UserPojo` is just a plain pojo with getter/setter as shown:

[source,java]
----
public class UserPojo {
    private int id;
    private String name;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
----

The `UserPojo` only supports json, as XML requires to use JAXB
annotations, so we can add those annotations if we want to support XML
also

[source,java]
----
@XmlRootElement(name = "user")
@XmlAccessorType(XmlAccessType.FIELD)
public class UserPojo {
    @XmlAttribute
    private int id;
    @XmlAttribute
    private String name;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
----

By having the JAXB annotations the POJO supports both json and xml
bindings.

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.

 

=== Enabling or disabling Jackson JSON features

*Available as of Camel 2.15*

When using JSON binding you may want to turn specific Jackson features
on or off. For example to disable failing on unknown properties (eg json
input has a property which cannot be mapped to a POJO) then configure
this using the dataFormatProperty as shown below:

[source,java]
----
restConfiguration().component("jetty").host("localhost").port(getPort()).bindingMode(RestBindingMode.json)
   .dataFormatProperty("json.in.disableFeatures", "FAIL_ON_UNKNOWN_PROPERTIES");
----

You can disable more features by separating the values using comma, such
as:

[source,java]
----
.dataFormatProperty("json.in.disableFeatures", "FAIL_ON_UNKNOWN_PROPERTIES,ADJUST_DATES_TO_CONTEXT_TIME_ZONE");
----

Likewise you can enable features using the enableFeatures such as:

[source,java]
----
restConfiguration().component("jetty").host("localhost").port(getPort()).bindingMode(RestBindingMode.json)
   .dataFormatProperty("json.in.disableFeatures", "FAIL_ON_UNKNOWN_PROPERTIES,ADJUST_DATES_TO_CONTEXT_TIME_ZONE")
   .dataFormatProperty("json.in.enableFeatures", "FAIL_ON_NUMBERS_FOR_ENUMS,USE_BIG_DECIMAL_FOR_FLOATS");
----

The values that can be used for enabling and disabling features on
Jackson are the names of the enums from the following three Jackson
classes

* com.fasterxml.jackson.databind.SerializationFeature
* com.fasterxml.jackson.databind.DeserializationFeature
* com.fasterxml.jackson.databind.MapperFeature

The rest configuration is of course also possible using XML DSL

[source,xml]
----
<restConfiguration component="jetty" host="localhost" port="9090" bindingMode="json">
  <dataFormatProperty key="json.in.disableFeatures" value="FAIL_ON_UNKNOWN_PROPERTIES,ADJUST_DATES_TO_CONTEXT_TIME_ZONE"/>
  <dataFormatProperty key="json.in.enableFeatures" value="FAIL_ON_NUMBERS_FOR_ENUMS,USE_BIG_DECIMAL_FOR_FLOATS"/>
</restConfiguration>
----

=== Default CORS headers

*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.

[width="100%",cols="50%,50%",options="header",]
|===
|Key |Value

|Access-Control-Allow-Origin |*

|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

|Access-Control-Max-Age |3600
|===
 
=== 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:

[source,java]
----
restConfiguration().component("restlet").host("localhost").port(portNum).bindingMode(RestBindingMode.json);
// use the rest DSL to define the rest services
rest("/users/")
    .post("lives").type(UserPojo.class).outType(CountryPojo.class)
        .route()
            .choice()
                .when().simple("${body.id} < 100")
                    .bean(new UserErrorService(), "idToLowError")
                .otherwise()
                    .bean(new UserService(), "livesWhere");
----

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:

[source,java]
----
public class UserErrorService {
    public void idToLowError(Exchange exchange) {
        exchange.getIn().setBody("id value is too low");
        exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "text/plain");
        exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, 400);
    }
}
----

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:

[source,java]
----
onException(JsonParseException.class)
    .handled(true)
    .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(400))
    .setHeader(Exchange.CONTENT_TYPE, constant("text/plain"))
    .setBody().constant("Invalid json data");
----

=== Query Parameter default Values

You can specify default values for parameters in the rest-dsl, such as
the verbose parameter below:

[source,java]
----
  rest("/customers/")
      .get("/{id}").to("direct:customerDetail")
      .get("/{id}/orders")
        .param().name("verbose").type(RestParamType.query).defaultValue("false").description("Verbose order details").endParam()
          .to("direct:customerOrders")
      .post("/neworder").to("direct:customerNewOrder");
----

From *Camel 2.17* onwards then the default value is automatic set as
header on the incoming Camel `Message`. So if the call
the `/customers/id/orders` do not include a query parameter with
key `verbose` then Camel will now include a header with key `verbose`
and the value `false` because it was declared as the default value. This
functionality is only applicable for query parameters.

=== Integrating 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.

=== Swagger API

The Rest DSL supports Swagger Java by
the `camel-swagger-java` module. See more details at
 Swagger and the `camel-swagger-java` example
from the Apache Camel distribution.

From *Camel 2.16* onwards you can define each parameter fine grained
with details such as name, description, data type, parameter type and so
on, using the <param>. For example to define the id path parameter you
can do as shown below:

[source,xml]
----
<!-- this is a rest GET to view an user by the given id -->
<get uri="/{id}" outType="org.apache.camel.example.rest.User">
  <description>Find user by id</description>
  <param name="id" type="path" description="The id of the user to get" dataType="int"/>
  <to uri="bean:userService?method=getUser(${header.id})"/>
</get>
----

And in Java DSL

[source,java]
----
.get("/{id}").description("Find user by id").outType(User.class)
    .param().name("id").type(path).description("The id of the user to get").dataType("int").endParam()
    .to("bean:userService?method=getUser(${header.id})")
----

The body parameter type requires to use body as well for the name. For
example a REST PUT operation to create/update an user could be done as:

[source,xml]
----
<!-- this is a rest PUT to create/update an user -->
<put type="org.apache.camel.example.rest.User">
  <description>Updates or create a user</description>
  <param name="body" type="body" description="The user to update or create"/>
  <to uri="bean:userService?method=updateUser"/>
</put>
----

And in Java DSL

[source,java]
----
.put().description("Updates or create a user").type(User.class)
    .param().name("body").type(body).description("The user to update or create").endParam()
    .to("bean:userService?method=updateUser")
----

==== Vendor Extensions

The generated API documentation can be configured to include vendor extensions (https://swagger.io/specification/#specificationExtensions)
which document the operations and definitions with additional information, such as class name of model classes, camel context id and route id's.
This information can aid developers and during trouble shooting. However at production usage you may wish to not have this turned
on to avoid leaking implementation details into your API docs.

The vendor extension information is stored in the API documentation with keys starting with `x-`.

NOTE: Not all 3rd party API gateways and tools supports vendor-extensions when importing your API docs.

The vendor extensions can be turned on `RestConfiguration` via the `apiVendorExtension` option:

[source,java]
----
restConfiguration()
    .component("servlet")
    .bindingMode(RestBindingMode.json)
    .dataFormatProperty("prettyPrint", "true")
    .apiContextPath("api-doc")
    .apiVendorExtension(true)
        .apiProperty("api.title", "User API").apiProperty("api.version", "1.0.0")
        .apiProperty("cors", "true");
----

And in XML DSL:
[source,xml]
----
 <restConfiguration component="servlet" bindingMode="json"
                       apiContextPath="api-docs"
                       apiVendorExtension="true">

      <!-- we want json output in pretty mode -->
      <dataFormatProperty key="prettyPrint" value="true"/>

      <!-- setup swagger api descriptions -->
      <apiProperty key="api.version" value="1.0.0"/>
      <apiProperty key="api.title" value="User API"/>

</restConfiguration>
----