On Wed, Oct 27, 2010 at 11:08 PM, kristofsajdak <[email protected]> wrote: > > Great feedback guys, much appreciated ! > > > jstrachan wrote: >> >> Agreed. If you kinda squint a bit and think of the route builders as >> 'objects' and you want to compose 2 different routes together with >> shared dependencies its a bit like 'constructors' and 'data hiding'. >> >> We have protocol A and B and we need to route the output of A to the >> input of B; so rather than B needing to know the implementation detail >> of A; we add a constructor parameter for B's input... >> >> class A extends ProtocolBuilder {...} >> >> class B extends ProtocolBuilder { >> public B(String inputUri) { ... } >> } >> >> // lets use Java code to simulate DI... >> ProtocolBuilder a = new A(); >> ProtocolBuilder b = new B(b.getOutputUri()); >> >> >> we've now wired A and B together without B knowing anything about the >> implementation detail of A. >> >> Its quite common for lots of protocols to be 'unix pipe-ish' with an >> input and output; so we could have helper classes where there's >> standard input/output endpoints like this to create a pipeline... >> >> CompositeProtocol composite = Protocols.pipeline(A.class, B.class, >> C.class); >> >> where A:out -> B:in and B:out -> C:in. Indeed that could return a new >> protocol; where composite:in maps to A:in and composite:out maps to >> C:out >> >> But then this is sounding like just treating A, B and C as endpoints :) >> > > Indeed that is adding more flexibility and will be quite usefull when > nesting protocolBuilders several levels deep. > > However, I do have another point which relates to the specific use case of > the customer I mentioned. > > Developers -> provide ProtocolBuilder implementations > Solution consultants -> use ProtocolBuilders abstractions to wire the route. >
Yeah this sounds like a great use case and in demand in more and more companies. This is something that we hear more often and often. > Practically, it seems to me that the easiest way of achieving that is to > create one or more modules > which contain the ProtocolBuilders implementation classes and the spring xml > files which configure them. > > Whenever a solution consultant starts working on a new customer > implementation he could use an archetype to create a module which has the > dependencies to the ProtocolBuilder modules preconfigured. > > The solution consultant would then create the route in xml dsl and use > camel:run to execute the route, this plugin goal would in turn bootstrap all > the ProtocolBuilder configurations located in > classpath*:META-INF/spring/.xml, making them available to the route at > runtime. > > Now my question is: When you define a ProtocolBuilder in the spring xml, > would it get initialized and added to the CamelContext at that point ? I > mean I don't think it's a good idea to initialize and add all the > ProtocolBuilders which are available in classpath*:META-INF/spring, but > neither do I want to leave it up to the solution consultant to explicitly > define which builders get initialized. > > E.g. Like with the Parameterized RouteBuilder concept I mentioned earlier > > <camelContext ... > <routeBuilder ref="generateAndSignPdfRouteBuilder"/> > <routeBuilder ref="signPdfRouteBuilder"/> > .... > > Which is just way to complex for non developers in my opinion. > You can use annotations, for example the Spring @Component annotation. You would then @Component annotate the RouteBuilder to be included. Then you can use the <contextScan/> tag See http://camel.apache.org/spring.html This means its standard Spring stuff to annotate and use the spring XML tag to enable its context scanner. All you do in Camel is to add this <contextScan/> inside the <camelContext> tag. Maybe there are other ways to make this easier? Any suggestions? > > It sure would be nice if you could initialize and add the ProtocolBuilder > route configuration on demand. > Saving overhead on startup and runtime, yet making it easy for a low tech > guy to use all of the available > ProtocolBuilders -> no explicit declaration of ProtocolBuilders nor any > fiddling with dependencies in the pom.xml. > > The concept of the shorthand notation could add value here as well. > > The global properties + tech dependencies like a datasource could be > configured by developers using spring di in the xml. Wheras the parameters, > which make sense in the context of the route, are defined by the solution > consultant using the shorthand notation. > > E.g. > > ?signatureReason=JustForFun&signatureVisible=true&xslUri=com/xti/poc/camel/route/sample1/krusty.xsl > > > > jstrachan wrote: >> >> >> Thats a great point! Just like with OO, we probably need some kind of >> data hiding; or in this case its 'endpoint hiding'. So maybe using >> nested CamelContexts is a good thing. >> >> Another random idea; imagine if we had a ProtocolBuilder which created >> a child CamelContext - so all "direct:foo" and "seda:bar" endpoints >> were totally private. Then imagine, as a simple implementation option >> - we map all URIs within the ProtocolBuilder's URI space to the >> direct: endpoint within the nested CamelContext. >> >> So rather than having to add the "alias()" method I mentioned in the >> other thread - we could just use URIs inside the route for the >> 'input/output/error' URIs... >> http://camel.465427.n5.nabble.com/implementing-Protocols-or-a-way-to-make-it-easier-to-black-box-routes-and-compose-them-with-other-ros-td3218777.html#a3218777 >> >> e.g. imagine... >> >> class A extends ProtocolBuilder { >> public void configure() { >> from("direct:in"). >> beanRef("foo"). >> to("direct:out"); >> } >> } >> >> class B extends ProtocolBuilder { >> public void configure() { >> from("direct:in"). >> unmarshal().jaxb(). >> to("direct:out"); >> } >> } >> >> // now lets wire A and B >> // kinda like "Foo | A | B | Bar" on a unix command line >> >> class Foo extends RouteBuilder { >> public void configure() { >> from("activemq:Foo").to("a:in"); >> from("a:out").to("b:in"); >> from("b:out").to("activemq:Bar"); >> } >> } >> >> >> i.e. so A and B have no knowledge of each other (kinda like unix >> pipes), you can compose them together in any way you like (Foo) - and >> bind them to any middleware. >> >> In this example the 'local endpoints' (using direct:) are totally >> private to each ProtocolBuilder so there's no name clashes as we're >> using nested CamelContext's. >> >> Not totally sure if we should make "direct" into some magical >> component here; or if we should just introduce some kind of "local:" >> endpoint to use inside a ProtocolBuilder to emphasise a local, >> internal endpoint which is private to the ProtocolBuilder? e.g. >> replace "direct:in" to "local:in". >> >> The question of local v global endpoint URIs is interesting; I wonder >> how many kinds of endpoints can even support the concept of local. >> Using nested CamelContexts we'd have local seda/vm/direct I think; >> though given their similarity, maybe a new 'local' endpoint is simpler >> as it clearly describes what really is local versus what really is an >> external/global endpoint? >> >> Note that there's nothing to stop these protocols using >> external/global endpoints too; am sure they will. Its more where we >> parameterise things together we might want to use local endpoints >> which we can then route into / out of. >> > > Having the ProtocolBuilder create a child CamelContext seems like a very > good idea ! > This way you can use the direct: and seda endpoints with normal semantics > and without risk of namespace collisions. > > Just a thought though, if you are going with this concept, wouldn't it make > more sense to use a public: endpoint to explicitly define public endpoints ? > > E.g. > > class A extends ProtocolBuilder { > > public void configure() { > > from("public:in"). > beanRef("foo"). > to("direct:bar"); > > from("direct:bar"). > to("public:out"); > > } > } > > Doesn't a local: endpoints make more sense when you are not using a nested > Context, > and therefore would have to define explicitly what you keep private. > In the case of a nested CamelContext, the direct: and seda: endpoints are > always private and defining explicitly what you want as public makes sense. > > -- > View this message in context: > http://camel.465427.n5.nabble.com/Abstracting-Routes-using-Components-tp3234703p3239506.html > Sent from the Camel - Users mailing list archive at Nabble.com. > -- Claus Ibsen ----------------- FuseSource Email: [email protected] Web: http://fusesource.com Twitter: davsclaus Blog: http://davsclaus.blogspot.com/ Author of Camel in Action: http://www.manning.com/ibsen/
