Monday, March 12, 2012

A Generic Pass-Through Route to solve a variety of Integration Challenges

Have you have ever needed to write a proxy (pass-through) route? This scenario applies to situations where you receive an HTTP request from a client, and simply need to redirect that HTTP request to another back-end server, returning the response from back end to the original client.

You might want to add some custom processing  or transformation to the message (or not) before sending to the back end service. Camel makes it easy to add such custom processing. I’ve seen cases where the simple ability to log and provide a “point of record” was enough to warrant the use of a pass-through route.  Another use for a pass-through would be to “fix” a request message  (so that it contains expected payload) before sending it on to the server – or manipulating a response into a suitable format for the client.  You can imagine a pass-through route that doesn’t touch requests coming from newer clients, but that can update requests (on the fly) that come from legacy clients so that those messages adhere to newer version, and eliminate need to maintain older back end server. 

So now that we’ve established the usefulness of a pass-through pattern – I will show you an easy way to implement this pattern. Apache Camel makes it very easy to write a route that implements the pass-through pattern. Here I will descried the steps of to create such a pass-through route is just a matter of minutes. You can create a new FUSE Project using the FUSE IDE. You can download FUSE IDE from here:

Once installed, FUSE IDE will allow you to easily create any type of route.

Below is the spring configuration that implements the proxy route.



<beans xmlns="http://www.springframework.org/schema/beans"

       xmlns:camel="http://camel.apache.org/schema/spring" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xsi:schemaLocation="        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd        http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">



       <camelContext xmlns="http://camel.apache.org/schema/spring">

              <route>

                     <from uri="jetty:http://0.0.0.0:5012/proxy/incoming" />

                     <to uri="log:com.fusesource.proxytest?level=DEBUG&amp;showAll=true&amp;multiline=true&amp;showBody=true" />

                     <removeHeaders pattern="CamelHttp*"/>

                     <removeHeader headerName="Host"/>

       

                     <to uri="jetty:http://localhostt:3000/myservice/send" />

              </route>

       </camelContext>



</beans>

From the example, you can see the incoming component is the camel jetty. The Outgoing is also camel jetty.

The reason for the “removeHeaders” is basically to remove all the CamelHttp* headers that get populated by the incoming camel jetty consumer. Because certain headers get automatically populated and retained as the exchange passes through the route, the existence of these headers could potentially confuse and impact the behavior of the outgoing camel jetty producer. When certain headers are not removed, The outgoing jetty producer component (that sends requests to back end) gets confused, potentially over-riding the value configured for destination URL,  and you can end up with unexpected value for actual endpoint destination URL used by consumer component. Take care with these CamelHttp* headers and my advice is remove them in routes that go from jetty consumer to  jetty producer.  The basic idea is explained here:


You may be tempted to use the Camel HTTP component (camel-http) rather than 'jetty' for calling the back end in your pass-through route. The 'jetty' producer component has better performance under load, so it is almost always the right choice for this pattern.

The Jetty HTTP client endpoint uses the Jetty library to implement a HTTP client. In particular, the Jetty HTTP client features support for HttpClient thread pool and non-blocking request/response.  See more info on benefits of the Camel 'jetty' producer component in the FUSE documentation for writing a pass-through route .

I’m attaching a working example. If you want to play with working code - you can download it from here.
The the following sub-projects:
proxytest - A maven project that implements the route. To build run 'mvn install'. To run the route in standalone mode you can type 'mvn camel:run'.

mockservice - A simple mock server that mimics a real back end service. Your pass-through route can use this to redirect requests to in the absence of a real back end service. To build type 'mvn install'. To run the mock service in standalone mode you can type 'mvn camel:run'.

Included, is a sample SOAP UI client project (see proxytest\proxy-test-soapui-project.xml) that you can import into SOAP UI, and use to send HTTP request into the route. The route will receive the request on port 5012, redirect to the mock service listening on port 3000. The mock service will simply echo back the request. The route will then return the response back to the original SOAP UI client.  You can use SOAP UI to perform load tests on your new proxy service!

No comments:

Post a Comment