camel-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Camel > OnCompletion
Date Thu, 23 Aug 2012 07:01: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/OnCompletion">OnCompletion</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" >The *onCompletion* DSL allows you
to add custom routes/processors when the original [Exchange] is complete. Camel spin off a
copy of the [Exchange] and routes it in a separate thread, kinda like a [Wire Tap]. This allows
the original thread to continue while the *onCompletion* route is running concurrently. We
decided for this model as we did not want the *onCompletion* route to interfere with the original
route. <br> <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">{note:title=Only
1 onCompletion supported by route scope} <br>You can only have 1 onCompletion in a route.
Only at context scoped level you can have multiple. And notice that when you use a route scoped
onCompletion then any context scoped are disabled for that given route. <br>{note} <br></td></tr>
            <tr><td class="diff-unchanged" > <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/OnCompletionTest.java}
<br> <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <h2><a name="OnCompletion-OnCompletion"></a>OnCompletion</h2>

<p>Camel has this concept of a Unit of Work that encompass the <a href="/confluence/display/CAMEL/Exchange"
title="Exchange">Exchange</a>. The unit of work among others supports synchronization
callbacks that are invoked when the <a href="/confluence/display/CAMEL/Exchange" title="Exchange">Exchange</a>
is complete. The callback API is defined in <tt>org.apache.camel.spi.Synchronization</tt>.</p>

<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td
valign='top'><img src="/confluence/images/icons/emoticons/check.gif" width="16" height="16"
align="absmiddle" alt="" border="0"></td><td><b>Getting the UnitOfWork</b><br
/>You can get hold of the <tt>org.apache.camel.spi.UnitOfWork</tt> from <tt>org.apache.camel.Exchange</tt>
with the method <tt>getUnitOfWork()</tt>.</td></tr></table></div>

<p>In Camel 2.0 we have added DSL for these callbacks using the new <b>onCompletion</b>
DSL name.</p>

<p><b>onCompletion</b> supports the following features:</p>
<ul class="alternate" type="square">
	<li>scope: global and/or per route (route scope override all global scope)</li>
	<li>multiple global scope</li>
	<li>triggered either always, only if completed with success, or only if failed</li>
	<li><tt>onWhen</tt> predicate to only trigger in certain situations</li>
</ul>


<div class='panelMacro'><table class='infoMacro'><colgroup><col width='24'><col></colgroup><tr><td
valign='top'><img src="/confluence/images/icons/emoticons/information.gif" width="16"
height="16" align="absmiddle" alt="" border="0"></td><td><b>On completion
runs in separate thread</b><br />The <b>onCompletion</b> runs in a
separate thread in parallel with the original route. It is therefore not intended to influence
the outcome of the original route. The idea for on completion is to spin off a new thread
to eg send logs to a central log database, send an email, send alterts to a monitoring system,
store a copy of the result message etc.<br/>
Therefore if you want to do some work that influence the original route, then do <b>not</b>
use <b>onCompletion</b> for that. Notice: if you use the <tt>UnitOfWork</tt>
API as mentioned in the top of this page, then you can register a <tt>Synchronization</tt>
callback on the <a href="/confluence/display/CAMEL/Exchange" title="Exchange">Exchange</a>
which is executed in the original route. That way allows you to do some custom code when the
route is completed; this is how custom components can enlist on completion services which
they need, eg the <a href="/confluence/display/CAMEL/File2" title="File2">File</a>
component does that for work that moves/deletes the original file etc.</td></tr></table></div>

<h3><a name="OnCompletion-onCompletionwithroutescope"></a>onCompletion with
route scope</h3>
<p>The <b>onCompletion</b> DSL allows you to add custom routes/processors
when the original <a href="/confluence/display/CAMEL/Exchange" title="Exchange">Exchange</a>
is complete. Camel spin off a copy of the <a href="/confluence/display/CAMEL/Exchange"
title="Exchange">Exchange</a> and routes it in a separate thread, kinda like a <a
href="/confluence/display/CAMEL/Wire+Tap" title="Wire Tap">Wire Tap</a>. This allows
the original thread to continue while the <b>onCompletion</b> route is running
concurrently. We decided for this model as we did not want the <b>onCompletion</b>
route to interfere with the original route.</p>

