torsdag 1 december 2011

Gotcha when using camel-servlet

In my current project I'm using Apache Camel for the integration, and I bumped into a significant "oups"-moment while using the camel-servlet component.

I found that while I had multiple applications (WAR's) deployed I often started the wrong routes, even though I was hitting the correct endpoint url.

Say i.e. that you have two application, A and B. Both of these has the same endpoint addresses, i.e. servlet:/myservice

The logical thing would be that you could reach application A through:
http://localhost/A/myservice

and B through:
http://localhost/B/myservice

Now imagine my surprise when requests for the A application would up in the route for B. It took me a while to figure this out, but here's the reason for this...

When you expose your routes through servlet's you are using the CamelHttpTransportServlet class. An example web.xml could be something like this:

<!-- Camel servlet -->
<servlet>
<servlet-name>CamelServlet</servlet-name>
<servlet-class>org.apache.camel.component.servlet.CamelHttpTransportServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<!-- Camel servlet mapping -->
<servlet-mapping>
<servlet-name>CamelServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>


Now, if you name your servlet the same for both applications you're actually only publishing one common servlet class. The camel servlet component does not take your context-root into account, which means that you hit the same endpoint irregardless whether you go to /A/myservice or /B/myservice. The one that gets hit is the one that was last deployed (or started).

Ok, easily fixed I thought... Just rename the servlet-name to something more unique for each application...
After that my routes where no longer reachable and I was just left with 404's each time I tried to hit the endpoints.
After some trial and error as well as googling I found out that if you rename your servlet from the default "CamelServlet" you *have* to specify the servlet name in your endpoint uri as well.
That is, the endpoint in application A would be i.e.:

servlet:/myService?servletName=AServlet

and B:

servlet:/myservice?servletName=BServlet

So, the lesson is:

- Always rename the camel servlet name, you never know which other applications will be deployed together on the same server. Your endpoints might clash with these and you'll have a mess figuring out why.

- Always include the servletName in your endpoint uri.

These tips should definitely be added to the documentation page to help others avoid making the same mistake.

'til next time!