Enterprise Integration Zone is brought to you in partnership with:

Billy is a Swedish consultant in the java space focusing on solving integration challenges. He started his career focusing on heavyweight IBM products but has since then switched over to open source alternatives. When he is not churning out code or instructing for his employer Redpill-Linpro he likes to spend his time home in the beautiful archipelago outside Stockholm with his fiancee Maria and their cat Zorro. Billy is a DZone MVB and is not an employee of DZone and has posted 9 posts at DZone. You can read more from them at their website. View Full User Profile

Gotcha When Using Camel-Servlet

04.20.2012
| 7985 views |
  • submit to reddit
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!
Published at DZone with permission of Billy Sjöberg, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Claus Ibsen replied on Sun, 2012/04/22 - 2:15am

Thanks for the gotcha. I have updated the servlet documentation at Apache, takes a while to sync the changes.

Brock Mills replied on Sun, 2012/04/22 - 8:02pm

Does anyone know what actually causes this behaviour? 

Like does Camel override the web app classloader and/or ask for the system classloader and if so why would this be a good idea? Especially if the effect of this is that you need to expose fairly low level implementation detail such as the name of the servlet as a part of the interface endpoint. 

Christian Schneider replied on Mon, 2012/04/23 - 2:20am

Normally this should not happen as each war has a separate classloader. There is one exception though. If you put camel jars in the shared libs of the container this behaviour could occur. Is that the case?

 In any case I considers that as a bug or possible improvement in camel and logged an issue https://issues.apache.org/jira/browse/CAMEL-5206

 Christian

 

Billy Sjöberg replied on Mon, 2012/04/23 - 6:12am in response to: Christian Schneider

You are absolutely right Christian, thats indeed the case.

What I've done is simply to collect the needed jar's and put it inside my appserver to keep my deployments small as I tend to get a lot of them. Apart from the reported issue above I've found no problems doing so.

Btw, big kudos to you, Claus and the whole Apache Camel community as I simply love the framework. In my view the simplicity and productivity puts the big traditional integration products in shame.

Claus Ibsen replied on Wed, 2012/04/25 - 12:29am

Whao putting JARs in the app server shared lib on its boot classpath is somewhat dangerous to do. I would definitly have put that information in the blog as its a very important detail. And at first read I could not believe if you did that, did not write that in the blog. And hence thought there was a problem with the Camel servlet. 

Claus Ibsen replied on Wed, 2012/04/25 - 8:44am

The ticket logged by Christian is an acknowledgement that there is a bug in the camel servet component, when you put the JARs in the application server shared lib.

If you do not do that, which is what the regular use cases would be, then there is no problem at all.

You can keep an eye on that ticket to see status of the bug fix. The Camel servlet documentation has been updated to warn about the issue with the shared JARs in the app server classpath.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.