<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td
valign='top'><img src="/confluence/images/icons/emoticons/warning.gif" width="16" height="16"
align="absmiddle" alt="" border="0"></td><td><b>Only 1 onCompletion supported
by route scope</b><br />You can only have 1 onCompletion in a route. Only at context
scoped level you can have multiple. And notice that when you use a route scoped onCompletion
then any context scoped are disabled for that given route.</td></tr></table></div>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">from(<span class="code-quote">"direct:start"</span>)
    .onCompletion()
        <span class="code-comment">// <span class="code-keyword">this</span>
route is only invoked when the original route is complete as a kind
</span>        <span class="code-comment">// of completion callback
</span>        .to(<span class="code-quote">"log:sync"</span>)
        .to(<span class="code-quote">"mock:sync"</span>)
    <span class="code-comment">// must use end to denote the end of the onCompletion
route
</span>    .end()
    <span class="code-comment">// here the original route contiues
</span>    .process(<span class="code-keyword">new</span> MyProcessor())
    .to(<span class="code-quote">"mock:result"</span>);
</pre>
</div></div>

<p>By default the <b>onCompletion</b> will be triggered when the <a href="/confluence/display/CAMEL/Exchange"
title="Exchange">Exchange</a> is complete and regardless if the <a href="/confluence/display/CAMEL/Exchange"
title="Exchange">Exchange</a> completed with success or with an failure (such as
an Exception was thrown). You can limit the trigger to only occur <tt>onCompleteOnly</tt>
or by <tt>onFauilureOnly</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">// here we qualify onCompletion to only invoke when the
exchange failed (exception or FAULT body)
</span>    .onCompletion().onFailureOnly()
        .to(<span class="code-quote">"log:sync"</span>)
        .to(<span class="code-quote">"mock:sync"</span>)
    <span class="code-comment">// must use end to denote the end of the onCompletion
route
</span>    .end()
    <span class="code-comment">// here the original route contiues
</span>    .process(<span class="code-keyword">new</span> MyProcessor())
    .to(<span class="code-quote">"mock:result"</span>);
</pre>
</div></div>

<p>You can identify if the <a href="/confluence/display/CAMEL/Exchange" title="Exchange">Exchange</a>
is an <b>onCompletion</b> <a href="/confluence/display/CAMEL/Exchange" title="Exchange">Exchange</a>
as Camel will add the property <tt>Exchange.ON_COMPLETION</tt> with a boolean
value of <tt>true</tt> when it spin offs the <b>onCompletion</b> <a
href="/confluence/display/CAMEL/Exchange" title="Exchange">Exchange</a>.</p>


<h4><a name="OnCompletion-UsingonCompletionfromSpringDSL"></a>Using onCompletion
from Spring DSL</h4>
<p>The onCompletion is defined like this with Spring DSL:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml"><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"><span class="code-comment">&lt;!-- this onCompletion
block will only be executed when the exchange is done being routed --&gt;</span></span>
    <span class="code-tag"><span class="code-comment">&lt;!-- this callback
is always triggered even if the exchange failed --&gt;</span></span>
    <span class="code-tag">&lt;onCompletion&gt;</span>
        <span class="code-tag"><span class="code-comment">&lt;!-- so this
is a kinda like an after completion callback --&gt;</span></span>
        <span class="code-tag">&lt;to uri=<span class="code-quote">"log:sync"</span>/&gt;</span>
        <span class="code-tag">&lt;to uri=<span class="code-quote">"mock:sync"</span>/&gt;</span>
    <span class="code-tag">&lt;/onCompletion&gt;</span>
    <span class="code-tag">&lt;process ref=<span class="code-quote">"myProcessor"</span>/&gt;</span>
    <span class="code-tag">&lt;to uri=<span class="code-quote">"mock:result"</span>/&gt;</span>
<span class="code-tag">&lt;/route&gt;</span>
</pre>
</div></div>

<p>And the <tt>onCompleteOnly</tt> and <tt>onFailureOnly</tt>
is defined as a boolean attribute on the &lt;onCompletion&gt; tag so the failure example
would be:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml"><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"><span class="code-comment">&lt;!-- this onCompletion
block will only be executed when the exchange is done being routed --&gt;</span></span>
    <span class="code-tag"><span class="code-comment">&lt;!-- this callback
