I've seen quite a few Camel riders doing very similar things over the years; particularly in cases where teams are sharing routes with other team or folks want to wrap up 'protocols' as something thats a black box and easy to cookie-cut. The following is admittedly advanced usage but seems common enough to be a valid pattern I'd like to describe.
So I was chatting with a nice chap at the recent Paris FuseDay (sorry I forgot your name, if you're reading this please say Hi and I apologise for my lousy memory!). We were chatting about what he was doing and it started ringing lots of bells then on further reflection we came up with this idea... So often folks: * wrap up a number of routes into a protocol bean (say a RouteBuilder) and parameterize it with fields/properties so that the same 'shape' of route can be instantiated many times with just different values (e.g. the names of the queues change or whatever) * the protocol bean is then instantiated many times using, say, dependency injection * sometimes the protocols are totally stand alone as a black box - however quite often there are some public inputs and outputs for the black box. i.e. folks want to hide the internal implementation detail and routes inside the protocol - but want to expose the public inputs and outputs. Then others can compose the protocols into higher level protocols. For example if two teams create protocol A and protocol B then a different user might wish to route A and B together; without necessarily having to know all about the internal implementation detail of A and B along with whatever middleware was used etc. Basically this is just a description of composing new protocols out of existing protocols; not unlike Object Orientation where we can nest things together and have public interface versus private implementation and so forth. (I guess its not unlike the SCA concept of composing a hierarchy of assemblies though I've never been much of an SCA fan ;-). I was wondering how we can make it easier for the person wiring together A and B though; without having to dive inside the code of A and B to figure stuff out. e.g. often A and B just have a single input and output. Wouldn't it be nice to just do... from("a://output").to("b://input") where "input" and "output" are just logical names relative to the protocols A and B which then map to the actual physical implementation detail endpoints that the creators of A and B decided to choose. So think data hiding in OO and having logical alias names for things inside protocols. In the above using Camel terminology, we've just got A and B implemented as Camel Components which then act as a factory of endpoints (i.e. taking a logical endpoint name and returning the actual physical endpoint name that the protocol is using) Implementing Protocols ================= So the realisation we came to was, we just need to combine a protocol bean RouteBuilder and a Component into a single, simple bean that we use Dependency Injection to create and configure. i.e. a single RouteBuilder can also be a Component as well which can then expose its public endpoints. e.g. here's a strawman... /** * a simple protocol that does something but has a public * input and output endpoint if you wish to communicate with the protocol */ public class MyProtocol extends ProtocolBuilder { // variables injected.. private String input; private String output; protected void configure() { // lets expose the public endpoints alias("input", input); alias("output", input); // regular implementation detail routes go here... from(input). beanRef("foo", "bar"). to("foo:bar"). to(output); } // properties.... ... } Then folks could expose protocol A and B using Spring XML (these protocols don't have to be the same class BTW, just reusing it for brevity)... <bean id="a" class="MyProtocol"> <property name="input" value="activemq:Some.A.Input"/> <property name="output" value="activemq:Some.A.Output"/> </bean> <bean id="b" class="MyProtocol"> <property name="input" value="mq:BlahBlah"/> <property name="output" value="file:somethingOrOther"/> </bean> Then to route these two 'protocols' together we could refer to the public aliases (kinda like exported public methods in OO terms) via... from("a://output").to("b://input") (I kinda wanted to use the term "export" for these alias endpoints, but we use export in the DSL for exporting a service to an endpoint - the server side of "Spring Remoting" type stuff so didn't want to confuse folks with overusing the same term). So what does ProtocolBuilder do? Well its just a RouteBuilder extension which implements the "alias" methods. (Not 100% sure on the name "alias" yet). public abstract ProtocolBuilder alias(String logicalName, String physicalEndpointUri); public abstract ProtocolBuilder alias(String logicalName, Endpoint physicalEndpoint); Then it either needs to implement Component directly or have some kind of Type Converter to convert ProtocolBuilder to be a Component. The Component implementation just maps the logical endpoint name like "input" to whatever physical URI its using. The basic result is, protocol developers just have a slightly different base class then an easy way to expose logical endpoints. Then folks who assemble the protocols get to reuse simple logical URIs relative to the protocol instances; making the protocol appear a very simple protocol, hiding all the internal complexity (and protecting the higher order route from the lower level implementation details). Thoughts? -- James ------- http://macstrac.blogspot.com/ Open Source Integration http://fusesource.com/