camel-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Camel > Tutorial-Example-ReportIncident-Part2
Date Sun, 27 Jan 2013 11:17: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/Tutorial-Example-ReportIncident-Part2">Tutorial-Example-ReportIncident-Part2</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" >- [Part 4|Tutorial-Example-ReportIncident-Part4]
<br>- [Part 5|Tutorial-Example-ReportIncident-Part5] <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">-
[Part 6|Tutorial-Example-ReportIncident-Part6] <br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <h2><a name="Tutorial-Example-ReportIncident-Part2-Part2"></a>Part
2</h2>

<h2><a name="Tutorial-Example-ReportIncident-Part2-AddingCamel"></a>Adding
Camel</h2>
<p>In this part we will introduce Camel so we start by adding Camel to our pom.xml:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
       <span class="code-tag">&lt;properties&gt;</span>
            ...
            <span class="code-tag">&lt;camel-version&gt;</span>1.4.0<span
class="code-tag">&lt;/camel-version&gt;</span>
        <span class="code-tag">&lt;/properties&gt;</span>

        <span class="code-tag"><span class="code-comment">&lt;!-- camel --&gt;</span></span>
        <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-core<span
class="code-tag">&lt;/artifactId&gt;</span>
            <span class="code-tag">&lt;version&gt;</span>${camel-version}<span
class="code-tag">&lt;/version&gt;</span>
        <span class="code-tag">&lt;/dependency&gt;</span>
</pre>
</div></div>

<p>That's it, only <b>one</b> dependency for now.</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>Synchronize IDE</b><br
/>If you continue from part 1, remember to update your editor project settings since we
have introduce new .jar files. For instance IDEA has a feature to synchronize with Maven projects.</td></tr></table></div>

<p>Now we turn towards our webservice endpoint implementation where we want to let Camel
have a go at the input we receive. As Camel is very non invasive its basically a .jar file
then we can just grap Camel but creating a new instance of <tt>DefaultCamelContext</tt>
that is the hearth of Camel its context.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
CamelContext camel = <span class="code-keyword">new</span> DefaultCamelContext();
</pre>
</div></div>

<p>In fact we create a constructor in our webservice and add this code:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
    <span class="code-keyword">private</span> CamelContext camel;

    <span class="code-keyword">public</span> ReportIncidentEndpointImpl() <span
class="code-keyword">throws</span> Exception {
        <span class="code-comment">// create the camel context that is the <span
class="code-quote">"heart"</span> of Camel
</span>        camel = <span class="code-keyword">new</span> DefaultCamelContext();

        <span class="code-comment">// add the log component
</span>        camel.addComponent(<span class="code-quote">"log"</span>,
<span class="code-keyword">new</span> LogComponent());

        <span class="code-comment">// start Camel
</span>        camel.start();
    }
</pre>
</div></div>

<h2><a name="Tutorial-Example-ReportIncident-Part2-Loggingthe%22HelloWorld%22"></a>Logging
the "Hello World"</h2>
<p>Here at first we want Camel to log the <b>givenName</b> and <b>familyName</b>
parameters we receive, so we add the <tt>LogComponent</tt> with the key <b>log</b>.
And we must <b>start</b> Camel before its ready to act.</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>Component Documentation</b><br
/>The <a href="/confluence/display/CAMEL/Log" title="Log">Log</a> and <a
href="/confluence/display/CAMEL/File2" title="File2">File</a> components is documented
as well, just click on the links. Just return to this documentation later when you must use
these components for real.</td></tr></table></div>
<p>Then we change the code in the method that is invoked by Apache CXF when a webservice
request arrives. We get the name and let Camel have a go at it in the new method we create
<b>sendToCamel</b>:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
    <span class="code-keyword">public</span> OutputReportIncident reportIncident(InputReportIncident
parameters) {
        <span class="code-object">String</span> name = parameters.getGivenName()
+ <span class="code-quote">" "</span> + parameters.getFamilyName();

        <span class="code-comment">// let Camel <span class="code-keyword">do</span>
something with the name
</span>        sendToCamelLog(name);

        OutputReportIncident out = <span class="code-keyword">new</span> OutputReportIncident();
        out.setCode(<span class="code-quote">"OK"</span>);
        <span class="code-keyword">return</span> out;
    }
