Apache camel as default servlet on Tomcat
I have set my sights on learning Apache Camel to handle routing for web applications. I can’t say with any certainty that Apache Camel Servlet has the features needed for robust routing. It seems to only support routing based on the prefix of the path or by exact matches but that isn’t the problem I face today. I built my HelloWorld application using Tomcat embed, Spring, and Apache Camel and everything was going fine until I decided to set Apache Camel as the default Servlet and that is when Apache Camel Servlet decided to greet me with 404 page not found. If you have tried to run Apache Camel Servlet as the default servlet you have probably seen this before but I wasn’t ready to give up!
Why is it important to run Apache Camel Servlet as the default servlet? This is very important because it doesn’t make sense to allow Apache Camel to handle every request, especially when you may want it to only handle requests for resources that don’t exist. The problem is the Servlet Component wasn’t built to handle this for Tomcat which returns pathInfo of null when the servlet has been reached as a default servlet. When pathInfo is null you want to use the servletPath instead. After some digging I found that by extending CamelHttpTransportServlet, shadowing the consumers map, and overriding the service, resolve, connect, and disconnect methods I was able to use this custom Servlet to select the appropriate route when it was run as a default servlet. This didn’t solve all of the problems though, it only lead to a server 500 error.
The final problem to resolve was that the DefaultHttpBinding also don’t support execution from a default servlet on Tomcat. The binding sets the path to null from the pathInfo which eventually leads to a server 500 error. I was able to get around this issue also by extending the DefaultHttpBinding class and overriding the readRequest method. I built the readRequest to first call the original readRequest method and then if the pathInfo is null it sets the HTTP_PATH header from the servletPath. Finally I reconfigured my servlet routes to use this custom binding and everything worked!
Eventually I do plan on releasing the code as a library but right now I’m still learning the basics of Apache Camel. I’m also not in a very sharing mood right now after being banned by @cheeser on freenode’s #java channel for calling him out for trolling and abusing visitors to the channel. I brought the issue to freenode’s administration who basically said they wouldn’t do anything about it. Apparently freenode’s policies only apply to certain people, while others can break the rules at will. Freenode suggested I create my own channel, which I did, #java-alt, but when I attempted to help some people who were on #java and not getting assistance by inviting them to my newly created channel @cheeser set a permanent ban on me. In addition to banning me he also made numerous defamatory comments about me. I was waiting for the opportunity to file a lawsuit against him but I didn’t lose any clients behind it so there isn’t much I could sue for. It seems you will never again see me on #java on freenode and good luck getting help. I just want to warn you that they are quick to attack anyone that isn’t in their little clan. It isn’t just one person trolling either, the entire clan attacks new members like a pack of wolves. I’m too busy to be on freenode all of the time but when I am you can find me at #java-alt. If you happen to stop by #java on freenode tell @cheeser hello for me! Now back to business.
I have only crossed the first bridge in Apache Camel and have many more bridges to cross. The next project is to see if I can somehow route the message request to the Spring Web Servlet. I’m quite certain that Apache Camel wasn’t designed for this kind of funny-business but using a servlet as an endpoint makes a lot of sense and should make it possible to dynamically configure all endpoints using this one technology.