camel-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Camel > Routebox
Date Fri, 07 Jan 2011 20:36:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/1810/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/Routebox">Routebox</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~akarpe">Ashwin
Karpe</a>
    </h4>
        <br/>
                         <h4>Changes (6)</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" > <br>In such environments, it
is often necessary to craft an integration solution by creating a sense of layering among
camel routes effectively organizing them into  <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">
 * Coarse grained or higher level routes - routes with Routebox endpoints that facade a collection
of inner or lower level routes that are decomposed along   <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">
 * Coarse grained or higher level routes - aggregated collection of inner or lower level routes
exposed as Routebox endpoints that represent an integration focus area. For example <br>
     ||Focus Area||Coarse grained Route Examples||  <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">**
*Business needs* --&gt; HR</span> <span class="diff-added-words"style="background-color:
#dfd;">|Department Focus|HR</span> routes, Sales routes <span class="diff-changed-words">etc<span
class="diff-added-chars"style="background-color: #dfd;">|</span></span> <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">
     ** *Objectives*        --&gt; Shipping routes, Fulfillment routes etc <br>
     ** *Technologies*     --&gt; Database routes, Caching routes, polling routes etc
<br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">
     |Supply chain &amp; B2B Focus|Shipping routes, Fulfillment routes, 3rd party services
etc| <br>      |Technology Focus|Database routes, JMS routes, Scheduled batch routes
etc| <br></td></tr>
            <tr><td class="diff-changed-lines" >* Fine grained routes - routes
that execute a <span class="diff-added-words"style="background-color: #dfd;">singular
and</span> specific business and/or integration pattern. <br></td></tr>
            <tr><td class="diff-unchanged" > <br>Requests sent to Routebox
endpoints on coarse grained routes can then delegate requests to inner fine grained routes
to achieve a specific integration objective, collect the final inner result, and continue
to progress to the next step along the coarse-grained route. <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
        </table>
</div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <h2><a name="Routebox-RouteboxComponent"></a>Routebox Component</h2>

<p><b>Available as of Camel 2.6</b></p>

<p>The <b>routebox</b> component enables the creation of specialized endpoints
that offer encapsulation and a strategy based indirection service to a collection of camel
routes hosted in an automatically created or user injected camel context.</p>

<p>Routebox endpoints are camel endpoints that may be invoked directly on camel routes.
The routebox endpoint performs the following key functions</p>
<ul>
	<li>encapsulation - acts as a blackbox, hosting a collection of camel routes stored
in an inner camel context. The inner context is fully under the control of the routebox component
and is <b>JVM bound</b>.</li>
	<li>strategy based indirection - direct payloads sent to the routebox endpoint along
a camel route to specific inner routes based on a user defined internal routing strategy or
a dispatch map.</li>
	<li>exchange propagation - forward exchanges modified by the routebox endpoint to the
next segment of the camel route.</li>
</ul>


<p>The routebox component supports both consumer and producer endpoints. </p>

<p>Producer endpoints are of two flavors</p>
<ul>
	<li>Producers that send or dispatch incoming requests to a external routebox consumer
endpoint</li>
	<li>Producers that directly invoke routes in an internal embedded camel context thereby
not sending requests to an external consumer.</li>
</ul>


<p>Maven users will need to add the following dependency to their <tt>pom.xml</tt>
for this component:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
<span class="code-tag">&lt;dependency&gt;</span>
    <span class="code-tag">&lt;groupId&gt;</span>org.apache.camel<span
class="code-tag">&lt;/groupId&gt;</span>
    <span class="code-tag">&lt;artifactId&gt;</span>camel-routebox<span
class="code-tag">&lt;/artifactId&gt;</span>
    <span class="code-tag">&lt;version&gt;</span>x.x.x<span class="code-tag">&lt;/version&gt;</span>
    <span class="code-tag"><span class="code-comment">&lt;!-- use the same
version as your Camel core version --&gt;</span></span>
<span class="code-tag">&lt;/dependency&gt;</span>
</pre>
</div></div>

<h3><a name="Routebox-TheneedforaCamelRouteboxendpoint"></a>The need for
a Camel Routebox endpoint</h3>

<p>The routebox component is designed to ease integration in complex environments needing</p>
<ul>
	<li>a large collection of routes and</li>
	<li>involving a wide set of endpoint technologies needing integration in different
