Results 1 to 8 of 8

Thread: Non-annotation driven Cafe example?

  1. #1

    Default Non-annotation driven Cafe example?

    While using annotations to configure the ESB components makes for very little config, I have found it difficult to infer where particular components are. I also don't get an overview of the overall process flow. It feels to me that if I let my team develop services using annotations we would quickly end up with a ball of spaghetti services.

    So what I'd like to do is to ensure that most of the components are clearly defined. What I'm lacking is details on how to define some of the components without using annotations.

    For instance, how do you define a router and link it into the process flow such as that defined in the Cafe example?

    Could someone post a non-annotation driven config for the cafe example? Seeing the annotation driven and non-annotation driven side by side would be really useful.
    Last edited by william_ferguson_au@yahoo; May 26th, 2008 at 01:56 AM. Reason: Typo in the header

  2. #2
    Join Date
    Oct 2005
    Location
    Boston, MA
    Posts
    2,840

    Default

    In M4, we added namespace support for the <router/> and <splitter/> elements. They are not yet documented in the reference manual, but it is fairly straightforward. Here's a simple example:
    Code:
    <router id="router" ref="somePojo" method="someMethod"/>
    Thanks for the suggestion - I think we should provide a parallel version of the cafe demo that uses only XML.

  3. #3

    Default

    Thanks Mark. I had spotted the <router/> and <splitter/> elements and in fact thats what led to my post.

    How do I configure the input-channel for the router/splitter?

    Using annotations its
    Code:
    @MessageEndpoint(input="someChannel")
    but I can't see how it can be done using XML config
    Code:
    <splitter ref="splitter" method="split" output-channel="drinks"/>
    		
    <router ref="drinkRouter" method="resolveDrinkChannel"/>

  4. #4
    Join Date
    Oct 2005
    Location
    Boston, MA
    Posts
    2,840

    Default

    The <router/> and <splitter/> elements actually create instances that implement MessageHandler, so to supply the "input-channel", you just need to register them within a <handler-endpoint/> element. For example (from routerParserTests.xml):
    Code:
    <handler-endpoint handler="router" input-channel="input"/>
    
    <router id="router" ref="pojo" method="route"/>

  5. #5

    Default

    Mark, is the following config the correct way to specify the cafe example without using annotations?

    NB I can't check because I can't find spring-integration-core-1.0.0.M4 in the SpringSource bundle repository. Is there a way to browse the repository?

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans:beans xmlns="http://www.springframework.org/schema/integration"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:beans="http://www.springframework.org/schema/beans"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans
    			http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    			http://www.springframework.org/schema/integration
    			http://www.springframework.org/schema/integration/spring-integration-1.0.xsd
    			http://www.springframework.org/schema/context
    			http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    
    	<message-bus/>
    	<!--annotation-driven/ -->
    
    	<channel id="orders"/>
    	<channel id="drinks"/>
    	<channel id="coldDrinks"/>
    	<channel id="hotDrinks"/>
    	
    	<handler-endpoint handler="drink-splitter" input-channel="orders" />
    	<splitter id="drink-splitter" ref="splitter" method="split" output-channel="drinks"/> 
    	
    	<handler-endpoint handler="drinkRouter" input-channel="drinks"/>
    	<router ref="drinkRouter" method="resolveDrinkChannel"/>
    		
    	<target-endpoint target="barista" method="prepareColdDrink" input-channel="coldDrinks"/>
    	
    	<target-endpoint target="barista" method="prepareHotDrink" input-channel="hotDrinks">
    		<concurrency core="5" max="25" queue-capacity="0"/>
    	</target-endpoint>
    	
    	
    	<!-- Beans -->
    			
    	<beans:bean id="cafe" class="org.springframework.integration.samples.cafe.Cafe">
    		<beans:property name="orderChannel" ref="orders"/>
    	</beans:bean>
    	
    	<beans:bean id="barista" class="org.springframework.integration.samples.cafe.Barista">
    		<!--beans:property name="hotDrinkDelay" value="1000"/-->
    		<!--beans:property name="coldDrinkDelay" value="700"/-->
    	</beans:bean>
    	
    	<beans:bean id="drinkRouter" class="org.springframework.integration.samples.cafe.DrinkRouter"/>
    	
    	<beans:bean id="splitter" class="org.springframework.integration.samples.cafe.OrderSplitter"/>
    	
    </beans:beans>

  6. #6

    Default

    Or perhaps even possible to contract the orders and drinks channel consumers to:

    Code:
    <handler-endpoint handler="splitter" method="split" 
                      output-channel="drinks" input-channel="orders"/>
    	
    <handler-endpoint handler="drinkRouter" method="resolveDrinkChannel" 
                      input-channel="drinks"/>

  7. #7

    Default

    A was also wondering whether any thought had been given to representing the handler-endpoints and handler using contained elements like:

    Code:
    <handler-endpoint input-channel="drinks">
    	<router ref="drinkRouter" method="resolveDrinkChannel"/>
    </handler-endpoint>
    	
      or
    
    <handler-endpoint input-channel="drinks">
    	<handler ref="drinkRouter" method="resolveDrinkChannel"/>
    </handler-endpoint>
    While more verbose than the config immediately above, it his seems to make the distinction between endpoint and handler much clearly. The handler endpoint is only concerned with input/output channels while the contained handler/router/splitter element defines the handler to invoke.

    Also the config for a source-endpoint, which I imagine is something like the following:

    Code:
    <source-adapter id="my-source-adapter" ref="some-bean" method="some-method"/>
    <source-endpoint source="my-source-adapter" channel="some-output-channel">
    	<schedule period="500"/>
    </source-endpoint>
    would seem to be more clearly represented by something like (note change of channel attribute to output-channel as well as contained adapter element):
    Code:
    <source-endpoint output-channel="some-output-channel">
    	<adapter ref="some-source-bean" method="source-bean-method"/>
    	<schedule period="500"/>
    </source-endpoint>
    just my 2 cents, but I'd be interested in feedback.

  8. #8
    Join Date
    May 2007
    Location
    Netherlands
    Posts
    614

    Default

    Good ideas. I had the same thought on allowing handlers nested inside handler-enpoints (while reading this post). An argument for it you haven't mentioned is the fact that you might not want to expose the handler to the outside by id.

    Another benefit would be that it is possible to validate nesting with xsd, but references can only be evaluated at runtime.

    The downside is that this would complicate the schema and the namespace handlers. It will also add to the responsibility for backwards compatibility (you can put this in, but you can never take it out).

    The options you have now are already quite sufficient:
    1. namespace support with references (like your sample)
    2. wiring annotated beans explicitly (intermediate solution)
    3. component scanning

    I would personally go for option 2 most of the times I think. I do feel uncomfortable with sticking channel names inside classes, but those can be injected as well.

    Code:
    <bean class="..MyRouter" p:inputChannel="someInput" 
        p:caseAOutput="AMessages" p:caseBOutput="BMessages" />
    <si:annotation-driven/>
    Code:
    @MessageEndpoint public class MyRouter {
      @Router String aOrB(Message m){
        return m.getPayload().isCaseA() ? caseAOutput : caseBOutput;
      }
    }
    Who needs more namespace features?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •