On 19 October 2010 12:54, Willem Jiang <willem.ji...@gmail.com> wrote:
> On 10/19/10 6:06 PM, James Strachan wrote:
[snip]
>> 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")
>
> With this DSL, I don't think protocol-a's output is connect to the
> protocol-b's input automatically.
>
> Maybe we should override their input or output definition by looking up the
> position of these two protocols.


So the idea is the ProtocolBuilder implements the
Component.createEndpoint method
http://camel.apache.org/maven/camel-2.2.0/camel-core/apidocs/org/apache/camel/Component.html#createEndpoint(java.lang.String)

taking the "output" String and aliasing it to whatever real physical
endpoint the ProtocolBuilder decides to map it to via the
alias("output", something) method call. Its up to the ProtocolBuilder
implementation to decide how to map a physical endpoint to a logical
name.

i.e. the alias() method in this strawman creates the map of logical
names to physical endpoints used inside the routes; which can then be
used to resolve endpoint URIs within the protocol instances namespace.


>> (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.
>
> Maybe a ProtocolComponent can do this job, and the DSL could be
>
> from(protocol://a).to(protocol://b);

If there's only one input and output for protocols thats another
option; though I can imagine many protocols having multiple inputs or
outputs.

e.g. there might be a dead letter error output (e.g. like stdin /
stdout / stderr). Some protocols might have multiple inputs (e.g.
doing a BAM protocol to correlate messages together).

I guess having a protocol endpoint could just assume input and output
as the default endpoint names. Or maybe we could name the logical
endpoints within the protocols...

  from("protocol://a/input").to("protocol://b/output")

Though given how we need some API to look up in the RouteBuilder to
find the logical -> physical mappings, I figured it was easiest to
just add 1 new class which is-a RouteBuilder and is-a Component and so
knows how to do the URI mapping from public name -> physical endpoint
and can implement the alias() methods. It would also lead to simpler,
shorter URIs...

  from("a://input").to("b://output")

Then folks can instantiate as many instances of a ProtocolBuilder as
required - each instance getting its own scheme in Camel and so its
own logical set of endpoint names which map to a separate set of
physical endpoints.

Camel already binds a URI scheme to a bean if it can convert itself to
a Component; I figured protocols was a good use case of using that
same behaviour, leading to short concise URIs.

-- 
James
-------
http://macstrac.blogspot.com/

Open Source Integration
http://fusesource.com/

Reply via email to