ways</li>
</ul>


<p>In such environments, it is often necessary to craft an integration solution by creating
a sense of layering among camel routes effectively organizing them into </p>
<ul>
	<li>Coarse grained or higher level routes - aggregated collection of inner or lower
level routes exposed as Routebox endpoints that represent an integration focus area. For example
<div class='table-wrap'>
<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'>Focus Area</th>
<th class='confluenceTh'>Coarse grained Route Examples</th>
</tr>
<tr>
<td class='confluenceTd'>Department Focus</td>
<td class='confluenceTd'>HR routes, Sales routes etc</td>
</tr>
<tr>
<td class='confluenceTd'>Supply chain &amp; B2B Focus</td>
<td class='confluenceTd'>Shipping routes, Fulfillment routes, 3rd party services etc</td>
</tr>
<tr>
<td class='confluenceTd'>Technology Focus</td>
<td class='confluenceTd'>Database routes, JMS routes, Scheduled batch routes etc</td>
</tr>
</tbody></table>
</div>
</li>
	<li>Fine grained routes - routes that execute a singular and specific business and/or
integration pattern.</li>
</ul>


<p>Requests sent to Routebox endpoints on coarse grained routes can then delegate requests
to inner fine grained routes to achieve a specific integration objective, collect the final
inner result, and continue to progress to the next step along the coarse-grained route.</p>

<h3><a name="Routebox-URIformat"></a>URI format</h3>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
routebox:routeboxname[?options]
</pre>
</div></div>

<p>You can append query options to the URI in the following format, <tt>?option=value&amp;option=value&amp;...</tt></p>

<h3><a name="Routebox-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>dispatchStrategy</tt> </td>
<td class='confluenceTd'> <tt>null</tt> </td>
<td class='confluenceTd'> A string representing a key in the Camel Registry matching
an object value implementing the interface <em>org.apache.camel.component.routebox.strategy.RouteboxDispatchStrategy</em>
</td>
</tr>
<tr>
<td class='confluenceTd'> <tt>dispatchMap</tt> </td>
<td class='confluenceTd'> <tt>null</tt> </td>
<td class='confluenceTd'> A string representing a key in the Camel Registry matching
an object value of the type HashMap&lt;String, String&gt;. The HashMap key should
contain strings that can be matched against the value set for the exchange header <b>ROUTE_DISPATCH_KEY</b>.
The HashMap value should contain inner route consumer URI's to which requests should be directed.
</td>
</tr>
<tr>
<td class='confluenceTd'> <tt>innerContext</tt> </td>
<td class='confluenceTd'> <tt>auto created</tt> </td>
<td class='confluenceTd'> A string representing a key in the Camel Registry matching
an object value of the type <em>org.apache.camel.CamelContext</em>. If a CamelContext
is not provided by the user a CamelContext is automatically created for deployment of inner
routes. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>innerRegistry</tt> </td>
<td class='confluenceTd'> <tt>null</tt> </td>
<td class='confluenceTd'> A string representing a key in the Camel Registry matching
an object value that implements the interface <em>org.apache.camel.spi.Registry</em>.
If Registry values are utilized by inner routes to create endpoints, an innerRegistry parameter
must be provided </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>routeBuilders</tt> </td>
<td class='confluenceTd'> <tt>empty List</tt> </td>
<td class='confluenceTd'> A string representing a key in the Camel Registry matching
an object value of the type <em>List&lt;org.apache.camel.builder.RouteBuilder&gt;</em>.
If the user does not supply an innerContext pre-primed with inner routes, the routeBuilders
option must be provided as a non-empty list of RouteBuilders containing inner routes </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>innerProtocol</tt> </td>
<td class='confluenceTd'> <tt>Direct</tt> </td>
<td class='confluenceTd'> The Protocol used internally by the Routebox component. Can
be Direct or SEDA. <b>The Routebox component currently offers protocols that are JVM
bound.</b> </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>sendToConsumer</tt> </td>
<td class='confluenceTd'> <tt>true</tt> </td>
<td class='confluenceTd'> Dictates whether a Producer endpoint sends a request to an
external routebox consumer. If the setting is false, the Producer creates an embedded inner
context and processes requests internally. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>forkContext</tt> </td>
<td class='confluenceTd'> <tt>true</tt> </td>
<td class='confluenceTd'> The Protocol used internally by the Routebox component. Can
be Direct or SEDA. <b>The Routebox component currently offers protocols that are JVM
bound.</b> </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>threads</tt> </td>
<td class='confluenceTd'> <tt>20</tt> </td>
<td class='confluenceTd'> Number of threads to be used by the routebox to receive requests.
<b>Setting applicable only for innerProtocol SEDA</b>. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>queueSize</tt> </td>
<td class='confluenceTd'> <tt>unlimited</tt> </td>
<td class='confluenceTd'> Create a fixed size queue to receive requests. <b>Setting
applicable only for innerProtocol SEDA</b>. </td>
</tr>
</tbody></table>
</div>
</div>