is only triggered when the exchange failed, as we have onFailure=true --&gt;</span></span>
    <span class="code-tag">&lt;onCompletion onFailureOnly=<span class="code-quote">"true"</span>&gt;</span>
        <span class="code-tag">&lt;to uri=<span class="code-quote">"log:sync"</span>/&gt;</span>
        <span class="code-tag">&lt;to uri=<span class="code-quote">"mock:sync"</span>/&gt;</span>
    <span class="code-tag">&lt;/onCompletion&gt;</span>
    <span class="code-tag">&lt;process ref=<span class="code-quote">"myProcessor"</span>/&gt;</span>
    <span class="code-tag">&lt;to uri=<span class="code-quote">"mock:result"</span>/&gt;</span>
<span class="code-tag">&lt;/route&gt;</span>
</pre>
</div></div>

<h3><a name="OnCompletion-onCompletionwithglobalscope"></a>onCompletion
with global scope</h3>
<p>This works just like the route scope except from the fact that they are defined globally.
An example below:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-comment">// define a global on completion
that is invoked when the exchange is complete
</span>onCompletion().to(<span class="code-quote">"log:global"</span>).to(<span
class="code-quote">"mock:sync"</span>);

from(<span class="code-quote">"direct:start"</span>)
    .process(<span class="code-keyword">new</span> MyProcessor())
    .to(<span class="code-quote">"mock:result"</span>);
</pre>
</div></div>

<h4><a name="OnCompletion-UsingonCompletionfromSpringDSL"></a>Using onCompletion
from Spring DSL</h4>
<p>This works just like the route scope except from the fact that they are defined globally.
An example below:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">&lt;!-- this is a global onCompletion route that is invoke
when any exchange is complete
     as a kind of after callback --&gt;
<span class="code-tag">&lt;onCompletion&gt;</span>
    <span class="code-tag">&lt;to uri=<span class="code-quote">"log:global"</span>/&gt;</span>
    <span class="code-tag">&lt;to uri=<span class="code-quote">"mock:sync"</span>/&gt;</span>
<span class="code-tag">&lt;/onCompletion&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;process ref=<span class="code-quote">"myProcessor"</span>/&gt;</span>
    <span class="code-tag">&lt;to uri=<span class="code-quote">"mock:result"</span>/&gt;</span>
<span class="code-tag">&lt;/route&gt;</span>
</pre>
</div></div>

<div class='panelMacro'><table class='infoMacro'><colgroup><col width='24'><col></colgroup><tr><td
valign='top'><img src="/confluence/images/icons/emoticons/information.gif" width="16"
height="16" align="absmiddle" alt="" border="0"></td><td><b>Route scope
override Global scope</b><br />If an <b>onCompletion</b> is defined
in a route, it overrides <b>all</b> global scoped and thus its only the route
scoped that are used. The globally scoped ones are never used.</td></tr></table></div>

<h3><a name="OnCompletion-UsingonCompletionwithonWhenpredicate"></a>Using
onCompletion with onWhen predicate</h3>
<p>As other DSL in Camel you can attach a <a href="/confluence/display/CAMEL/Predicate"
title="Predicate">Predicate</a> to the <b>onCompletion</b> so it only
triggers in certain conditions, when the predicate matches.<br/>
For example to only trigger if the message body contains the word <tt>Hello</tt>
we can do like:</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>)
    .onCompletion().onWhen(body().contains(<span class="code-quote">"Hello"</span>))
        <span class="code-comment">// <span class="code-keyword">this</span>
route is only invoked when the original route is complete as a kind
</span>        <span class="code-comment">// of completion callback. And also
only <span class="code-keyword">if</span> the onWhen predicate is <span class="code-keyword">true</span>
</span>        .to(<span class="code-quote">"log:sync"</span>)
        .to(<span class="code-quote">"mock:sync"</span>)
    <span class="code-comment">// must use end to denote the end of the onCompletion
route
</span>    .end()
    <span class="code-comment">// here the original route contiues
</span>    .to(<span class="code-quote">"log:original"</span>)
    .to(<span class="code-quote">"mock:result"</span>);
</pre>
</div></div>

<h3><a name="OnCompletion-SeeAlso"></a>See Also</h3>
<ul class="alternate" type="square">
	<li>Unit of Work</li>
</ul>

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

Mime
View raw message