camel-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Camel > AdviceWith
Date Thu, 04 Aug 2011 09:55: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/AdviceWith">AdviceWith</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~davsclaus">Claus
Ibsen</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" >{snippet:id=e1|lang=java|url=camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/AdviceWithTest.java}
<br> <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">{warning:title=Recommendation}
<br>It is recommended to only advice a given route once (you can of course advice multiple
routes). If you do it multiple times, then it may not work as expected, especially when any
kind of error handling is involved. <br>The Camel team plan for Camel 3.0 to support
this as internal refactorings in the routing engine is needed to support this properly. <br>{warning}
<br></td></tr>
            <tr><td class="diff-unchanged" > <br>h3. Using AdviceWithRouteBuilder
<br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <h2><a name="AdviceWith-AdviceWith"></a>AdviceWith</h2>
<p><b>Available as of Camel 2.1</b></p>

<p>AdviceWith is used for testing Camel routes where you can <em>advice</em>
an existing route before its being tested. What <tt>adviceWith</tt> allows is
to changes some factors on the route before the test is being run. </p>

<p>At current time you can <em>advice</em> an existing route by adding <a
href="/confluence/display/CAMEL/Intercept" title="Intercept">Intercept</a>, <a
href="/confluence/display/CAMEL/Exception+Clause" title="Exception Clause">Exception Clause</a>
etc. which then will apply for the route being advice.</p>

<p>For example in the route below we intercept sending a message to the <tt>mock:foo</tt>
endpoint and detour 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> void testAdvised()
<span class="code-keyword">throws</span> Exception {
    <span class="code-comment">// advice the first route using the inlined route builder
</span>    context.getRouteDefinitions().get(0).adviceWith(context, <span class="code-keyword">new</span>
RouteBuilder() {
        @Override
        <span class="code-keyword">public</span> void configure() <span class="code-keyword">throws</span>
Exception {
            <span class="code-comment">// intercept sending to mock:foo and <span
class="code-keyword">do</span> something <span class="code-keyword">else</span>
</span>            interceptSendToEndpoint(<span class="code-quote">"mock:foo"</span>)
                    .skipSendToOriginalEndpoint()
                    .to(<span class="code-quote">"log:foo"</span>)
                    .to(<span class="code-quote">"mock:advised"</span>);
        }
    });

    getMockEndpoint(<span class="code-quote">"mock:foo"</span>).expectedMessageCount(0);
    getMockEndpoint(<span class="code-quote">"mock:advised"</span>).expectedMessageCount(1);
    getMockEndpoint(<span class="code-quote">"mock:result"</span>).expectedMessageCount(1);

    template.sendBody(<span class="code-quote">"direct:start"</span>, <span
class="code-quote">"Hello World"</span>);

    assertMockEndpointsSatisfied();
}
</pre>
</div></div>

<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>Recommendation</b><br
/>It is recommended to only advice a given route once (you can of course advice multiple
routes). If you do it multiple times, then it may not work as expected, especially when any
kind of error handling is involved.<br/>
The Camel team plan for Camel 3.0 to support this as internal refactorings in the routing
engine is needed to support this properly.</td></tr></table></div>

<h3><a name="AdviceWith-UsingAdviceWithRouteBuilder"></a>Using AdviceWithRouteBuilder</h3>
<p><b>Available as of Camel 2.7</b></p>

<p>The <tt>AdviceWithRouteBuilder</tt> is a specialized <tt>RouteBuilder</tt>
which has additional methods for advising routes. For example this allows you to manipulate
the advised route, such as replacing a node with some other nodes.</p>

<p>The <tt>AdviceWithRouteBuilder</tt> offers the following extra methods</p>

<div class='table-wrap'>
<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'> Method </th>
<th class='confluenceTh'> Description </th>
</tr>
<tr>
<td class='confluenceTd'> <tt>mockEndpoints</tt> </td>
<td class='confluenceTd'> Is used to easily mock all endpoints. See more details and
examples at <a href="/confluence/display/CAMEL/Mock" title="Mock">Mock</a>. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>mockEndpoints(pattern)</tt> </td>
<td class='confluenceTd'> Is used to easily mock endpoints using a pattern. See more
details and examples at <a href="/confluence/display/CAMEL/Mock" title="Mock">Mock</a>.
See below for pattern matching. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>weaveById(pattern)</tt> </td>
<td class='confluenceTd'> Is used to select node(s) matching by id's, and weave in the
following nodes. See below for pattern matching and examples. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>weaveByToString(pattern)</tt> </td>
<td class='confluenceTd'> Is used to select nodes(s) matching by their <tt>toString</tt>
representation, and weave in the following nodes. See below for pattern matching and examples.
</td>
</tr>
<tr>
<td class='confluenceTd'> <tt>weaveByType(Class)</tt> </td>
<td class='confluenceTd'> <b>Camel 2.8:</b> Is used to select node(s) matching
by their class type (the classes from the org.apache.camel.model package), and weave in the
following nodes. See below for examples. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>weaveAddFirst</tt> </td>
<td class='confluenceTd'> <b>Camel 2.8:</b> Is a short hand to easily weave
in the following nodes in the start of the route. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>weaveAddLast</tt> </td>
<td class='confluenceTd'> <b>Camel 2.8:</b> Is a short hand to easily weave
in the following nodes in the end of the route. </td>
</tr>
</tbody></table>
</div>


