camel-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Camel > Dynamic Router
Date Thu, 04 Aug 2011 18:18:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/2042/9/1/_/styles/combined.css?spaceKey=CAMEL&amp;forWysiwyg=true"
type="text/css">
    </head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
    <h2><a href="https://cwiki.apache.org/confluence/display/CAMEL/Dynamic+Router">Dynamic
Router</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~janstey">Jonathan
Anstey</a>
    </h4>
        <br/>
                         <h4>Changes (1)</h4>
                                 
    
<div id="page-diffs">
                    <table class="diff" cellpadding="0" cellspacing="0">
    
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >h4. Java DSL <br> <br></td></tr>
            <tr><td class="diff-changed-lines" >In Java DSL you can use the <span
class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">{{routingSlip}}</span>
<span class="diff-added-words"style="background-color: #dfd;">{{dynamicRouter}}</span>
as shown below: <br></td></tr>
            <tr><td class="diff-unchanged" > <br>{snippet:id=e1|lang=java|url=camel/trunk/camel-core/src/test/java/org/apache/camel/processor/DynamicRouterTest.java}
<br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <h2><a name="DynamicRouter-DynamicRouter"></a>Dynamic Router</h2>

<p>The <a href="http://www.enterpriseintegrationpatterns.com/DynamicRouter.html"
class="external-link" rel="nofollow">Dynamic Router</a> from the <a href="/confluence/display/CAMEL/Enterprise+Integration+Patterns"
title="Enterprise Integration Patterns">EIP patterns</a> allows you to route messages
while avoiding the dependency of the router on all possible destinations while maintaining
its efficiency.</p>

<p><span class="image-wrap" style=""><img src="http://www.enterpriseintegrationpatterns.com/img/DynamicRouter.gif"
style="border: 0px solid black" /></span></p>

<p>In <b>Camel 2.5</b> we introduced a <tt>dynamicRouter</tt>
in the DSL which is like a dynamic <a href="/confluence/display/CAMEL/Routing+Slip" title="Routing
Slip">Routing Slip</a> which evaluates the slip <em>on-the-fly</em>.
</p>

<div class='panelMacro'><table class='warningMacro'><colgroup><col width='24'><col></colgroup><tr><td
valign='top'><img src="/confluence/images/icons/emoticons/forbidden.gif" width="16"
height="16" align="absmiddle" alt="" border="0"></td><td><b>Beware</b><br
/>You must ensure the expression used for the <tt>dynamicRouter</tt> such as
a bean, will return <tt>null</tt> to indicate the end. Otherwise the <tt>dynamicRouter</tt>
will keep repeating endlessly.</td></tr></table></div>


<h3><a name="DynamicRouter-Options"></a>Options</h3>

<div class="confluenceTableSmall"><div class='table-wrap'>
<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'> Name </th>
<th class='confluenceTh'> Default Value </th>
<th class='confluenceTh'> Description </th>
</tr>
<tr>
<td class='confluenceTd'> <tt>uriDelimiter</tt> </td>
<td class='confluenceTd'> <tt>,</tt> </td>
<td class='confluenceTd'> Delimiter used if the <a href="/confluence/display/CAMEL/Expression"
title="Expression">Expression</a> returned multiple endpoints. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>ignoreInvalidEndpoints</tt> </td>
<td class='confluenceTd'> <tt>false</tt> </td>
<td class='confluenceTd'> If an endpoint uri could not be resolved, should it be ignored.
Otherwise Camel will thrown an exception stating the endpoint uri is not valid. </td>
</tr>
</tbody></table>
</div>
</div>


<h3><a name="DynamicRouter-DynamicRouterinCamel2.5onwards"></a>Dynamic Router
in Camel 2.5 onwards</h3>

<p>From Camel 2.5 the <a href="/confluence/display/CAMEL/Dynamic+Router" title="Dynamic
Router">Dynamic Router</a> will set a property (Exchange.SLIP_ENDPOINT) on the <a
href="/confluence/display/CAMEL/Exchange" title="Exchange">Exchange</a> which contains
the current endpoint as it advanced though the slip. This allows you to know how far we have
processed in the slip. (It's a slip because the <a href="/confluence/display/CAMEL/Dynamic+Router"
title="Dynamic Router">Dynamic Router</a> implementation is based on top of <a
href="/confluence/display/CAMEL/Routing+Slip" title="Routing Slip">Routing Slip</a>).</p>