<h3><a name="Routebox-Sending%2FReceivingMessagesto%2Ffromtheroutebox"></a>Sending/Receiving
Messages to/from the routebox</h3>

<p>Before sending requests it is necessary to properly configure the routebox by loading
the required URI parameters into the Registry as shown below. In the case of Spring, if the
necessary beans are declared correctly, the registry is automatically populated by Camel.</p>

<h4><a name="Routebox-Step1%3ALoadinginnerroutedetailsintotheRegistry"></a>Step
1: Loading inner route details into the Registry </h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
@Override
<span class="code-keyword">protected</span> JndiRegistry createRegistry() <span
class="code-keyword">throws</span> Exception {
    JndiRegistry registry = <span class="code-keyword">new</span> JndiRegistry(createJndiContext());
        
    <span class="code-comment">// Wire the routeDefinitions &amp; dispatchStrategy
to the <span class="code-keyword">outer</span> camelContext where the routebox
is declared
</span>    List&lt;RouteBuilder&gt; routes = <span class="code-keyword">new</span>
ArrayList&lt;RouteBuilder&gt;();
    routes.add(<span class="code-keyword">new</span> SimpleRouteBuilder());
    registry.bind(<span class="code-quote">"registry"</span>, createInnerRegistry());
    registry.bind(<span class="code-quote">"routes"</span>, routes);
        
    <span class="code-comment">// Wire a dispatch map to registry
</span>    HashMap&lt;<span class="code-object">String</span>, <span
class="code-object">String</span>&gt; map = <span class="code-keyword">new</span>
HashMap&lt;<span class="code-object">String</span>, <span class="code-object">String</span>&gt;();
    map.put(<span class="code-quote">"addToCatalog"</span>, <span class="code-quote">"seda:addToCatalog"</span>);
    map.put(<span class="code-quote">"findBook"</span>, <span class="code-quote">"seda:findBook"</span>);
    registry.bind(<span class="code-quote">"map"</span>, map);
    
    <span class="code-comment">// Alternatively wiring a dispatch strategy to the registry
</span>    registry.bind(<span class="code-quote">"strategy"</span>, <span
class="code-keyword">new</span> SimpleRouteDispatchStrategy());

    <span class="code-keyword">return</span> registry;
}
    
<span class="code-keyword">private</span> JndiRegistry createInnerRegistry() <span
class="code-keyword">throws</span> Exception {
    JndiRegistry innerRegistry = <span class="code-keyword">new</span> JndiRegistry(createJndiContext());
    BookCatalog catalogBean = <span class="code-keyword">new</span> BookCatalog();
    innerRegistry.bind(<span class="code-quote">"library"</span>, catalogBean);
       
        
    <span class="code-keyword">return</span> innerRegistry;
}
...
CamelContext context = <span class="code-keyword">new</span> DefaultCamelContext(createRegistry());
</pre>
</div></div>

<h4><a name="Routebox-Step2%3AOptionalyusingaDispatchStrategyinsteadofaDispatchMap"></a>Step
2: Optionaly using a Dispatch Strategy instead of a Dispatch Map</h4>