<p>The <tt>pattern</tt> option is used for matching. It uses the same rules
as the <a href="/confluence/display/CAMEL/Intercept" title="Intercept">Intercept</a>,
which is applied in the following order:</p>
<ul>
	<li>match exact</li>
	<li>match by wildcard</li>
	<li>match by regular expression</li>
</ul>


<p>For example to match exact you can use <tt>weaveById("foo")</tt> which
will match only the id in the route which has the value <tt>"foo"</tt>.<br/>
The wildcard is when the pattern ends with a * char, such as: <tt>weaveById("foo*")</tt>
which will match any id's starting with <tt>"foo"</tt>, such as <tt>foo,
foobar, foobie</tt> and so forth.<br/>
The regular expression is more advanced and allows you to match multiple ids, such as <tt>weaveById("(foo|bar)")</tt>
which will match both <tt>"foo"</tt> and <tt>"bar"</tt>.</p>


<h3><a name="AdviceWith-UsingweaveById"></a>Using weaveById</h3>

<p>The <tt>weaveById</tt> allows you to manipulate the rote, for example
by replacing a node with other nodes. The following methods is available:</p>

<div class='table-wrap'>
<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'> Method </th>
<th class='confluenceTh'> Description </th>
</tr>
<tr>
<td class='confluenceTd'> <tt>remove</tt> </td>
<td class='confluenceTd'> Removes the selected node(s). </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>replace</tt> </td>
<td class='confluenceTd'> Replaces the selected node(s) with the following nodes. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>before</tt> </td>
<td class='confluenceTd'> Before the selected node(s), the following nodes is added.
</td>
</tr>
<tr>
<td class='confluenceTd'> <tt>after</tt> </td>
<td class='confluenceTd'> After the selected node(s), the following nodes is added.
</td>
</tr>
</tbody></table>
</div>


<p>For example given the following route:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader"
style="border-bottom-width: 1px;"><b>Route</b></div><div class="codeContent
panelContent">
<pre class="code-java">
from(<span class="code-quote">"direct:start"</span>)
    .to(<span class="code-quote">"mock:foo"</span>)
    .to(<span class="code-quote">"mock:bar"</span>).id(<span class="code-quote">"bar"</span>)
    .to(<span class="code-quote">"mock:result"</span>);
</pre>
</div></div>

<p>Then let's go over the four methods to see how you can use them in unit tests:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader"
style="border-bottom-width: 1px;"><b>Replace</b></div><div class="codeContent
panelContent">
<pre class="code-java">context.getRouteDefinitions().get(0).adviceWith(context, <span
class="code-keyword">new</span> AdviceWithRouteBuilder() {
    @Override
    <span class="code-keyword">public</span> void configure() <span class="code-keyword">throws</span>
Exception {
        <span class="code-comment">// weave the node in the route which has id = bar
</span>        <span class="code-comment">// and replace it with the following
route path
</span>        weaveById(<span class="code-quote">"bar"</span>).replace().multicast().to(<span
class="code-quote">"mock:a"</span>).to(<span class="code-quote">"mock:b"</span>);
    }
});
</pre>
</div></div>

