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/