Rest just got easy

As of version 2.14 camel supports an easy alternative for the implementation of rest interfaces, RedHat implemented it in Fuse 6.2 You can now use the rest DSL as an alternative for CXFRS. This means you no longer have to define the interface in a separate class. With the rest DSL you can specify the interface definition inside the route builder itself. This means that you can link your rest interface directly to your camel route implementation. No extra injection etc. is required. You can have a rest interface up and running in just a few easy steps. In this blog post I will describe these steps and some extra options you might find useful.

The code I use in the examples can be found here. I have used blueprint in combination with the java DSL.

The rest DSL is similar to the standard DSL you use when defining your camel routes. The configuration globally consists out of two factors. First there is the rest configuration.
In the configuration part you tell which Camel component you want to use to host your rest service. This component will handle the actual rest transportation. For my example I used the jetty component.

Besides the camel component you have to configure some other stuff. The most important ones are listed below:
• host – the location on which the endpoint needs to be hosted;
• port – the port on which the endpoint is hosted;
• bindingmode – dictates the way the input of the rest calls is binded / mapped. Here you can specify that a post method with a specific type must be cast to the corresponding pojo. In my example I set it to JSON. This means that the JSON input is mapped to the pojo automatically.

restConfiguration()
	.component("jetty")
	.host("localhost")
	.port(9091)
	.dataFormatProperty("prettyPrint", "true")
	.bindingMode(RestBindingMode.json);

The second part of the rest configuration is the interface definition. Here you will see the biggest advantage when using the rest DSL.

Normally you start a camel route with a simple “from()”, using the rest DSL you start with “rest()”.

The first thing you can set in the interface is the path on which your interface can be found. After that you can define your methods. The rest DSL supports the standard rest methods (post, get, delete etc.)

rest("/restDsl/")
	.get("/getOperation/{id}").id("getOperationRest").to("direct:getOperation")
	.post("/postOperatoin").id("postOperationRest").type(OrderInputPojo.class).to("direct:postOperation");

from("direct:getOperation").routeId("getOperation")
	.log("body: ${header.id}"
	.processRef("orderInputProcessor");

When defining a post operation you have the possibility to define the input type. By setting the POJO as the input type you can automatically cast (bindingmode) the input (json or XML) to the POJO class.

When defining an operation you have two options. You can either use the route functionality inside your rest definition or you can use the to() method to call another route. By calling another route you separate your interface definition from the orchestration which keeps your code clean.

References:
Camel RestDSL documentation

Calling a Soap Service with camel

Invoking a SOAP service in Fuse (camel) is similar to exposing a SOAP service. The first steps are the same, you have to create a CXF endpoint. This is explained in full in this blogpost.

You first generate the source classes based on the WSDL. After that you register it as a CXF endpoint in (in my case) the blueprint file of your project. The main difference is that you need to specify the address / endpoint of service.

<cxf:cxfEndpoint id="newOrderEndpoint"  
address="http://localhost:8088/mockNewOrder" 
serviceClass="nl.rubix.service.neworder.NewOrderServiceOperationsPortType"/>

Calling the service from your route can be done by simply setting the CXF endpoint in your “to” statement.

.to("cxf:bean:theRefToYourCXFBean")

If you would now call the service, CXF would choose the first operation in the WDSL. So we have to tell CXF which operation it needs to call. This is done by setting the header “OperationName”. This header will tell CXF to call the operation you want.

.setHeader("OperationName", simple("getTheSpecialOrder"))

The last part is creating the body for the request message. One way to do this is in a processor. In my case the code looks like this:

ObjectFactory objFac = new ObjectFactory();
GetTheSpecialOrderRequest requestMsg = objFac.createGetTheSpecialOrderRequest();
requestMsg.setOrderNumber(BigInteger.valueOf(123));
exchange.getOut().setBody(requestMsg);		

If everything is set correctly you should be able to call the service. In order to test it properly I created a mockserver in SoapUI. Which is included in the sources of this project (project sources).