<p>Using a dispatch Strategy involves implementing the interface <em>org.apache.camel.component.routebox.strategy.RouteboxDispatchStrategy</em>
as shown in the example below.</p>

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

    /* (non-Javadoc)
     * @see org.apache.camel.component.routebox.strategy.RouteboxDispatchStrategy#selectDestinationUri(java.util.List,
org.apache.camel.Exchange)
     */
    <span class="code-keyword">public</span> URI selectDestinationUri(List&lt;URI&gt;
activeDestinations,
            Exchange exchange) {
        URI dispatchDestination = <span class="code-keyword">null</span>;
            
        <span class="code-object">String</span> operation = exchange.getIn().getHeader(<span
class="code-quote">"ROUTE_DISPATCH_KEY"</span>, <span class="code-object">String</span>.class);
        <span class="code-keyword">for</span> (URI destination : activeDestinations)
{
            <span class="code-keyword">if</span> (destination.toASCIIString().equalsIgnoreCase(<span
class="code-quote">"seda:"</span> + operation)) {
                dispatchDestination = destination;
                <span class="code-keyword">break</span>;
            }
        }
            
        <span class="code-keyword">return</span> dispatchDestination;
    }
}
</pre>
</div></div>

<h4><a name="Routebox-Step2%3ALaunchingarouteboxconsumer"></a>Step 2: Launching
a routebox consumer</h4>

<p>When creating a route consumer, note that the # entries in the routeboxUri are matched
to the created inner registry, routebuilder list and dispatchStrategy/dispatchMap in the CamelContext
Registry. Note that all routebuilders and associated routes are launched in the routebox created
inner context</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
<span class="code-keyword">private</span> <span class="code-object">String</span>
routeboxUri = <span class="code-quote">"routebox:multipleRoutes?innerRegistry=#registry&amp;routeBuilders=#routes&amp;dispatchMap=#map"</span>;

<span class="code-keyword">public</span> void testRouteboxRequests() <span
class="code-keyword">throws</span> Exception {
    CamelContext context = createCamelContext();
    template = <span class="code-keyword">new</span> DefaultProducerTemplate(context);
    template.start();        
     
    context.addRoutes(<span class="code-keyword">new</span> RouteBuilder() {
        <span class="code-keyword">public</span> void configure() {
            from(routeboxUri)
                .to(<span class="code-quote">"log:Routes operation performed?showAll=<span
class="code-keyword">true</span>"</span>);
        }
    });
    context.start();

    <span class="code-comment">// Now use the ProducerTemplate to send the request to
the routebox
</span>    template.requestBodyAndHeader(routeboxUri, book, <span class="code-quote">"ROUTE_DISPATCH_KEY"</span>,
<span class="code-quote">"addToCatalog"</span>);
}
</pre>
</div></div>

<h4><a name="Routebox-Step3%3AUsingarouteboxproducer"></a>Step 3: Using
a routebox producer</h4>

<p>When sending requests to the routebox, it is not necessary for producers do not need
to know the inner route endpoint URI and they can simply invoke the Routebox URI endpoint
with a dispatch strategy or dispatchMap as shown below</p>

<p>It is necessary to set a special exchange Header called <b>ROUTE_DISPATCH_KEY</b>
(optional for Dispatch Strategy) with a key that matches a key in the dispatch map so that
the request can be sent to the correct inner route</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
from(<span class="code-quote">"direct:sendToStrategyBasedRoutebox"</span>)
    .to(<span class="code-quote">"routebox:multipleRoutes?innerRegistry=#registry&amp;routeBuilders=#routes&amp;dispatchStrategy=#strategy"</span>)
    .to(<span class="code-quote">"log:Routes operation performed?showAll=<span class="code-keyword">true</span>"</span>);

from (<span class="code-quote">"direct:sendToMapBasedRoutebox"</span>)
    .setHeader(<span class="code-quote">"ROUTE_DISPATCH_KEY"</span>, constant(<span
class="code-quote">"addToCatalog"</span>))
    .to(<span class="code-quote">"routebox:multipleRoutes?innerRegistry=#registry&amp;routeBuilders=#routes&amp;dispatchMap=#map"</span>)
    .to(<span class="code-quote">"log:Routes operation performed?showAll=<span class="code-keyword">true</span>"</span>);
</pre>
</div></div>

    </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/Routebox">View Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=24192258&revisedVersion=4&originalVersion=3">View
Changes</a>
                |
        <a href="https://cwiki.apache.org/confluence/display/CAMEL/Routebox?showComments=true&amp;showCommentArea=true#addcomment">Add
Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message