</pre>
</div></div>

<p>Next is the Camel code. At first it looks like there are many code lines to do a
simple task of logging the name - yes it is. But later you will in fact realize this is one
of Camels true power. Its concise API. Hint: The same code can be used for <b>any</b>
component in Camel.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
    <span class="code-keyword">private</span> void sendToCamelLog(<span class="code-object">String</span>
name) {
        <span class="code-keyword">try</span> {
            <span class="code-comment">// get the log component
</span>            Component component = camel.getComponent(<span class="code-quote">"log"</span>);

            <span class="code-comment">// create an endpoint and configure it.
</span>            <span class="code-comment">// Notice the URI parameters <span
class="code-keyword">this</span> is a common pratice in Camel to configure
</span>            <span class="code-comment">// endpoints based on URI.
</span>            <span class="code-comment">// com.mycompany.part2 = the log
category used. Will log at INFO level as <span class="code-keyword">default</span>
</span>            Endpoint endpoint = component.createEndpoint(<span class="code-quote">"log:com.mycompany.part2"</span>);

            <span class="code-comment">// create an Exchange that we want to send to
the endpoint
</span>            Exchange exchange = endpoint.createExchange();
            <span class="code-comment">// set the in message payload (=body) with the
name parameter
</span>            exchange.getIn().setBody(name);

            <span class="code-comment">// now we want to send the exchange to <span
class="code-keyword">this</span> endpoint and we then need a producer
</span>            <span class="code-comment">// <span class="code-keyword">for</span>
<span class="code-keyword">this</span>, so we create and start the producer.
</span>            Producer producer = endpoint.createProducer();
            producer.start();
            <span class="code-comment">// process the exchange will send the exchange
to the log component, that will process
</span>            <span class="code-comment">// the exchange and yes log the
payload
</span>            producer.process(exchange);

            <span class="code-comment">// stop the producer, we want to be nice and
cleanup
</span>            producer.stop();




        } <span class="code-keyword">catch</span> (Exception e) {
            <span class="code-comment">// we ignore any exceptions and just rethrow
as runtime
</span>            <span class="code-keyword">throw</span> <span class="code-keyword">new</span>
RuntimeException(e);

        }
    }
</pre>
</div></div>
<p>Okay there are code comments in the code block above that should explain what is
happening. We run the code by invoking our unit test with maven <tt>mvn test</tt>,
and we should get this log line:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
INFO: Exchange[BodyType:<span class="code-object">String</span>, Body:Claus Ibsen]
</pre>
</div></div>

<h2><a name="Tutorial-Example-ReportIncident-Part2-Writetofileeasywiththesamecodestyle"></a>Write
to file - easy with the same code style</h2>
<p>Okay that isn't to impressive, Camel can log <img class="emoticon" src="/confluence/images/icons/emoticons/wink.gif"
height="20" width="20" align="absmiddle" alt="" border="0"/> Well I promised that the above
code style can be used for <b>any</b> component, so let's store the payload in
a file. We do this by adding the file component to the Camel context</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
        <span class="code-comment">// add the file component
</span>        camel.addComponent(<span class="code-quote">"file"</span>,
<span class="code-keyword">new</span> FileComponent());
</pre>
</div></div>

<p>And then we let camel write the payload to the file after we have logged, by creating
a new method <b>sendToCamelFile</b>. We want to store the payload in filename
with the incident id so we need this parameter also:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
        <span class="code-comment">// let Camel <span class="code-keyword">do</span>
something with the name
</span>        sendToCamelLog(name);
        sendToCamelFile(parameters.getIncidentId(), name);
</pre>
</div></div>