<h4><a name="DynamicRouter-JavaDSL"></a>Java DSL</h4>

<p>In Java DSL you can use the <tt>dynamicRouter</tt> as shown below:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">from(<span class="code-quote">"direct:start"</span>)
    <span class="code-comment">// use a bean as the dynamic router
</span>    .dynamicRouter(bean(DynamicRouterTest.class, <span class="code-quote">"slip"</span>));
</pre>
</div></div>

<p>Which will leverage a <a href="/confluence/display/CAMEL/Bean" title="Bean">Bean</a>
to compute the slip <em>on-the-fly</em>, which could be implemented as follows:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">/**
 * Use <span class="code-keyword">this</span> method to compute dynamic where
we should route next.
 *
 * @param body the message body
 * @<span class="code-keyword">return</span> endpoints to go, or &lt;tt&gt;<span
class="code-keyword">null</span>&lt;/tt&gt; to indicate the end
 */
<span class="code-keyword">public</span> <span class="code-object">String</span>
slip(<span class="code-object">String</span> body) {
    bodies.add(body);
    invoked++;

    <span class="code-keyword">if</span> (invoked == 1) {
        <span class="code-keyword">return</span> <span class="code-quote">"mock:a"</span>;
    } <span class="code-keyword">else</span> <span class="code-keyword">if</span>
(invoked == 2) {
        <span class="code-keyword">return</span> <span class="code-quote">"mock:b,mock:c"</span>;
    } <span class="code-keyword">else</span> <span class="code-keyword">if</span>
(invoked == 3) {
        <span class="code-keyword">return</span> <span class="code-quote">"direct:foo"</span>;
    } <span class="code-keyword">else</span> <span class="code-keyword">if</span>
(invoked == 4) {
        <span class="code-keyword">return</span> <span class="code-quote">"mock:result"</span>;
    }

    <span class="code-comment">// no more so <span class="code-keyword">return</span>
<span class="code-keyword">null</span>
</span>    <span class="code-keyword">return</span> <span class="code-keyword">null</span>;
}
</pre>
</div></div>

<p>Mind that this example is only for show and tell. The current implementation is not
thread safe. You would have to store the state on the Exchange, to ensure thread safety. </p>

<h4><a name="DynamicRouter-SpringXML"></a>Spring XML</h4>
<p>The same example in Spring XML would be:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml"><span class="code-tag">&lt;bean id=<span class="code-quote">"mySlip"</span>
class=<span class="code-quote">"org.apache.camel.processor.DynamicRouterTest"</span>/&gt;</span>

<span class="code-tag">&lt;camelContext xmlns=<span class="code-quote">"http://camel.apache.org/schema/spring"</span>&gt;</span>
    <span class="code-tag">&lt;route&gt;</span>
        <span class="code-tag">&lt;from uri=<span class="code-quote">"direct:start"</span>/&gt;</span>
        <span class="code-tag">&lt;dynamicRouter&gt;</span>
            <span class="code-tag"><span class="code-comment">&lt;!-- use
a method call on a bean as dynamic router --&gt;</span></span>
            <span class="code-tag">&lt;method ref=<span class="code-quote">"mySlip"</span>
method=<span class="code-quote">"slip"</span>/&gt;</span>
        <span class="code-tag">&lt;/dynamicRouter&gt;</span>
    <span class="code-tag">&lt;/route&gt;</span>

    <span class="code-tag">&lt;route&gt;</span>
        <span class="code-tag">&lt;from uri=<span class="code-quote">"direct:foo"</span>/&gt;</span>
        <span class="code-tag">&lt;transform&gt;</span><span class="code-tag">&lt;constant&gt;</span>Bye
World<span class="code-tag">&lt;/constant&gt;</span><span class="code-tag">&lt;/transform&gt;</span>
        <span class="code-tag">&lt;to uri=<span class="code-quote">"mock:foo"</span>/&gt;</span>
    <span class="code-tag">&lt;/route&gt;</span>

<span class="code-tag">&lt;/camelContext&gt;</span>
</pre>
</div></div>

<h4><a name="DynamicRouter-@DynamicRouterannotation"></a>@DynamicRouter
annotation</h4>

