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/

Reply via email to