<p>And then the code that is 99% identical. We have change the URI configuration when
we create the endpoint as we pass in configuration parameters to the file component.<br/>
And then we need to set the output filename and this is done by adding a special header to
the exchange. That's the only difference:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
    <span class="code-keyword">private</span> void sendToCamelFile(<span class="code-object">String</span>
incidentId, <span class="code-object">String</span> name) {
        <span class="code-keyword">try</span> {
            <span class="code-comment">// get the file component
</span>            Component component = camel.getComponent(<span class="code-quote">"file"</span>);

            <span class="code-comment">// create an endpoint and configure it.
</span>            <span class="code-comment">// Notice the URI parameters <span
class="code-keyword">this</span> is a common pratice in Camel to configure
</span>            <span class="code-comment">// endpoints based on URI.
</span>            <span class="code-comment">// file://target instructs the base
folder to output the files. We put in the target folder
</span>            <span class="code-comment">// then its actumatically cleaned
by mvn clean
</span>            Endpoint endpoint = component.createEndpoint(<span class="code-quote">"file:<span
class="code-comment">//target"</span>);
</span>
            <span class="code-comment">// create an Exchange that we want to send to
the endpoint
</span>            Exchange exchange = endpoint.createExchange();
            <span class="code-comment">// set the in message payload (=body) with the
name parameter
</span>            exchange.getIn().setBody(name);

            <span class="code-comment">// now a special header is set to instruct the
file component what the output filename
</span>            <span class="code-comment">// should be
</span>            exchange.getIn().setHeader(FileComponent.HEADER_FILE_NAME, <span
class="code-quote">"incident-"</span> + incidentId + <span class="code-quote">".txt"</span>);

            <span class="code-comment">// now we want to send the exchange to <span
class="code-keyword">this</span> endpoint and we then need a producer
</span>            <span class="code-comment">// <span class="code-keyword">for</span>
<span class="code-keyword">this</span>, so we create and start the producer.
</span>            Producer producer = endpoint.createProducer();
            producer.start();
            <span class="code-comment">// process the exchange will send the exchange
to the file component, that will process
</span>            <span class="code-comment">// the exchange and yes write the
payload to the given filename
</span>            producer.process(exchange);

            <span class="code-comment">// stop the producer, we want to be nice and
cleanup
</span>            producer.stop();
        } <span class="code-keyword">catch</span> (Exception e) {
            <span class="code-comment">// we ignore any exceptions and just rethrow
as runtime
</span>            <span class="code-keyword">throw</span> <span class="code-keyword">new</span>
RuntimeException(e);
        }
    }
</pre>
</div></div>

<p>After running our unit test again with <tt>mvn test</tt> we have a output
file in the target folder:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
D:\demo\part-two&gt;type target\incident-123.txt
Claus Ibsen
</pre>
</div></div>

<h2><a name="Tutorial-Example-ReportIncident-Part2-Fullyjavabasedconfigurationofendpoints"></a>Fully
java based configuration of endpoints</h2>
<p>In the file example above the configuration was URI based. What if you want 100%
java setter based style, well this is of course also possible. We just need to cast to the
component specific endpoint and then we have all the setters available:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
            <span class="code-comment">// create the file endpoint, we <span class="code-keyword">cast</span>
to FileEndpoint because then we can <span class="code-keyword">do</span>
</span>            <span class="code-comment">// 100% java settter based configuration
instead of the URI sting based
</span>            <span class="code-comment">// must pass in an empty string,
or part of the URI configuration <span class="code-keyword">if</span> wanted 
</span>            FileEndpoint endpoint = (FileEndpoint)component.createEndpoint("");
            endpoint.setFile(<span class="code-keyword">new</span> File(<span
class="code-quote">"target/subfolder"</span>));
            endpoint.setAutoCreate(<span class="code-keyword">true</span>);
</pre>
</div></div>
<p>That's it. Now we have used the setters to configure the <tt>FileEndpoint</tt>
that it should store the file in the folder target/subfolder. Of course Camel now stores the
file in the subfolder.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
D:\demo\part-two&gt;type target\subfolder\incident-123.txt
Claus Ibsen
</pre>
</div></div>

<h2><a name="Tutorial-Example-ReportIncident-Part2-Lessonslearned"></a>Lessons
learned</h2>
<p>Okay I wanted to demonstrate how you can be in 100% control of the configuration
and usage of Camel based on plain Java code with no hidden magic or special <b>XML</b>
or other configuration files. Just add the camel-core.jar and you are ready to go.</p>

<p>You must have noticed that the code for sending a message to a given endpoint is
the same for both the <b>log</b> and <b>file</b>, in fact <b>any</b>
Camel endpoint. You as the client shouldn't bother with component specific code such as file
stuff for file components, jms stuff for JMS messaging etc. This is what the <a href="/confluence/display/CAMEL/Message+Endpoint"
title="Message Endpoint">Message Endpoint</a> EIP pattern is all about and Camel
solves this very very nice - a key pattern in Camel.</p>

<h2><a name="Tutorial-Example-ReportIncident-Part2-Reducingcodelines"></a>Reducing
code lines</h2>
<p>Now that you have been introduced to Camel and one of its masterpiece patterns solved
elegantly with the <a href="/confluence/display/CAMEL/Message+Endpoint" title="Message
Endpoint">Message Endpoint</a> its time to give productive and show a solution in
fewer code lines, in fact we can get it down to 5, 4, 3, 2 .. yes only <b>1 line of
code</b>.</p>

<p>The key is the <b>ProducerTemplate</b> that is a Spring'ish xxxTemplate
based producer. Meaning that it has methods to send messages to any Camel endpoints. First
of all we need to get hold of such a template and this is done from the CamelContext</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
    <span class="code-keyword">private</span> ProducerTemplate template;

    <span class="code-keyword">public</span> ReportIncidentEndpointImpl() <span
class="code-keyword">throws</span> Exception {
        ...

        <span class="code-comment">// get the ProducerTemplate thst is a Spring'ish
xxxTemplate based producer <span class="code-keyword">for</span> very
</span>        <span class="code-comment">// easy sending exchanges to Camel.
</span>        template = camel.createProducerTemplate();

        <span class="code-comment">// start Camel
</span>        camel.start();
    }
</pre>
</div></div>

<p>Now we can use <b>template</b> for sending payloads to any endpoint in
Camel. So all the logging gabble can be reduced to:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
    template.sendBody(<span class="code-quote">"log:com.mycompany.part2.easy"</span>,
name);
</pre>
</div></div>

<p>And the same goes for the file, but we must also send the header to instruct what
the output filename should be:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
    <span class="code-object">String</span> filename = <span class="code-quote">"easy-incident-"</span>
+ incidentId + <span class="code-quote">".txt"</span>;
    template.sendBodyAndHeader(<span class="code-quote">"file:<span class="code-comment">//target/subfolder"</span>,
name, FileComponent.HEADER_FILE_NAME, filename);</span>
</pre>
</div></div>

<h2><a name="Tutorial-Example-ReportIncident-Part2-Reducingevenmorecodelines"></a>Reducing
even more code lines</h2>
<p>Well we got the Camel code down to 1-2 lines for sending the message to the component
that does all the heavy work of wring the message to a file etc. But we still got 5 lines
to initialize Camel.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
    camel = <span class="code-keyword">new</span> DefaultCamelContext();
    camel.addComponent(<span class="code-quote">"log"</span>, <span class="code-keyword">new</span>
LogComponent());
    camel.addComponent(<span class="code-quote">"file"</span>, <span class="code-keyword">new</span>
FileComponent());
    template = camel.createProducerTemplate();
    camel.start();
</pre>
</div></div>
<p>This can also be reduced. All the standard components in Camel is auto discovered
on-the-fly so we can remove these code lines and we are down to 3 lines.</p>

<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>Component
auto discovery</b><br />When an endpoint is requested with a scheme that Camel
hasn't seen before it will try to look for it in the classpath. It will do so by looking for
special Camel component marker files that reside in the folder <tt>META-INF/services/org/apache/camel/component</tt>.
If there are files in this folder it will read them as the filename is the <b>scheme</b>
part of the URL. For instance the <b>log</b> component is defined in this file
<tt>META-INF/services/org/apache/component/log</tt> and its content is:
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
class=org.apache.camel.component.log.LogComponent
</pre>
</div></div>
<p>The class property defines the component implementation.</p>

<p><b>Tip:</b> End-users can create their 3rd party components using the
same technique and have them been auto discovered on-the-fly.</p></td></tr></table></div>

<p>Okay back to the 3 code lines:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
    camel = <span class="code-keyword">new</span> DefaultCamelContext();
    template = camel.createProducerTemplate();
    camel.start();
</pre>
</div></div>
<p>Later will we see how we can reduce this to ... in fact 0 java code lines. But the
3 lines will do for now.</p>

<h2><a name="Tutorial-Example-ReportIncident-Part2-MessageTranslation"></a>Message
Translation</h2>
<p>Okay lets head back to the over goal of the integration. Looking at the EIP diagrams
at the introduction page we need to be able to translate the incoming webservice to an email.
Doing so we need to create the email body. When doing the message translation we could put
up our sleeves and do it manually in pure java with a StringBuilder such as:</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>
createMailBody(InputReportIncident parameters) {
        StringBuilder sb = <span class="code-keyword">new</span> StringBuilder();
        sb.append(<span class="code-quote">"Incident "</span>).append(parameters.getIncidentId());
        sb.append(<span class="code-quote">" has been reported on the "</span>).append(parameters.getIncidentDate());
        sb.append(<span class="code-quote">" by "</span>).append(parameters.getGivenName());
        sb.append(<span class="code-quote">" "</span>).append(parameters.getFamilyName());
        
        <span class="code-comment">// and the <span class="code-keyword">rest</span>
of the mail body with more appends to the string builder
</span>        
        <span class="code-keyword">return</span> sb.toString();
    }
</pre>
</div></div>
<p>But as always it is a hardcoded template for the mail body and the code gets kinda
ugly if the mail message has to be a bit more advanced. But of course it just works out-of-the-box
with just classes already in the JDK.</p>

<p>Lets use a template language instead such as <a href="http://velocity.apache.org/"
class="external-link" rel="nofollow">Apache Velocity</a>. As Camel have a component
for <a href="/confluence/display/CAMEL/Velocity" title="Velocity">Velocity</a>
integration we will use this component. Looking at the <a href="/confluence/display/CAMEL/Component"
title="Component">Component List</a> overview we can see that camel-velocity component
uses the artifactId <b>camel-velocity</b> so therefore we need to add this to
the <b>pom.xml</b></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-velocity<span
class="code-tag">&lt;/artifactId&gt;</span>
            <span class="code-tag">&lt;version&gt;</span>${camel-version}<span
class="code-tag">&lt;/version&gt;</span>
        <span class="code-tag">&lt;/dependency&gt;</span>
</pre>
</div></div>

<p>And now we have a Spring conflict as Apache CXF is dependent on Spring 2.0.8 and
camel-velocity is dependent on Spring 2.5.5. To remedy this we could wrestle with the <b>pom.xml</b>
with excludes settings in the dependencies or just bring in another dependency <b>camel-spring</b>:</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-spring<span
class="code-tag">&lt;/artifactId&gt;</span>
            <span class="code-tag">&lt;version&gt;</span>${camel-version}<span
class="code-tag">&lt;/version&gt;</span>
        <span class="code-tag">&lt;/dependency&gt;</span>
</pre>
</div></div>

<p>In fact camel-spring is such a vital part of Camel that you will end up using it
in nearly all situations - we will look into how well Camel is seamless integration with Spring
in part 3. For now its just another dependency. </p>

<p>We create the mail body with the Velocity template and create the file <tt>src/main/resources/MailBody.vm</tt>.
The content in the <b>MailBody.vm</b> file is:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
Incident $body.incidentId has been reported on the $body.incidentDate by $body.givenName $body.familyName.

The person can be contact by:
- email: $body.email
- phone: $body.phone

Summary: $body.summary

Details:
$body.details

This is an auto generated email. You can not reply.
</pre>
</div></div>

<p>Letting Camel creating the mail body and storing it as a file is as easy as the following
3 code lines:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
    <span class="code-keyword">private</span> void generateEmailBodyAndStoreAsFile(InputReportIncident
parameters) {
        <span class="code-comment">// generate the mail body using velocity template
</span>        <span class="code-comment">// notice that we just pass in our POJO
(= InputReportIncident) that we
</span>        <span class="code-comment">// got from Apache CXF to Velocity.
</span>        <span class="code-object">Object</span> response = template.sendBody(<span
class="code-quote">"velocity:MailBody.vm"</span>, parameters);
        <span class="code-comment">// Note: the response is a <span class="code-object">String</span>
and can be <span class="code-keyword">cast</span> to <span class="code-object">String</span>
<span class="code-keyword">if</span> needed
</span>
        <span class="code-comment">// store the mail in a file
</span>        <span class="code-object">String</span> filename = <span
class="code-quote">"mail-incident-"</span> + parameters.getIncidentId() + <span
class="code-quote">".txt"</span>;
        template.sendBodyAndHeader(<span class="code-quote">"file:<span class="code-comment">//target/subfolder"</span>,
response, FileComponent.HEADER_FILE_NAME, filename);
</span>    }
</pre>
</div></div>

<p>What is impressive is that we can just pass in our POJO object we got from Apache
CXF to Velocity and it will be able to generate the mail body with this object in its context.
Thus we don't need to prepare <b>anything</b> before we let Velocity loose and
generate our mail body. Notice that the <b>template</b> method returns a object
with out response. This object contains the mail body as a String object. We can cast to String
if needed. </p>

<p>If we run our unit test with <tt>mvn test</tt> we can in fact see that
Camel has produced the file and we can type its content:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
D:\demo\part-two&gt;type target\subfolder\mail-incident-123.txt
Incident 123 has been reported on the 2008-07-16 by Claus Ibsen.

The person can be contact by:
- email: davsclaus@apache.org
- phone: +45 2962 7576

Summary: bla bla

Details:
more bla bla

This is an auto generated email. You can not reply.
</pre>
</div></div>

<h2><a name="Tutorial-Example-ReportIncident-Part2-Firstpartofthesolution"></a>First
part of the solution</h2>
<p>What we have seen here is actually what it takes to build the first part of the integration
flow. Receiving a request from a webservice, transform it to a mail body and store it to a
file, and return an OK response to the webservice. All possible within 10 lines of code. So
lets wrap it up here is what it takes:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
/**
 * The webservice we have implemented.
 */
<span class="code-keyword">public</span> class ReportIncidentEndpointImpl <span
class="code-keyword">implements</span> ReportIncidentEndpoint {

    <span class="code-keyword">private</span> CamelContext camel;
    <span class="code-keyword">private</span> ProducerTemplate template;

    <span class="code-keyword">public</span> ReportIncidentEndpointImpl() <span
class="code-keyword">throws</span> Exception {
        <span class="code-comment">// create the camel context that is the <span
class="code-quote">"heart"</span> of Camel
</span>        camel = <span class="code-keyword">new</span> DefaultCamelContext();

        <span class="code-comment">// get the ProducerTemplate thst is a Spring'ish
xxxTemplate based producer <span class="code-keyword">for</span> very
</span>        <span class="code-comment">// easy sending exchanges to Camel.
</span>        template = camel.createProducerTemplate();

        <span class="code-comment">// start Camel
</span>        camel.start();
    }

    <span class="code-keyword">public</span> OutputReportIncident reportIncident(InputReportIncident
parameters) {
        <span class="code-comment">// transform the request into a mail body
</span>        <span class="code-object">Object</span> mailBody = template.sendBody(<span
class="code-quote">"velocity:MailBody.vm"</span>, parameters);

        <span class="code-comment">// store the mail body in a file
</span>        <span class="code-object">String</span> filename = <span
class="code-quote">"mail-incident-"</span> + parameters.getIncidentId() + <span
class="code-quote">".txt"</span>;
        template.sendBodyAndHeader(<span class="code-quote">"file:<span class="code-comment">//target/subfolder"</span>,
mailBody, FileComponent.HEADER_FILE_NAME, filename);
</span>
        <span class="code-comment">// <span class="code-keyword">return</span>
an OK reply
</span>        OutputReportIncident out = <span class="code-keyword">new</span>
OutputReportIncident();
        out.setCode(<span class="code-quote">"OK"</span>);
        <span class="code-keyword">return</span> out;
    }

}
</pre>
</div></div>
<p>Okay I missed by one, its in fact only <b>9 lines of java code and 2 fields</b>.</p>

<h2><a name="Tutorial-Example-ReportIncident-Part2-Endofpart2"></a>End of
part 2</h2>
<p>I know this is a bit different introduction to Camel to how you can start using it
in your projects just as a plain java .jar framework that isn't invasive at all. I took you
through the coding parts that requires 6 - 10 lines to send a message to an endpoint, buts
it's important to show the <a href="/confluence/display/CAMEL/Message+Endpoint" title="Message
Endpoint">Message Endpoint</a> EIP pattern in action and how its implemented in Camel.
Yes of course Camel also has to one liners that you can use, and will use in your projects
for sending messages to endpoints. This part has been about good old plain java, nothing fancy
with Spring, XML files, auto discovery, OGSi or other new technologies. I wanted to demonstrate
the basic building blocks in Camel and how its setup in pure god old fashioned Java. There
are plenty of eye catcher examples with one liners that does more than you can imagine - we
will come there in the later parts. </p>

<p>Okay part 3 is about building the last pieces of the solution and now it gets interesting
since we have to wrestle with the event driven consumer.<br/>
Brew a cup of coffee, tug the kids and kiss the wife, for now we will have us some fun with
the Camel. See you in part 3.</p>

<h2><a name="Tutorial-Example-ReportIncident-Part2-Links"></a>Links</h2>
<ul class="alternate" type="square">
	<li><a href="/confluence/display/CAMEL/Tutorial-Example-ReportIncident" title="Tutorial-Example-ReportIncident">Introduction</a></li>
	<li><a href="/confluence/display/CAMEL/Tutorial-Example-ReportIncident-Part1" title="Tutorial-Example-ReportIncident-Part1">Part
1</a></li>
	<li><a href="/confluence/display/CAMEL/Tutorial-Example-ReportIncident-Part2" title="Tutorial-Example-ReportIncident-Part2">Part
2</a></li>
	<li><a href="/confluence/display/CAMEL/Tutorial-Example-ReportIncident-Part3" title="Tutorial-Example-ReportIncident-Part3">Part
3</a></li>
	<li><a href="/confluence/display/CAMEL/Tutorial-Example-ReportIncident-Part4" title="Tutorial-Example-ReportIncident-Part4">Part
4</a></li>
	<li><a href="/confluence/display/CAMEL/Tutorial-Example-ReportIncident-Part5" title="Tutorial-Example-ReportIncident-Part5">Part
5</a></li>
	<li><a href="/confluence/display/CAMEL/Tutorial-Example-ReportIncident-Part6" title="Tutorial-Example-ReportIncident-Part6">Part
6</a></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/Tutorial-Example-ReportIncident-Part2">View
Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=90919&revisedVersion=24&originalVersion=23">View
Changes</a>
                |
        <a href="https://cwiki.apache.org/confluence/display/CAMEL/Tutorial-Example-ReportIncident-Part2?showComments=true&amp;showCommentArea=true#addcomment">Add
Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message