<p>In this example we replace the <tt>.to("mock:bar").id("bar")</tt> with
the <tt>.multicast().to("mock:a").to("mock:b")</tt>.<br/>
That means instead of sending the message to a <tt>"mock:bar"</tt> endpoint, we
do a <a href="/confluence/display/CAMEL/Multicast" title="Multicast">Multicast</a>
to <tt>"mock:a"</tt> and <tt>"mock:b"</tt> endpoints instead.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader"
style="border-bottom-width: 1px;"><b>Remove</b></div><div class="codeContent
panelContent">
<pre class="code-java">context.getRouteDefinitions().get(0).adviceWith(context, <span
class="code-keyword">new</span> AdviceWithRouteBuilder() {
    @Override
    <span class="code-keyword">public</span> void configure() <span class="code-keyword">throws</span>
Exception {
        <span class="code-comment">// weave the node in the route which has id = bar
and remove it
</span>        weaveById(<span class="code-quote">"bar"</span>).remove();
    }
});
</pre>
</div></div>
<p>In the example above, we simply just remove the <tt>.to("mock:bar").id("bar")</tt>.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader"
style="border-bottom-width: 1px;"><b>Before</b></div><div class="codeContent
panelContent">
<pre class="code-java">context.getRouteDefinitions().get(0).adviceWith(context, <span
class="code-keyword">new</span> AdviceWithRouteBuilder() {
    @Override
    <span class="code-keyword">public</span> void configure() <span class="code-keyword">throws</span>
Exception {
        <span class="code-comment">// weave the node in the route which has id = bar
</span>        <span class="code-comment">// and insert the following route path
before the adviced node
</span>        weaveById(<span class="code-quote">"bar"</span>).before().to(<span
class="code-quote">"mock:a"</span>).transform(constant(<span class="code-quote">"Bye
World"</span>));
    }
});
</pre>
</div></div>
<p>In the example above, we add the following nodes <tt>to("mock:a").transform(constant("Bye
World"))</tt> <b>before</b> the node with the id <tt>"bar"</tt>.<br/>
That means the message being send to <tt>"mock:bar"</tt> would have been transformed
to a constant message "Bye World".</p>

<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader"
style="border-bottom-width: 1px;"><b>After</b></div><div class="codeContent
panelContent">
<pre class="code-java">context.getRouteDefinitions().get(0).adviceWith(context, <span
class="code-keyword">new</span> AdviceWithRouteBuilder() {
    @Override
    <span class="code-keyword">public</span> void configure() <span class="code-keyword">throws</span>
Exception {
        <span class="code-comment">// weave the node in the route which has id = bar
</span>        <span class="code-comment">// and insert the following route path
after the advice node
</span>        weaveById(<span class="code-quote">"bar"</span>).after().to(<span
class="code-quote">"mock:a"</span>).transform(constant(<span class="code-quote">"Bye
World"</span>));
    }
});
</pre>
</div></div>
<p>In the example above, we add the following nodes <tt>to("mock:a").transform(constant("Bye
World"))</tt> <b>after</b> the node with the id <tt>"bar"</tt>.</p>

<h3><a name="AdviceWith-UsingweaveByToString"></a>Using weaveByToString</h3>

<p>The <tt>weaveByToString</tt> also allows you to manipulate the route,
for example by replacing a node with other nodes. As opposed to <tt>weaveById</tt>,
this method uses the <tt>toString</tt> representation of the node(s) when matching.
This allows you to match nodes, which may not have assigned ids, or to match <a href="/confluence/display/CAMEL/EIP"
title="EIP">EIP</a> pattern.<br/>
You have to be a bit more careful when using this as the <tt>toString</tt> representation
can be verbose and contain characters such as [ ] ( ) -&gt; and so forth. That is why
using the regular expression matching is the must useable.</p>

<p>The <tt>weaveByToString</tt> has the same methods as <tt>weaceById</tt>.</p>

<p>For example to replace any nodes which has <tt>"foo"</tt> you can do</p>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader"
style="border-bottom-width: 1px;"><b>Replace</b></div><div class="codeContent
panelContent">
<pre class="code-java">context.getRouteDefinitions().get(0).adviceWith(context, <span
class="code-keyword">new</span> AdviceWithRouteBuilder() {
    @Override
    <span class="code-keyword">public</span> void configure() <span class="code-keyword">throws</span>
Exception {
        <span class="code-comment">// weave nodes in the route which has foo anywhere
in their to string representation
</span>        <span class="code-comment">// and replace them with the following
route path
</span>        weaveByToString(<span class="code-quote">".*foo.*"</span>).replace().multicast().to(<span
class="code-quote">"mock:a"</span>).to(<span class="code-quote">"mock:b"</span>);
    }
});
</pre>
</div></div>

<p>Notice that we have to use <tt>".&#42;foo.&#42;"</tt> in the
pattern to match that <tt>"foo"</tt> is present anywhere in the string.</p>


<h3><a name="AdviceWith-UsingweaveByType"></a>Using weaveByType</h3>
<p><b>Available as of Camel 2.8</b></p>

<p>The <tt>weaveByToType</tt> also allows you to manipulate the route, for
example by replacing a node with other nodes. As opposed to <tt>weaveById</tt>,
and <tt>weaveByToString</tt> this method uses the class type of the node(s) when
matching. This allows you to match <a href="/confluence/display/CAMEL/EIP" title="EIP">EIP</a>
pattern by its type.</p>

<p>The <tt>weaveByToType</tt> has the same methods as <tt>weaceById</tt>
and <tt>weaveByToString</tt>.</p>

<p>For example to remove a transform from the following route:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader"
style="border-bottom-width: 1px;"><b>Route</b></div><div class="codeContent
panelContent">
<pre class="code-java">from(<span class="code-quote">"direct:start"</span>)
    .transform(simple(<span class="code-quote">"Hello ${body}"</span>))
    .log(<span class="code-quote">"Got ${body}"</span>)
    .to(<span class="code-quote">"mock:result"</span>);
</pre>
</div></div>

<p>You can do:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader"
style="border-bottom-width: 1px;"><b>Remove</b></div><div class="codeContent
panelContent">
<pre class="code-java">context.getRouteDefinitions().get(0).adviceWith(context, <span
class="code-keyword">new</span> AdviceWithRouteBuilder() {
    @Override
    <span class="code-keyword">public</span> void configure() <span class="code-keyword">throws</span>
Exception {
        <span class="code-comment">// weave the type in the route and remove it
</span>        weaveByType(TransformDefinition.class).remove();
    }
});
</pre>
</div></div>


<h3><a name="AdviceWith-Usingselectors"></a>Using selectors</h3>
<p><b>Available os of Camel 2.8</b></p>

<p>The following methods <tt>weaveById(pattern)</tt>, <tt>weaveByToString(pattern)</tt>
and <tt>weaveByType(Class)</tt> each match N+ nodes. By using optional selectors
you can narrow down the nodes being used. For example if <tt>weaveByType(Class)</tt>
returns 2 nodes. Then you can use a selector to indicate it should only select the first node.</p>

<div class='table-wrap'>
<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'> Selector </th>
<th class='confluenceTh'> Description </th>
</tr>
<tr>
<td class='confluenceTd'> <tt>selectFirst</tt> </td>
<td class='confluenceTd'> Will only select the first matched node. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>selectLast</tt> </td>
<td class='confluenceTd'> Will only select the last matched node. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>selectIndex(index)</tt> </td>
<td class='confluenceTd'> Will only select the n'th matched node. The index is zero-based.
</td>
</tr>
<tr>
<td class='confluenceTd'> <tt>selectRange(from, to)</tt> </td>
<td class='confluenceTd'> Will only select the matches node within the given range by
index (both inclusive). The index is zero-based. </td>
</tr>
</tbody></table>
</div>


<p>For example to remove the first <tt>.to</tt> node in route you can do
as follows:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
context.getRouteDefinitions().get(0).adviceWith(context, <span class="code-keyword">new</span>
AdviceWithRouteBuilder() {
    @Override
    <span class="code-keyword">public</span> void configure() <span class="code-keyword">throws</span>
Exception {
        <span class="code-comment">// only remove the first to node in the route
</span>        weaveByType(ToDefinition.class).selectFirst().remove();
    }
});
</pre>
</div></div>


<h3><a name="AdviceWith-UsingweaveAddFirst%2FweaveAddLast"></a>Using weaveAddFirst
/ weaveAddLast</h3>
<p><b>Available os of Camel 2.8</b></p>

<p>The <tt>weaveAddFirst</tt> and <tt>weaveAddLast</tt> is a
shorthand to easily add nodes to the route. These methods can only <b>add</b>
to an existing routes. If you want to manipulate the route, then there are plenty of methods
as already shown on this page.</p>

<p>For example if you want to send a message to a <tt>mock:input</tt> endpoint
you can do as follows:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
context.getRouteDefinitions().get(0).adviceWith(context, <span class="code-keyword">new</span>
AdviceWithRouteBuilder() {
    @Override
    <span class="code-keyword">public</span> void configure() <span class="code-keyword">throws</span>
Exception {
        <span class="code-comment">// send the incoming message to mock:input
</span>        weaveAddFirst().to(<span class="code-quote">"mock:input"</span>);
    }
});
</pre>
</div></div>

<p>Likewise if you want to easily send a message to a <tt>mock:output</tt>
endpoint you can do as follows:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
context.getRouteDefinitions().get(0).adviceWith(context, <span class="code-keyword">new</span>
AdviceWithRouteBuilder() {
    @Override
    <span class="code-keyword">public</span> void configure() <span class="code-keyword">throws</span>
Exception {
        <span class="code-comment">// send the outgoing message to mock:output
</span>        weaveAddLast().to(<span class="code-quote">"mock:output"</span>);
    }
});
</pre>
</div></div>

<p>You can of course combine those in the same advice with:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
context.getRouteDefinitions().get(0).adviceWith(context, <span class="code-keyword">new</span>
AdviceWithRouteBuilder() {
    @Override
    <span class="code-keyword">public</span> void configure() <span class="code-keyword">throws</span>
Exception {
        weaveAddFirst().to(<span class="code-quote">"mock:input"</span>);
        weaveAddLast().to(<span class="code-quote">"mock:output"</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/AdviceWith">View
Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=12321556&revisedVersion=9&originalVersion=8">View
Changes</a>
                |
        <a href="https://cwiki.apache.org/confluence/display/CAMEL/AdviceWith?showComments=true&amp;showCommentArea=true#addcomment">Add
Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message