The geekier side of Riff Pie

Groovy HTTP with Camel

So I’ve been working on an ActiveMQ load-test harness – written entirely in Groovy, fact fans – on and off for a while, and today started exposing some simple admin tasks over HTTP. I used Groovy dynamic method names to some neat effect, and making it simple to add new functionality to with little effort. Here’s what I did, with specifics left out of course.

First, the camel route and relevant Spring stuff, expressed in Camel’s XML DSL:

<beans>
 <camelContext>
  <route>
   <from uri="jetty:http://0.0.0.0:8234/admin"/>
    <process ref="httpProcessor"/>
  </route>
 
  <bean id="httpProcessor" class="com.riffpie.names.changed.protect.guilty.HttpProcessor"/>
 
</beans>

Pretty straightforward stuff. If you’re wondering why I chose XML as the DSL, there are a couple of reasons. Largely, I just seem to personally find it more expressive, but of mileage varies enormously on that one. Also, I’m used to using the XML DSL here, as we usually have multiple, country-specific configurations of Camel-based apps, and it’s worked out easier to configuration-manage XML to this end. Lastly, and this may well be something that’s been fixed, but in the version of Groovy we’re using here – 1.6.5, yes, I know – anonymous inner subclasses of actual classes simply didn’t work. Groovy interpreted them as implementations of interfaces. So extending RouteBuilder and such involved writing further top-level classes, and I simply couldn’t be bothered. It seemed a shame that Groovy actually made for more code than the equivalent Java, so I didn’t use it. So there you have it. On with the example. The neat bit is that HttpProcessor class, and how simple it is to extend:

import org.apache.camel.Exchange
import org.apache.camel.Processor
 
class HttpProcessor implements Processor {
 
  void process(Exchange exchange) {
    def action = exchange.in.getHeader("action")
    "$action"(exchange)
  }
 
  def listClients(ex) {
    ex.out.body = "list clients would be implemented here"
  }
 
  def stopClients(ex) {
    ex.out.body = "stop clients logic goes here"
  }
 
  def methodMissing(String name, args) {
    args[0].out.body = "couldn't do " + name
  }
 
}

So the client end simply sets an action=? header on the request, and this class takes the value, and using some Groovy magic,  invokes that method. If it doesn’t find it, I’ve overridden methodMissing with something that just responds with a “no chance, mate” message, and we’re done. Adding a new action is as simple as adding the appropriately-named method to the class, and let things work themselves out.

As an aside, I started out writing this class with a map of action-name – closures, but that left me with some clumsy old-fashioned conditional code for if there was no action provided, or an unknown one. I felt this alternative made for neater, more compact code, and ran with it.

Of course, this is just the application of the pattern that I happened to be using when I felt like blogging about dynamic method names. There are tons of possibilities for them.

Til next time, cya

Comments are closed.