<p>You can also use the <tt>@DynamicRouter</tt> annotation, for example
the Camel 2.4 example below could be written as follows. The <tt>route</tt> method
would then be invoked repeatedly as the message is processed dynamically. The idea is to return
the next endpoint uri where to go. Return <tt>null</tt> to indicate the end. You
can return multiple endpoints if you like, just as the <a href="/confluence/display/CAMEL/Routing+Slip"
title="Routing Slip">Routing Slip</a>, where each endpoint is separated by a delimiter.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
<span class="code-keyword">public</span> class MyDynamicRouter {

    @Consume(uri = <span class="code-quote">"activemq:foo"</span>)
    @DynamicRouter
    <span class="code-keyword">public</span> <span class="code-object">String</span>
route(@XPath(<span class="code-quote">"/customer/id"</span>) <span class="code-object">String</span>
customerId, @Header(<span class="code-quote">"Location"</span>) <span class="code-object">String</span>
location, Document body) {
        <span class="code-comment">// query a database to find the best match of the
endpoint based on the input parameteres
</span>        <span class="code-comment">// <span class="code-keyword">return</span>
the next endpoint uri, where to go. Return <span class="code-keyword">null</span>
to indicate the end.
</span>    }
}
</pre>
</div></div>

<h3><a name="DynamicRouter-DynamicRouterinCamel2.4orolder"></a>Dynamic Router
in Camel 2.4 or older</h3>
<p>The simplest way to implement this is to use the <a href="/confluence/display/CAMEL/RecipientList+Annotation"
title="RecipientList Annotation">RecipientList Annotation</a> on a Bean method to
determine where to route the message.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
<span class="code-keyword">public</span> class MyDynamicRouter {

    @Consume(uri = <span class="code-quote">"activemq:foo"</span>)
    @RecipientList
    <span class="code-keyword">public</span> List&lt;<span class="code-object">String</span>&gt;
route(@XPath(<span class="code-quote">"/customer/id"</span>) <span class="code-object">String</span>
customerId, @Header(<span class="code-quote">"Location"</span>) <span class="code-object">String</span>
location, Document body) {
        <span class="code-comment">// query a database to find the best match of the
endpoint based on the input parameteres
</span>        ...
    }
}
</pre>
</div></div>

<p>In the above we can use the <a href="/confluence/display/CAMEL/Parameter+Binding+Annotations"
title="Parameter Binding Annotations">Parameter Binding Annotations</a> to bind different
parts of the <a href="/confluence/display/CAMEL/Message" title="Message">Message</a>
to method parameters or use an <a href="/confluence/display/CAMEL/Expression" title="Expression">Expression</a>
such as using <a href="/confluence/display/CAMEL/XPath" title="XPath">XPath</a>
or <a href="/confluence/display/CAMEL/XQuery" title="XQuery">XQuery</a>.</p>

<p>The method can be invoked in a number of ways as described in the <a href="/confluence/display/CAMEL/Bean+Integration"
title="Bean Integration">Bean Integration</a> such as</p>

<ul>
	<li><a href="/confluence/display/CAMEL/POJO+Producing" title="POJO Producing">POJO
Producing</a></li>
	<li><a href="/confluence/display/CAMEL/Spring+Remoting" title="Spring Remoting">Spring
Remoting</a></li>
	<li><a href="/confluence/display/CAMEL/Bean" title="Bean">Bean</a> component</li>
</ul>


<h4><a name="DynamicRouter-UsingThisPattern"></a>Using This Pattern</h4>

<p>If you would like to use this EIP Pattern then please read the <a href="/confluence/display/CAMEL/Getting+Started"
title="Getting Started">Getting Started</a>, you may also find the <a href="/confluence/display/CAMEL/Architecture"
title="Architecture">Architecture</a> useful particularly the description of <a
href="/confluence/display/CAMEL/Endpoint" title="Endpoint">Endpoint</a> and <a
href="/confluence/display/CAMEL/URIs" title="URIs">URIs</a>. Then you could try out
some of the <a href="/confluence/display/CAMEL/Examples" title="Examples">Examples</a>
first before trying this pattern out.</p>
    </div>
        <div id="commentsSection" class="wiki-content pageSection">
        <div style="float: right;">
            <a href="https://cwiki.apache.org/confluence/users/viewnotifications.action"
class="grey">Change Notification Preferences</a>
        </div>
        <a href="https://cwiki.apache.org/confluence/display/CAMEL/Dynamic+Router">View
Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=98539&revisedVersion=8&originalVersion=7">View
Changes</a>
                |
        <a href="https://cwiki.apache.org/confluence/display/CAMEL/Dynamic+Router?showComments=true&amp;showCommentArea=true#addcomment">Add
Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message