<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.5">Jekyll</generator><link href="http://juliuskrah.com/feed.xml" rel="self" type="application/atom+xml" /><link href="http://juliuskrah.com/" rel="alternate" type="text/html" /><updated>2024-07-04T19:57:08+00:00</updated><id>http://juliuskrah.com/feed.xml</id><title type="html">Software Musings</title><subtitle>Software Musings is my attempt to document the little things I have learnt, for reference later. Some of the things I document, include Web Application Development, Web Services, Microservices, Docker, Java and Python. Once I gain a broader understanding of a topic, I will document it in this blog.
</subtitle><author><name>juliuskrah</name></author><entry><title type="html">Build a Laravel Docker Image Using a Dockerfile</title><link href="http://juliuskrah.com/blog/2020/10/01/build-a-laravel-docker-image/" rel="alternate" type="text/html" title="Build a Laravel Docker Image Using a Dockerfile" /><published>2020-10-01T10:27:31+00:00</published><updated>2020-10-01T10:27:31+00:00</updated><id>http://juliuskrah.com/blog/2020/10/01/build-a-laravel-docker-image</id><content type="html" xml:base="http://juliuskrah.com/blog/2020/10/01/build-a-laravel-docker-image/"><![CDATA[<blockquote>
  <p>Laravel is a modern web application framework for artisans.</p>
</blockquote>

<h1 id="introduction">Introduction</h1>

<p>Building a dockerfile for a <code class="language-plaintext highlighter-rouge">Laravel</code> application does not need to be tedious. The good folks at
<a href="https://github.com/thecodingmachine/docker-images-php" target="_blank">The Coding Machine</a> have created several base images that we can leverage.</p>

<h2 id="prerequisites">Prerequisites</h2>

<p>You need to have the following setup on your development machine to proceed with this tutorial</p>

<ol>
  <li><a href="https://www.php.net/" target="_blank">PHP &gt;= 7.3</a></li>
  <li><a href="https://getcomposer.org/download/" target="_blank">Composer</a></li>
  <li><a href="https://laravel.com/docs/8.x#installation" target="_blank">Laravel</a></li>
  <li><a href="https://www.docker.com/products/docker-desktop" target="_blank">Docker</a></li>
</ol>

<h2 id="lets-get-started">Let’s get started</h2>

<p>Create a new laravel project</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span> laravel new laravel-app
</code></pre></div></div>

<p>and navigate into the <code class="language-plaintext highlighter-rouge">laravel-app</code> directory and execute the following command:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span> php artisan serve
</code></pre></div></div>

<p>Try it out in your browser <a href="http://localhost:8000" target="_blank">localhost:8000</a></p>

<p>Before we create our <code class="language-plaintext highlighter-rouge">Dockerfile</code> lets first create a <code class="language-plaintext highlighter-rouge">.dockerignore</code> file:</p>

<p>file: <code class="language-plaintext highlighter-rouge">laravel-app\.dockerignore</code></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>node_modules/
public/hot/
public/storage/
storage/*.key
vendor/
.env.backup
.phpunit.result.cache
Homestead.json
Homestead.yaml
npm-debug.log
yarn-error.log
Dockerfile
docker-compose.yml
docker-compose.yaml
**.git
.idea
**.gitignore
**.gitattributes
**.sass-cache
</code></pre></div></div>

<p>We can now create our <code class="language-plaintext highlighter-rouge">Dockerfile</code>:</p>

<p>file: <code class="language-plaintext highlighter-rouge">laravel-app\Dockerfile</code></p>

<div class="language-dockerfile highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">ARG</span><span class="s"> PHP_EXTENSIONS="intl pdo_mysql pdo_pgsql bcmath"</span>

<span class="k">FROM</span><span class="w"> </span><span class="s">thecodingmachine/php:7.4-v3-slim-apache</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="s">php_base</span>
<span class="k">LABEL</span><span class="s"> maintainer "Julius Krah &lt;juliuskrah@gmail.com&gt;"</span>

<span class="k">ENV</span><span class="s"> TEMPLATE_PHP_INI=production</span>
<span class="k">COPY</span><span class="s"> --chown=docker:docker . /var/www/html</span>
<span class="k">RUN </span>composer <span class="nb">install</span> <span class="nt">--quiet</span> <span class="nt">--optimize-autoloader</span> <span class="nt">--no-dev</span>

<span class="k">FROM</span><span class="w"> </span><span class="s">node:10</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="s">node_dependencies</span>
<span class="k">WORKDIR</span><span class="s"> /var/www/html</span>

<span class="k">ENV</span><span class="s"> PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=false</span>
<span class="k">COPY</span><span class="s"> --from=php_base /var/www/html /var/www/html</span>

<span class="k">RUN </span>npm <span class="nb">set </span><span class="nv">progress</span><span class="o">=</span><span class="nb">false</span> <span class="o">&amp;&amp;</span> <span class="se">\
</span>  npm config <span class="nb">set </span>depth 0 <span class="o">&amp;&amp;</span> <span class="se">\
</span>  npm <span class="nb">install</span> <span class="o">&amp;&amp;</span> <span class="se">\
</span>  npm run prod <span class="o">&amp;&amp;</span> <span class="se">\
</span>  <span class="nb">rm</span> <span class="nt">-rf</span> node_modules

<span class="k">FROM</span><span class="s"> php_base</span>
<span class="k">ENV</span><span class="s"> APACHE_DOCUMENT_ROOT=/var/www/html/public</span>
<span class="k">COPY</span><span class="s"> --from=node_dependencies --chown=docker:docker /var/www/html /var/www/html</span>
</code></pre></div></div>

<p>Build and tag the image:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span> docker build <span class="nt">-t</span> laravel-app <span class="nb">.</span>
</code></pre></div></div>

<p>Time to test our image with a container</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span> docker run <span class="nt">--rm</span> <span class="nt">--name</span> laravel <span class="nt">-e</span> <span class="nv">DB_CONNECTION</span><span class="o">=</span>pgsql <span class="nt">-p</span> 8000:80 laravel-app
</code></pre></div></div>

<p>NOTE: <em>You can replace all options in the <code class="language-plaintext highlighter-rouge">.env</code> file with environment variables on the command line e.g.
<code class="language-plaintext highlighter-rouge">-e DB_CONNECTION=pgsql</code></em></p>

<h2 id="conclusion">Conclusion</h2>

<p>An optional step is to tag and upload your image to docker hub:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span> docker tag laravel-app &lt;username&gt;/laravel-app
<span class="o">&gt;</span> docker login
<span class="o">&gt;</span> docker push &lt;username&gt;/laravel-app
</code></pre></div></div>

<p>In this post we discussed creating a laravel project and making an OCI image out of it. Until the next post, keep
doing cool things :+1:.</p>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;juliuskrah&quot;}</name></author><category term="blog" /><category term="php" /><category term="laravel" /><category term="docker" /><summary type="html"><![CDATA[Laravel is a modern web application framework for artisans.]]></summary></entry><entry><title type="html">Building an SMPP Application using Spring Boot and Camel</title><link href="http://juliuskrah.com/blog/2020/03/27/building-an-smpp-application-using-spring-boot-and-camel/" rel="alternate" type="text/html" title="Building an SMPP Application using Spring Boot and Camel" /><published>2020-03-27T18:32:25+00:00</published><updated>2020-03-27T18:32:25+00:00</updated><id>http://juliuskrah.com/blog/2020/03/27/building-an-smpp-application-using-spring-boot-and-camel</id><content type="html" xml:base="http://juliuskrah.com/blog/2020/03/27/building-an-smpp-application-using-spring-boot-and-camel/"><![CDATA[<blockquote>
  <p>Short Message Peer-to-Peer (SMPP) is a protocol used by the telecommunications industry for exchanging
  messages between Short Message Service Centers (SMSC) and/or External Short Messaging Entities (ESME).</p>
</blockquote>

<h1 id="introduction">Introduction</h1>

<p>In this post I will build a simple app that will send SMS using the SMPP protocol, bootstraped with
Spring Boot and <a href="https://camel.apache.org/components/latest/smpp-component.html" target="_blank">Camel</a>. To use <code class="language-plaintext highlighter-rouge">CloudHopper</code> to send SMS refer to the
<a href="/blog/2018/12/28/building-an-smpp-application-using-spring-boot/">CloudHopper Post</a>.</p>

<p>SMPP is a level-7 TCP/IP protocol, which allows fast delivery of SMS messages. The most conmmonly used
versions of SMPP are v3.3, the most widely supported standard, and v3.4, which adds transceiver support
(single connections that can send and receive messages).</p>

<h1 id="prerequisites">Prerequisites</h1>

<ul>
  <li><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Java Development Kit</a></li>
  <li><a href="http://maven.apache.org" target="_blank">Maven</a></li>
  <li>SMPP account that supports v3.4</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.
|__src/
|  |__main/
|  |  |__java/
|  |  |  |__com/
|  |  |  |  |__juliuskrah/
|  |  |  |  |  |__smpp/
|  |  |  |  |  |  |__Application.java
|  |  |  |  |  |  |__MessageReceiver.java
|  |  |  |  |  |  |__MessageRoute.java
|  |  |__resources/
|  |  |  |__application.yaml
|__pom.xml
</code></pre></div></div>

<h2 id="project-setup">Project Setup</h2>

<p>Create a simple Spring Boot Application by heading over to <a href="https://start.spring.io/#!type=maven-project&amp;language=java&amp;platformVersion=2.2.6.RELEASE&amp;packaging=jar&amp;jvmVersion=11&amp;groupId=com.juliuskrah&amp;artifactId=smpp&amp;name=smpp&amp;description=Demo%20project%20for%20Camel%20SMPP&amp;packageName=com.juliuskrah.smpp" target="_blank">start.spring.io</a>.
Add the following to your <code class="language-plaintext highlighter-rouge">pom.xml</code> (assuming you picked maven) after creating your Spring-Boot
application:</p>

<figure class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="c">&lt;!-- Sections omitted --&gt;</span>
<span class="nt">&lt;properties&gt;</span>
  <span class="nt">&lt;java.version&gt;</span>11<span class="nt">&lt;/java.version&gt;</span>
  <span class="nt">&lt;camel-spring.version&gt;</span>3.1.0<span class="nt">&lt;/camel-spring.version&gt;</span>
<span class="nt">&lt;/properties&gt;</span>

<span class="nt">&lt;dependencyManagement&gt;</span>
  <span class="nt">&lt;dependencies&gt;</span>
    <span class="nt">&lt;dependency&gt;</span>
      <span class="nt">&lt;groupId&gt;</span>org.apache.camel.springboot<span class="nt">&lt;/groupId&gt;</span>
      <span class="nt">&lt;artifactId&gt;</span>camel-spring-boot-dependencies<span class="nt">&lt;/artifactId&gt;</span>
      <span class="nt">&lt;version&gt;</span>${camel-spring.version}<span class="nt">&lt;/version&gt;</span>
      <span class="nt">&lt;type&gt;</span>pom<span class="nt">&lt;/type&gt;</span>
      <span class="nt">&lt;scope&gt;</span>import<span class="nt">&lt;/scope&gt;</span>
    <span class="nt">&lt;/dependency&gt;</span>
  <span class="nt">&lt;/dependencies&gt;</span>
<span class="nt">&lt;/dependencyManagement&gt;</span>

<span class="nt">&lt;dependencies&gt;</span>
  <span class="nt">&lt;dependency&gt;</span>
    <span class="nt">&lt;groupId&gt;</span>org.apache.camel.springboot<span class="nt">&lt;/groupId&gt;</span>
    <span class="nt">&lt;artifactId&gt;</span>camel-spring-boot-starter<span class="nt">&lt;/artifactId&gt;</span>
  <span class="nt">&lt;/dependency&gt;</span>
  <span class="nt">&lt;dependency&gt;</span>
    <span class="nt">&lt;groupId&gt;</span>org.apache.camel.springboot<span class="nt">&lt;/groupId&gt;</span>
    <span class="nt">&lt;artifactId&gt;</span>camel-smpp-starter<span class="nt">&lt;/artifactId&gt;</span>
  <span class="nt">&lt;/dependency&gt;</span>
  <span class="nt">&lt;dependency&gt;</span>
    <span class="nt">&lt;groupId&gt;</span>org.apache.camel.springboot<span class="nt">&lt;/groupId&gt;</span>
    <span class="nt">&lt;artifactId&gt;</span>camel-bean-starter<span class="nt">&lt;/artifactId&gt;</span>
  <span class="nt">&lt;/dependency&gt;</span>
<span class="nt">&lt;/dependencies&gt;</span></code></pre></figure>

<h1 id="configuring-came-smpp">Configuring Came SMPP</h1>

<p>SMPP using camel is very covenient, as it provides some auto-configuration for Spring. We need the
following configuration to get started:</p>

<p>file: <a href="https://github.com/juliuskrah/smpp/tree/camel/src/main/resources/application.yaml">
  <code class="highlighter-rouge">src/main/resources/application.yaml</code>
</a></p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="na">camel</span><span class="pi">:</span>
  <span class="na">component</span><span class="pi">:</span>
    <span class="na">enabled</span><span class="pi">:</span> <span class="no">true</span>
    <span class="na">smpp</span><span class="pi">:</span>
      <span class="na">configuration</span><span class="pi">:</span>
        <span class="na">host</span><span class="pi">:</span> <span class="s">:smpp.host:</span>
        <span class="na">password</span><span class="pi">:</span> <span class="s">:password:</span>
        <span class="na">system-id</span><span class="pi">:</span> <span class="s">:user:</span>
        <span class="na">source-addr-ton</span><span class="pi">:</span> <span class="s">0x05</span>
        <span class="na">source-addr-npi</span><span class="pi">:</span> <span class="s">0x01</span>
        <span class="na">dest-addr-npi</span><span class="pi">:</span> <span class="s">0x01</span>
        <span class="na">dest-addr-ton</span><span class="pi">:</span> <span class="s">0x01</span>
        <span class="na">registered-delivery</span><span class="pi">:</span> <span class="m">1</span>
    <span class="na">bean</span><span class="pi">:</span>
      <span class="na">scope</span><span class="pi">:</span> <span class="s">singleton</span>
  <span class="na">springboot</span><span class="pi">:</span>
    <span class="na">name</span><span class="pi">:</span> <span class="s">smpp-app</span>
    <span class="na">main-run-controller</span><span class="pi">:</span> <span class="no">false</span></code></pre></figure>

<blockquote>
  <p>NOTE: Be sure to replace the values for <code class="language-plaintext highlighter-rouge">host</code>, <code class="language-plaintext highlighter-rouge">system-id</code> and <code class="language-plaintext highlighter-rouge">password</code>. You can get these values 
  from your SMPP service provider.</p>
</blockquote>

<p>That’s all we need. Now let’s add code to send an SMS</p>

<h2 id="send-an-sms">Send an SMS</h2>

<p>We will add a simple method that sends an SMS on application bootstrap:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">private</span> <span class="nc">Exchange</span> <span class="nf">sendTextMessage</span><span class="o">(</span><span class="nc">ProducerTemplate</span> <span class="n">template</span><span class="o">,</span> <span class="nc">String</span> <span class="n">sourceAddress</span><span class="o">,</span>
      <span class="nc">String</span> <span class="n">destinationAddress</span><span class="o">,</span> <span class="nc">String</span> <span class="n">message</span><span class="o">)</span> <span class="o">{</span>
    <span class="kt">var</span> <span class="n">exchange</span> <span class="o">=</span> <span class="nc">ExchangeBuilder</span><span class="o">.</span><span class="na">anExchange</span><span class="o">(</span><span class="n">context</span><span class="o">)</span>
        <span class="o">.</span><span class="na">withHeader</span><span class="o">(</span><span class="s">"CamelSmppDestAddr"</span><span class="o">,</span> <span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="n">destinationAddress</span><span class="o">))</span>
        <span class="o">.</span><span class="na">withHeader</span><span class="o">(</span><span class="s">"CamelSmppSourceAddr"</span><span class="o">,</span> <span class="n">sourceAddress</span><span class="o">)</span>
        <span class="o">.</span><span class="na">withPattern</span><span class="o">(</span><span class="nc">ExchangePattern</span><span class="o">.</span><span class="na">InOnly</span><span class="o">)</span>
        <span class="o">.</span><span class="na">withBody</span><span class="o">(</span><span class="n">message</span><span class="o">).</span><span class="na">build</span><span class="o">();</span>
    
    <span class="c1">// exceptions are not thrown from this method</span>
    <span class="c1">// exceptions are stored in Exchange#setException()</span>
    <span class="k">return</span> <span class="n">template</span><span class="o">.</span><span class="na">send</span><span class="o">(</span><span class="s">"smpp://{{camel.component.smpp.configuration.host}}"</span><span class="o">,</span> <span class="n">exchange</span><span class="o">);</span>
    
<span class="o">}</span></code></pre></figure>

<p>With this method created, we can call it on application startup with a <code class="language-plaintext highlighter-rouge">CommandlineRunner</code></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@Bean</span>
<span class="nc">CommandLineRunner</span> <span class="nf">init</span><span class="o">(</span><span class="nc">ProducerTemplate</span> <span class="n">template</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">return</span> <span class="n">args</span> <span class="o">-&gt;</span> <span class="o">{</span>
        <span class="kt">var</span> <span class="n">exchange</span> <span class="o">=</span> <span class="n">sendTextMessage</span><span class="o">(</span><span class="n">template</span><span class="o">,</span> <span class="s">"5432"</span><span class="o">,</span> <span class="s">"&lt;replace with phone number&gt;"</span><span class="o">,</span> <span class="s">"Hello World!"</span><span class="o">);</span>
        <span class="k">if</span> <span class="o">(</span><span class="n">exchange</span><span class="o">.</span><span class="na">getException</span><span class="o">()</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span>
            <span class="n">log</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Message Id - {}"</span><span class="o">,</span> <span class="n">exchange</span><span class="o">.</span><span class="na">getMessage</span><span class="o">().</span><span class="na">getHeader</span><span class="o">(</span><span class="s">"CamelSmppId"</span><span class="o">));</span>
        <span class="k">else</span>
            <span class="n">log</span><span class="o">.</span><span class="na">error</span><span class="o">(</span><span class="s">"Could not send message"</span><span class="o">,</span> <span class="n">exchange</span><span class="o">.</span><span class="na">getException</span><span class="o">());</span>
    <span class="o">};</span>
<span class="o">}</span></code></pre></figure>

<p>Putting it all together:</p>

<p>file: <a href="https://github.com/juliuskrah/smpp/tree/camel/src/main/java/com/juliuskrah/smpp/Application.java">
  <code class="highlighter-rouge">src/main/java/com/juliuskrah/smpp/Application.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@SpringBootApplication</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">Application</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="nc">Logger</span> <span class="n">log</span> <span class="o">=</span> <span class="nc">LoggerFactory</span><span class="o">.</span><span class="na">getLogger</span><span class="o">(</span><span class="nc">Application</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
    <span class="nd">@Autowired</span> <span class="kd">private</span> <span class="nc">CamelContext</span> <span class="n">context</span><span class="o">;</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">SpringApplication</span><span class="o">.</span><span class="na">run</span><span class="o">(</span><span class="nc">Application</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">args</span><span class="o">);</span>
    <span class="o">}</span>

    <span class="kd">private</span> <span class="nc">Exchange</span> <span class="nf">sendTextMessage</span><span class="o">(</span><span class="nc">ProducerTemplate</span> <span class="n">template</span><span class="o">,</span> <span class="nc">String</span> <span class="n">sourceAddress</span><span class="o">,</span>
        <span class="nc">String</span> <span class="n">destinationAddress</span><span class="o">,</span> <span class="nc">String</span> <span class="n">message</span><span class="o">)</span> <span class="o">{</span>
        <span class="kt">var</span> <span class="n">exchange</span> <span class="o">=</span> <span class="nc">ExchangeBuilder</span><span class="o">.</span><span class="na">anExchange</span><span class="o">(</span><span class="n">context</span><span class="o">)</span>
            <span class="o">.</span><span class="na">withHeader</span><span class="o">(</span><span class="s">"CamelSmppDestAddr"</span><span class="o">,</span> <span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="n">destinationAddress</span><span class="o">))</span>
            <span class="o">.</span><span class="na">withHeader</span><span class="o">(</span><span class="s">"CamelSmppSourceAddr"</span><span class="o">,</span> <span class="n">sourceAddress</span><span class="o">)</span>
            <span class="o">.</span><span class="na">withPattern</span><span class="o">(</span><span class="nc">ExchangePattern</span><span class="o">.</span><span class="na">InOnly</span><span class="o">)</span>
            <span class="o">.</span><span class="na">withBody</span><span class="o">(</span><span class="n">message</span><span class="o">).</span><span class="na">build</span><span class="o">();</span>
        
        <span class="c1">// exceptions are not thrown from this method</span>
        <span class="c1">// exceptions are stored in Exchange#setException()</span>
        <span class="k">return</span> <span class="n">template</span><span class="o">.</span><span class="na">send</span><span class="o">(</span><span class="s">"smpp://{{camel.component.smpp.configuration.host}}"</span><span class="o">,</span> <span class="n">exchange</span><span class="o">);</span>
        
    <span class="o">}</span>

    <span class="nd">@Bean</span>
    <span class="nc">CommandLineRunner</span> <span class="nf">init</span><span class="o">(</span><span class="nc">ProducerTemplate</span> <span class="n">template</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">args</span> <span class="o">-&gt;</span> <span class="o">{</span>
            <span class="kt">var</span> <span class="n">exchange</span> <span class="o">=</span> <span class="n">sendTextMessage</span><span class="o">(</span><span class="n">template</span><span class="o">,</span> <span class="s">"5432"</span><span class="o">,</span> <span class="s">"&lt;replace with phone number&gt;"</span><span class="o">,</span> <span class="s">"Hello World!"</span><span class="o">);</span>
            <span class="k">if</span> <span class="o">(</span><span class="n">exchange</span><span class="o">.</span><span class="na">getException</span><span class="o">()</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span>
                <span class="n">log</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Message Id - {}"</span><span class="o">,</span> <span class="n">exchange</span><span class="o">.</span><span class="na">getMessage</span><span class="o">().</span><span class="na">getHeader</span><span class="o">(</span><span class="s">"CamelSmppId"</span><span class="o">));</span>
            <span class="k">else</span>
                <span class="n">log</span><span class="o">.</span><span class="na">error</span><span class="o">(</span><span class="s">"Could not send message"</span><span class="o">,</span> <span class="n">exchange</span><span class="o">.</span><span class="na">getException</span><span class="o">());</span>
        <span class="o">};</span>
    <span class="o">}</span>

<span class="o">}</span></code></pre></figure>

<h2 id="receive-delivery-receipts">Receive delivery receipts</h2>

<p>After sending an SMS you may want to receive delivery receipts. To do this, we will create a bean
to process the delivery receipts.</p>

<p>file: <a href="https://github.com/juliuskrah/smpp/tree/camel/src/main/java/com/juliuskrah/smpp/MessageReceiver.java">
  <code class="highlighter-rouge">src/main/java/com/juliuskrah/smpp/MessageReceiver.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@Component</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">MessageReceiver</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="kd">static</span> <span class="nc">Logger</span> <span class="n">log</span> <span class="o">=</span> <span class="nc">LoggerFactory</span><span class="o">.</span><span class="na">getLogger</span><span class="o">(</span><span class="nc">MessageReceiver</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>

    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">receive</span><span class="o">(</span><span class="nc">Exchange</span> <span class="n">exchange</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">if</span> <span class="o">(</span><span class="n">exchange</span><span class="o">.</span><span class="na">getException</span><span class="o">()</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
            <span class="kt">var</span> <span class="n">message</span> <span class="o">=</span> <span class="n">exchange</span><span class="o">.</span><span class="na">getIn</span><span class="o">();</span>
            <span class="n">log</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Received id {}"</span><span class="o">,</span> <span class="n">message</span><span class="o">.</span><span class="na">getHeader</span><span class="o">(</span><span class="s">"CamelSmppId"</span><span class="o">));</span>
            <span class="n">log</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Text :- {}"</span><span class="o">,</span> <span class="n">message</span><span class="o">.</span><span class="na">getBody</span><span class="o">());</span>
            <span class="n">log</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Total delivered {}"</span><span class="o">,</span> <span class="n">message</span><span class="o">.</span><span class="na">getHeader</span><span class="o">(</span><span class="s">"CamelSmppDelivered"</span><span class="o">));</span>
            <span class="n">log</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Message status {}"</span><span class="o">,</span> <span class="n">message</span><span class="o">.</span><span class="na">getHeader</span><span class="o">(</span><span class="s">"CamelSmppStatus"</span><span class="o">));</span>
            <span class="n">log</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Submitted date {}"</span><span class="o">,</span> <span class="n">message</span><span class="o">.</span><span class="na">getHeader</span><span class="o">(</span><span class="s">"CamelSmppSubmitDate"</span><span class="o">,</span> <span class="nc">Date</span><span class="o">.</span><span class="na">class</span><span class="o">));</span>
            <span class="n">log</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Done date {}"</span><span class="o">,</span> <span class="n">message</span><span class="o">.</span><span class="na">getHeader</span><span class="o">(</span><span class="s">"CamelSmppDoneDate"</span><span class="o">,</span> <span class="nc">Date</span><span class="o">.</span><span class="na">class</span><span class="o">));</span>
        <span class="o">}</span> <span class="k">else</span>
            <span class="n">log</span><span class="o">.</span><span class="na">error</span><span class="o">(</span><span class="s">"Error receiving message"</span><span class="o">,</span> <span class="n">exchange</span><span class="o">.</span><span class="na">getException</span><span class="o">());</span>
    <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>Next we will create a router to route messages from the SMSC to our bean:</p>

<p>file: <a href="https://github.com/juliuskrah/smpp/tree/camel/src/main/java/com/juliuskrah/smpp/MessageRoute.java">
  <code class="highlighter-rouge">src/main/java/com/juliuskrah/smpp/MessageRoute.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@Component</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">MessageRoute</span> <span class="kd">extends</span> <span class="nc">RouteBuilder</span> <span class="o">{</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">configure</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">Exception</span> <span class="o">{</span>
        
        <span class="n">from</span><span class="o">(</span><span class="s">"smpp://{{camel.component.smpp.configuration.host}}"</span><span class="o">)</span>
                <span class="o">.</span><span class="na">to</span><span class="o">(</span><span class="s">"bean:messageReceiver?method=receive"</span><span class="o">);</span>
        
    <span class="o">}</span>   
<span class="o">}</span></code></pre></figure>

<h1 id="conclusion">Conclusion</h1>

<p>In this post we looked briefly at the SMPP protocol and its usage within the JVM. We also covered how to
use Spring Boot and Camel to make developing an SMPP client easier.</p>

<p>As usual you can find the full example to this guide <a href="https://github.com/juliuskrah/smpp/tree/camel" target="_blank">in the github repository</a>. Until the next post, keep
doing cool things :+1:.</p>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;juliuskrah&quot;}</name></author><category term="blog" /><category term="java" /><category term="spring-boot" /><category term="maven" /><summary type="html"><![CDATA[Short Message Peer-to-Peer (SMPP) is a protocol used by the telecommunications industry for exchanging messages between Short Message Service Centers (SMSC) and/or External Short Messaging Entities (ESME).]]></summary></entry><entry><title type="html">Sping Excel REST API with JasperReports</title><link href="http://juliuskrah.com/blog/2020/03/27/sping-excel-rest-api-with-jasperreports/" rel="alternate" type="text/html" title="Sping Excel REST API with JasperReports" /><published>2020-03-27T13:52:08+00:00</published><updated>2020-03-27T13:52:08+00:00</updated><id>http://juliuskrah.com/blog/2020/03/27/sping-excel-rest-api-with-jasperreports</id><content type="html" xml:base="http://juliuskrah.com/blog/2020/03/27/sping-excel-rest-api-with-jasperreports/"><![CDATA[<blockquote>
  <p><a href="/tag/jasperreports/">JasperReports</a> is a Java library, and it is meant for Java developers
  who need to add reporting to their applications.</p>
</blockquote>

<h1 id="introduction">Introduction</h1>
<p>In this post, we will create an excel report that is exposed over RESTful endpoint using Spring Boot. In
a <a href="/blog/2018/04/30/sping-pdf-rest-api-with-jasperreports/">previous post</a> we looked at how to
expose Jasper PDF over REST.</p>

<h2 id="prerequisites">Prerequisites</h2>

<ul>
  <li><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Java Development Kit</a> 11+</li>
  <li><a href="http://maven.apache.org" target="_blank">Maven</a></li>
</ul>

<h2 id="project-structure">Project Structure</h2>

<p>At the end of this guide our folder structure will look similar to the following:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.
|__src/
|  |__main/
|  |  |__java/
|  |  |  |__com/
|  |  |  |  |__juliuskrah/
|  |  |  |  |  |__jasper/
|  |  |  |  |  |  |__Application.java
|  |  |  |  |  |  |__ApplicationProperties.java
|  |  |  |  |  |  |__report/
|  |  |  |  |  |  |  |__JasperReportsService.java
|  |  |  |  |  |  |  |__ReportService.java
|  |  |  |  |  |  |__storage/
|  |  |  |  |  |  |  |__FileSystemStorageService.java
|  |  |  |  |  |  |  |__StorageException.java
|  |  |  |  |  |  |  |__StorageFileNotFoundException.java
|  |  |  |  |  |  |  |__StorageService.java
|  |  |  |  |  |  |__web/
|  |  |  |  |  |  |  |__rest/
|  |  |  |  |  |  |  |  |__ApplicationResource.java
|  |  |__resources/
|  |  |  |__reports/
|  |  |  |  |__pdf_rest_resource.jrxml
|  |  |  |  |__pdf_rest.jrxml
|  |  |  |__application.yaml
|  |  |  |__cherry.png
|  |  |  |__logo.png
|__pom.xml
</code></pre></div></div>

<h2 id="how-to-complete-this-guide">How to complete this guide</h2>

<p>To complete this guide, download (<a href="https://github.com/juliuskrah/jasper-html-mail/archive/v3.0.zip">zip</a>|
<a href="https://github.com/juliuskrah/jasper-html-mail/archive/v3.0.tar.gz">tar.gz</a>) 
and unzip the source repository for this guide.</p>

<h2 id="create-excel-report">Create Excel Report</h2>

<p>Let us start by implementing a solution to generate excel in JasperReports:</p>

<p>file: <a href="https://github.com/juliuskrah/jasper-html-mail/tree/jasper-rest-multi/src/main/java/com/juliuskrah/jasper/report/JasperReportsService.java">
  <code class="highlighter-rouge">src/main/java/com/juliuskrah/jasper/report/JasperReportsService.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@Component</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">JasperReportsService</span> <span class="kd">implements</span> <span class="nc">ReportService</span> <span class="o">{</span>
  <span class="c1">// ...</span>
  <span class="nd">@Override</span>
  <span class="kd">public</span> <span class="kt">byte</span><span class="o">[]</span> <span class="nf">generatePDFReport</span><span class="o">(</span><span class="nc">String</span> <span class="n">inputFileName</span><span class="o">,</span> <span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Object</span><span class="o">&gt;</span> <span class="n">params</span><span class="o">,</span>
    <span class="nc">JRDataSource</span> <span class="n">dataSource</span><span class="o">)</span> <span class="o">{</span>
    <span class="kt">byte</span><span class="o">[]</span> <span class="n">bytes</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
    <span class="nc">JasperReport</span> <span class="n">jasperReport</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
    <span class="k">try</span> <span class="o">{</span>
      <span class="k">if</span> <span class="o">(</span><span class="n">storageService</span><span class="o">.</span><span class="na">jasperFileExists</span><span class="o">(</span><span class="n">inputFileName</span><span class="o">))</span> <span class="o">{</span>
        <span class="n">jasperReport</span> <span class="o">=</span> <span class="o">(</span><span class="nc">JasperReport</span><span class="o">)</span> <span class="nc">JRLoader</span><span class="o">.</span><span class="na">loadObject</span><span class="o">(</span><span class="n">storageService</span><span class="o">.</span><span class="na">loadJasperFile</span><span class="o">(</span><span class="n">inputFileName</span><span class="o">));</span>
      <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
        <span class="kt">var</span> <span class="n">jrxml</span> <span class="o">=</span> <span class="n">storageService</span><span class="o">.</span><span class="na">loadJrxmlFile</span><span class="o">(</span><span class="n">inputFileName</span><span class="o">);</span>
        <span class="n">jasperReport</span> <span class="o">=</span> <span class="nc">JasperCompileManager</span><span class="o">.</span><span class="na">compileReport</span><span class="o">(</span><span class="n">jrxml</span><span class="o">);</span>
        <span class="c1">// Save the compiled report for use on next invocation</span>
        <span class="nc">JRSaver</span><span class="o">.</span><span class="na">saveObject</span><span class="o">(</span><span class="n">jasperReport</span><span class="o">,</span> <span class="n">storageService</span><span class="o">.</span><span class="na">loadJasperFile</span><span class="o">(</span><span class="n">inputFileName</span><span class="o">));</span>
      <span class="o">}</span>
      <span class="nc">JasperPrint</span> <span class="n">jasperPrint</span> <span class="o">=</span> <span class="nc">JasperFillManager</span><span class="o">.</span><span class="na">fillReport</span><span class="o">(</span><span class="n">jasperReport</span><span class="o">,</span> <span class="n">params</span><span class="o">,</span> <span class="n">dataSource</span><span class="o">);</span>
      <span class="kt">var</span> <span class="n">input</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">SimpleExporterInput</span><span class="o">(</span><span class="n">jasperPrint</span><span class="o">);</span>
      <span class="k">try</span> <span class="o">(</span><span class="kt">var</span> <span class="n">byteArray</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ByteArrayOutputStream</span><span class="o">())</span> <span class="o">{</span>
        <span class="kt">var</span> <span class="n">output</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">SimpleOutputStreamExporterOutput</span><span class="o">(</span><span class="n">byteArray</span><span class="o">);</span>
        <span class="kt">var</span> <span class="n">exporter</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">JRXlsxExporter</span><span class="o">();</span>
        <span class="n">exporter</span><span class="o">.</span><span class="na">setExporterInput</span><span class="o">(</span><span class="n">input</span><span class="o">);</span>
        <span class="n">exporter</span><span class="o">.</span><span class="na">setExporterOutput</span><span class="o">(</span><span class="n">output</span><span class="o">);</span>
        <span class="n">exporter</span><span class="o">.</span><span class="na">exportReport</span><span class="o">();</span>
        <span class="n">bytes</span> <span class="o">=</span> <span class="n">byteArray</span><span class="o">.</span><span class="na">toByteArray</span><span class="o">();</span>
        <span class="n">output</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
      <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
        <span class="c1">// handle IO error</span>
      <span class="o">}</span>
      <span class="k">return</span> <span class="n">bytes</span><span class="o">;</span>
    <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">JRException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
      <span class="c1">// handle error</span>
    <span class="o">}</span>
    <span class="k">return</span> <span class="n">bytes</span><span class="o">;</span>
  <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<h2 id="render-the-excel-rest-endpoint">Render the Excel REST Endpoint</h2>

<p>We will create the REST endpoint:</p>

<p>file: <a href="https://github.com/juliuskrah/jasper-html-mail/tree/jasper-rest-multi/src/main/java/com/juliuskrah/jasper/web/rest/ApplicationResource.java">
  <code class="highlighter-rouge">src/main/java/com/juliuskrah/jasper/web/rest/ApplicationResource.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@RestController</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">ApplicationResource</span> <span class="o">{</span>
  <span class="c1">// ...</span>
  <span class="nd">@GetMapping</span><span class="o">(</span><span class="s">"/{username}"</span><span class="o">)</span>
  <span class="kd">public</span> <span class="nc">ResponseEntity</span><span class="o">&lt;</span><span class="kt">byte</span><span class="o">[]&gt;</span> <span class="nf">report</span><span class="o">(</span><span class="nd">@PathVariable</span> <span class="nc">String</span> <span class="n">username</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Object</span><span class="o">&gt;</span> <span class="n">params</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HashMap</span><span class="o">&lt;&gt;();</span>
    <span class="n">params</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"username"</span><span class="o">,</span> <span class="n">username</span><span class="o">);</span>
    <span class="kt">byte</span><span class="o">[]</span> <span class="n">bytes</span> <span class="o">=</span> <span class="n">reportService</span><span class="o">.</span><span class="na">generatePDFReport</span><span class="o">(</span><span class="s">"pdf_rest_resource"</span><span class="o">,</span> <span class="n">params</span><span class="o">);</span>
    <span class="kt">var</span> <span class="n">contentDisposition</span> <span class="o">=</span> <span class="nc">ContentDisposition</span><span class="o">.</span><span class="na">builder</span><span class="o">(</span><span class="s">"attachment"</span><span class="o">)</span>
      <span class="o">.</span><span class="na">filename</span><span class="o">(</span><span class="n">username</span> <span class="o">+</span> <span class="s">".xlsx"</span><span class="o">).</span><span class="na">build</span><span class="o">();</span>
    <span class="nc">HttpHeaders</span> <span class="n">headers</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HttpHeaders</span><span class="o">();</span>
    <span class="n">headers</span><span class="o">.</span><span class="na">setContentDisposition</span><span class="o">(</span><span class="n">contentDisposition</span><span class="o">);</span>
    <span class="k">return</span> <span class="nc">ResponseEntity</span>
      <span class="o">.</span><span class="na">ok</span><span class="o">()</span>
      <span class="c1">// Specify content type as excel</span>
      <span class="o">.</span><span class="na">header</span><span class="o">(</span><span class="s">"Content-Type"</span><span class="o">,</span> <span class="s">"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=UTF-8"</span><span class="o">)</span>
      <span class="c1">// Tell browser to download Excel if it can</span>
      <span class="o">.</span><span class="na">headers</span><span class="o">(</span><span class="n">headers</span><span class="o">)</span> <span class="c1">//</span>
      <span class="o">.</span><span class="na">body</span><span class="o">(</span><span class="n">bytes</span><span class="o">);</span>
  <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>Now navigate to <a href="http://localhost:8080/:username">http://localhost:8080/:username</a> to view your report.</p>

<h1 id="conclusion">Conclusion</h1>

<p>In this post we learned how to generate Excel with JasperReports and serve it over HTTP with Spring
Boot. As usual you can find the full example to this guide <a href="https://github.com/juliuskrah/jasper-html-mail/tree/jasper-rest-multi" target="_blank">in the github repository</a>. Until the next
post, keep doing cool things :+1:.</p>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;juliuskrah&quot;}</name></author><category term="blog" /><category term="java" /><category term="maven" /><category term="jasperreports" /><category term="rest" /><category term="spring-boot" /><summary type="html"><![CDATA[JasperReports is a Java library, and it is meant for Java developers who need to add reporting to their applications.]]></summary></entry><entry><title type="html">Streaming Changes from Keycloak using Debezium (CDC)</title><link href="http://juliuskrah.com/blog/2020/01/06/streaming-changes-from-keycloak-using-debezium-cdc/" rel="alternate" type="text/html" title="Streaming Changes from Keycloak using Debezium (CDC)" /><published>2020-01-06T15:59:40+00:00</published><updated>2020-01-06T15:59:40+00:00</updated><id>http://juliuskrah.com/blog/2020/01/06/streaming-changes-from-keycloak-using-debezium-cdc</id><content type="html" xml:base="http://juliuskrah.com/blog/2020/01/06/streaming-changes-from-keycloak-using-debezium-cdc/"><![CDATA[<blockquote>
  <p><a href="https://docs.microsoft.com/en-us/sql/relational-databases/track-changes/about-change-data-capture-sql-server?view=sql-server-ver15" target="_blank">Change data capture</a> records insert, update, and delete
  activity that is applied to a relational database table.</p>
</blockquote>

<h1 id="introduction">Introduction</h1>

<p>In a microservices architecture, keeping consistent state between services becomes tedious. Several
techniques have been employed over the years to tackle these challenges. One such approach is <a href="https://docs.couchdb.org/en/stable/intro/consistency.html" target="_blank">Eventual Consistency</a>.
When you want to update an ElasticSearch index with data from PostgreSQL, you have to rely on one of these
techniques to keep data up-to-date.</p>

<p>In this blog post I will discuss an alternate technique using Change Data Capture (CDC). CDC<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup> is a set 
of software design patterns used to determine the data that has changed so that action can be taken using 
the changed data. I have put together a little <a href="https://github.com/juliuskrah//keycloak-cdc/tree/master" target="_blank">demo application</a> to showcase
this. In the demo I am streaming users created in <a href="https://www.keycloak.org/" target="_blank">Keycloak</a> and saving them in a Java application.</p>

<h1 id="solution-architecture">Solution Architecture</h1>

<p class="image-caption"><img src="https://i.imgur.com/poKXr9K.png" alt="CDC Architecture" /></p>
<p>Fig 1 <em>Solution showing all the components functioning together</em></p>

<p>There are several open source CDC tools out there in the wild. I have chosen to go with <a href="https://debezium.io/" target="_blank">Debezium</a>
and <a href="https://jdbc.postgresql.org/documentation/head/replication.html" target="_blank">PostgreSQL</a>; you can choose any combination of your choice. To start debzium, 
for CDC the following ritual must be performed.</p>

<p>First you have to configure your database of choice to enable CDC streaming. At the time of this writing
debezium<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup> supports the following databases:</p>

<ul>
  <li>MongoDB</li>
  <li>MySQL</li>
  <li><a href="https://jdbc.postgresql.org/documentation/head/replication.html" target="_blank">PostgreSQL</a></li>
  <li>SQL Server</li>
  <li>Oracle</li>
  <li>Cassandra</li>
</ul>

<h2 id="postgresql">PostgreSQL</h2>

<p>We are using PostgreSQL for this demo. PostgreSQL uses a <em>logical decoder</em> that writes change events to
a Write Ahead Log (WAL)<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup> after they are committed. 
PostgreSQL’s <em>logical decoding</em> feature was first introduced in version 9.4
and is a mechanism which allows the extraction of the changes which were committed to the transaction log.
The changes are processed in a user-friendly manner via the help of an <em>output plugin</em>. The logical 
decoding output plugin must be installed prior to running the PostgreSQL server and enabled together with
a replication slot. The output plugins supported by debezium are:</p>

<ul>
  <li><a href="https://github.com/debezium/postgres-decoderbufs" target="_blank">decoderbufs</a></li>
  <li><a href="https://github.com/eulerto/wal2json" target="_blank">wal2json</a></li>
  <li>pgoutput<sup id="fnref:4" role="doc-noteref"><a href="#fn:4" class="footnote" rel="footnote">4</a></sup> - standard logical decoding plug-in in PostgreSQL 10+</li>
</ul>

<p>I will be using <strong>pgoutput</strong> because it requires no additional libraries to be installed. Next enable
a replication slot, and configure a user with sufficient privileges to perform the replication.</p>

<p>According to the postgres documentation, a user with REPLICATION role is enough for CDC, however in my
case I’ve never managed to get it to work with the debezium postgres connector. Let me know in the 
comments if you are successful. I create a user with SUPERUSER role for this purpose;</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">psql&gt; CREATE ROLE postgres SUPERUSER LOGIN<span class="p">;</span>
psql&gt; ALTER ROLE postgres WITH PASSWORD <span class="s1">'postgrespwd'</span><span class="p">;</span></code></pre></figure>

<p>then configure the PostgreSQL server to allow replication;</p>

<p>file: <em>pg_hba.conf</em></p>

<figure class="highlight"><pre><code class="language-conf" data-lang="conf"><span class="n">local</span>   <span class="n">replication</span>     <span class="n">postgres</span>                          <span class="n">trust</span>   
<span class="n">host</span>    <span class="n">replication</span>     <span class="n">postgres</span>  <span class="m">127</span>.<span class="m">0</span>.<span class="m">0</span>.<span class="m">1</span>/<span class="m">32</span>            <span class="n">trust</span>   
<span class="n">host</span>    <span class="n">replication</span>     <span class="n">postgres</span>  ::<span class="m">1</span>/<span class="m">128</span>                 <span class="n">trust</span>   </code></pre></figure>

<p>and finally configure the replication slot:</p>

<p>file: <em>postgresql.conf</em></p>

<figure class="highlight"><pre><code class="language-conf" data-lang="conf"><span class="n">wal_level</span> = <span class="n">logical</span>             
<span class="n">max_wal_senders</span> = <span class="m">1</span>             
<span class="n">max_replication_slots</span> = <span class="m">5</span>      </code></pre></figure>

<p>With PostgreSQL up and running, create the database and user for Keycloak:</p>

<figure class="highlight"><pre><code class="language-conf" data-lang="conf"><span class="n">pasql</span>&gt; <span class="n">CREATE</span> <span class="n">USER</span> <span class="n">sample</span> <span class="n">WITH</span> <span class="n">PASSWORD</span> <span class="s1">'sample'</span>;
<span class="n">pasql</span>&gt; <span class="n">CREATE</span> <span class="n">DATABASE</span> <span class="n">sample</span>;
<span class="n">pasql</span>&gt; <span class="n">GRANT</span> <span class="n">ALL</span> <span class="n">PRIVILEGES</span> <span class="n">ON</span> <span class="n">DATABASE</span> <span class="n">sample</span> <span class="n">TO</span> <span class="n">sample</span>;
<span class="n">pasql</span>&gt; \<span class="n">c</span> <span class="n">sample</span>;
<span class="n">pasql</span>&gt; <span class="n">CREATE</span> <span class="n">SCHEMA</span> <span class="n">IF</span> <span class="n">NOT</span> <span class="n">EXISTS</span> <span class="n">AUTHORIZATION</span> <span class="n">sample</span>;</code></pre></figure>

<h2 id="kafka-and-zookeeper">Kafka and Zookeeper</h2>

<p>You now need to configure <a href="https://kafka.apache.org/" target="_blank">Kafka</a> and <a href="https://zookeeper.apache.org/" target="_blank">Zookeeper</a>. I will not 
demonstrate how to setup Kafka and Zookeeper; everything required to run this demo is setup in a 
<a href="https://github.com/juliuskrah//keycloak-cdc/tree/master/docker-compose.nobuild.yml" target="_blank">docker</a> file.</p>

<h2 id="keycloak">Keycloak</h2>

<p>Once keycloak is installed, import the <a href="https://raw.githubusercontent.com/juliuskrah/keycloak-cdc/master/keycloak/sample_realm.json" target="_blank">sample realm</a>. You can also run the 
<a href="https://github.com/juliuskrah//keycloak-cdc/tree/master/docker-compose.nobuild.yml" target="_blank">compose file</a> to get everything up and running.</p>

<h2 id="kafka-connect">Kafka Connect</h2>

<p>Debezium is a <a href="https://kafka.apache.org/documentation/#connect" target="_blank">Kafka Connect</a> connector; It can be easily setup using the
<a href="https://github.com/juliuskrah//keycloak-cdc/tree/master/docker-compose.nobuild.yml" target="_blank">compose file</a>.</p>

<p>Once the connector is ready to recieve connections, we make a post request to create our CDC Connector:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="code"><pre><span class="o">&gt;</span> curl <span class="nt">-s</span> <span class="se">\</span>
     <span class="nt">-X</span> <span class="s2">"POST"</span> <span class="s2">"http://localhost:8083/connectors/"</span> <span class="se">\</span>
     <span class="nt">-H</span> <span class="s2">"Content-Type: application/json"</span> <span class="se">\</span>
     <span class="nt">-d</span> <span class="s1">'{
  "name": "keycloak-connector",
  "config": {
    "connector.class": "io.debezium.connector.postgresql.PostgresConnector",
    "database.hostname": "postgres",
    "database.port": "5432",
    "slot.name": "keycloak_debezium",
    "plugin.name": "pgoutput",
    "database.user": "postgres",
    "database.password": "postgrespwd",
    "database.dbname": "sample",
    "database.server.name": "keycloak",
    "schema.whitelist": "sample",
    "table.whitelist": "sample.user_role_mapping,sample.user_group_membership,sample.keycloak_role,sample.user_entity"
  }
}'</span>
</pre></td></tr></tbody></table></code></pre></figure>

<p>A brief description of the payload above;</p>

<ul>
  <li>line 5 is the name for this CDC connector. It can be whatever you choose</li>
  <li>line 8 is the database hostname, it can also take an IP address</li>
  <li>line 10 indicates the replication slot you want to create in PostgreSQL server</li>
  <li>on line 11 I am using the <em>pgoutput</em> plugin. Other alternatives are <em>decoderbufs</em> and <em>wal2json</em>, to use
these alternatives, you have to install the plugins</li>
  <li>on line 15 I specify a server name (Can be any name you choose). This name is used by the connector
when creating the kafka topics. More on this in the next section.</li>
  <li>lines 16 and 17 I indicate which tables I want to capture changes on.</li>
</ul>

<p>You can read more on the debezium documentation.</p>

<p>The debezium connector will now recieve changes from the PostgreSQL WAL and publish them to Kafka.</p>

<p>I created a sink application to process the changes from Kafka.</p>

<h2 id="cdc-application">CDC Application</h2>

<p>I created a representation of the CDC payload from Kafka:</p>

<p>file: <a href="https://github.com/juliuskrah//keycloak-cdc/tree/master/app-service/src/main/java/com/juliuskrah/cdc/dto/KeycloakCdcDto.java">
  <code class="highlighter-rouge">app-service/src/main/java/com/juliuskrah/cdc/dto/KeycloakCdcDto.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">KeycloakCdcDto</span><span class="o">&lt;</span><span class="no">T</span><span class="o">&gt;</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Object</span><span class="o">&gt;</span> <span class="n">schema</span><span class="o">;</span>
    <span class="kd">private</span> <span class="nc">Payload</span><span class="o">&lt;</span><span class="no">T</span><span class="o">&gt;</span> <span class="n">payload</span><span class="o">;</span>

    <span class="c1">// Getters and Setters omitted for brevity</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">Payload</span><span class="o">&lt;</span><span class="no">T</span><span class="o">&gt;</span> <span class="o">{</span>
        <span class="kd">private</span> <span class="no">T</span> <span class="n">before</span><span class="o">;</span>
        <span class="kd">private</span> <span class="no">T</span> <span class="n">after</span><span class="o">;</span>
        <span class="kd">private</span> <span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Object</span><span class="o">&gt;</span> <span class="n">source</span><span class="o">;</span>
        <span class="kd">private</span> <span class="kt">char</span> <span class="n">op</span><span class="o">;</span>
        <span class="nd">@JsonProperty</span><span class="o">(</span><span class="s">"ts_ms"</span><span class="o">)</span>
        <span class="kd">private</span> <span class="nc">Instant</span> <span class="n">tsMs</span><span class="o">;</span>
        
        <span class="c1">// Getters and Setters omitted for brevity</span>
    <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>As already hinted in the previous section debezium creates topics in kafka for each table it captures
events on in the following format <code class="language-plaintext highlighter-rouge">&lt;database.server.name&gt;.&lt;schema_name&gt;.&lt;table_name&gt;</code>. In our example
above, the changes on the <code class="language-plaintext highlighter-rouge">user_entity</code> table will be stored in the <code class="language-plaintext highlighter-rouge">keycloak.sample.user_entity</code> topic.</p>

<p>And the consumer for the event:</p>

<p>file: <a href="https://github.com/juliuskrah//keycloak-cdc/tree/master/app-service/src/main/java/com/juliuskrah/cdc/sink/KafkaConsumer.java">
  <code class="highlighter-rouge">app-service/src/main/java/com/juliuskrah/cdc/sink/KafkaConsumer.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@KafkaListener</span><span class="o">(</span><span class="n">groupId</span> <span class="o">=</span> <span class="s">"${app.group.id:group-id}"</span><span class="o">,</span> <span class="n">offsetReset</span> <span class="o">=</span> <span class="nc">OffsetReset</span><span class="o">.</span><span class="na">EARLIEST</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">KafkaConsumer</span> <span class="o">{</span>

    <span class="nd">@Topic</span><span class="o">(</span><span class="s">"keycloak.sample.user_entity"</span><span class="o">)</span>
    <span class="kt">void</span> <span class="nf">onReceiveUser</span><span class="o">(</span><span class="nd">@KafkaKey</span> <span class="nc">String</span> <span class="n">key</span><span class="o">,</span> <span class="nd">@Nullable</span> <span class="nc">String</span> <span class="n">event</span><span class="o">)</span> <span class="o">{</span>
        <span class="c1">// process here</span>
    <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>The full source code is <a href="https://github.com/juliuskrah//keycloak-cdc/tree/master" target="_blank">in the github repository</a>.</p>

<h1 id="conclusion">Conclusion</h1>

<p>Integration between microservices in any deployment is crucial, and in this post I have discussed using
CDC to tackle it. We also tackled setting up PostgreSQL for replication, glanced over setting up Keycloak,
Zookeeper and Kafka. We looked at setting up the debezium Kafka Connector and a sample application to 
consume the CDC event stream. Until the next post, keep doing cool things :+1:.</p>

<h3 id="references">References</h3>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>https://en.wikipedia.org/wiki/Change_data_capture <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>https://debezium.io/documentation/reference/0.10/connectors/index.html <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3" role="doc-endnote">
      <p>https://www.postgresql.org/docs/12/high-availability.html <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:4" role="doc-endnote">
      <p>https://www.postgresql.org/docs/12/logical-replication-architecture.html <a href="#fnref:4" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;juliuskrah&quot;}</name></author><category term="blog" /><category term="java" /><category term="debezium" /><category term="micronaut" /><category term="cdc" /><category term="postgres" /><summary type="html"><![CDATA[Change data capture records insert, update, and delete activity that is applied to a relational database table.]]></summary></entry><entry><title type="html">Building an SMPP Application using Spring Boot</title><link href="http://juliuskrah.com/blog/2018/12/28/building-an-smpp-application-using-spring-boot/" rel="alternate" type="text/html" title="Building an SMPP Application using Spring Boot" /><published>2018-12-28T19:27:59+00:00</published><updated>2018-12-28T19:27:59+00:00</updated><id>http://juliuskrah.com/blog/2018/12/28/building-an-smpp-application-using-spring-boot</id><content type="html" xml:base="http://juliuskrah.com/blog/2018/12/28/building-an-smpp-application-using-spring-boot/"><![CDATA[<blockquote>
  <p>Short Message Peer-to-Peer (SMPP) is a protocol used by the telecommunications industry for exchanging 
  messages between Short Message Service Centers (SMSC) and/or External Short Messaging Entities (ESME).</p>
</blockquote>

<h1 id="introduction">Introduction</h1>

<p>In this post I will build a simple app that will send SMS using the SMPP protocol, bootstraped with Spring 
Boot. I will use the <a href="https://github.com/fizzed/cloudhopper-smpp" target="_blank">Cloudhopper</a> SMPP library for sending SMS. For
the <code class="language-plaintext highlighter-rouge">Camel Component</code> example, refer to this <a href="/blog/2020/03/27/building-an-smpp-application-using-spring-boot-and-camel/">Camel Post</a>.</p>

<p>SMPP is a level-7 TCP/IP protocol, which allows fast delivery of SMS messages. The most conmmonly used 
versions of SMPP are v3.3, the most widely supported standard, and v3.4, which adds transceiver support
(single connections that can send and receive messages).</p>

<h1 id="prerequisites">Prerequisites</h1>

<ul>
  <li><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Java Development Kit</a></li>
  <li><a href="http://maven.apache.org" target="_blank">Maven</a></li>
  <li>SMPP account that supports v3.4</li>
</ul>

<h2 id="project-structure">Project Structure</h2>

<p>At the end of this guide our folder structure will look similar to the following:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.
|__src/
|  |__main/
|  |  |__java/
|  |  |  |__com/
|  |  |  |  |__juliuskrah/
|  |  |  |  |  |__smpp/
|  |  |  |  |  |  |__Application.java
|  |  |  |  |  |  |__ApplicationProperties.java
|  |  |  |  |  |  |__ClientSmppSessionHandler.java
|  |  |  |  |  |  |__DeliveryReceipt.java
|  |  |__resources/
|  |  |  |__application.yaml
|__pom.xml
</code></pre></div></div>

<h2 id="project-setup">Project Setup</h2>

<p>Create a simple Spring Boot Application using any of the <a href="https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#getting-started-installing-spring-boot" target="_blank">bootstrap options</a>.</p>

<p>Add the following to your <code class="language-plaintext highlighter-rouge">pom.xml</code> after creating your Spring-Boot application:</p>

<figure class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="nt">&lt;dependency&gt;</span>
  <span class="nt">&lt;groupId&gt;</span>com.fizzed<span class="nt">&lt;/groupId&gt;</span>
  <span class="nt">&lt;artifactId&gt;</span>ch-smpp<span class="nt">&lt;/artifactId&gt;</span>
  <span class="nt">&lt;version&gt;</span>5.0.9<span class="nt">&lt;/version&gt;</span>
<span class="nt">&lt;/dependency&gt;</span></code></pre></figure>

<h1 id="configuring-the-smpp-session">Configuring the SMPP Session</h1>

<p>In order to start using SMPP to send messages, you need to establish a session. The session is usually
short-lived; we will implement long-lived sessions later in this post by extending the session 
periodically.</p>

<p>To bind a session, we need a <code class="language-plaintext highlighter-rouge">SmppSessionConfiguration</code> and <code class="language-plaintext highlighter-rouge">SmppClient</code>. The <code class="language-plaintext highlighter-rouge">SmppSessionConfiguration</code>
class contains the configurable aspects of the SmppSession. In this class you can configure the:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Host</code>:      [smpp.serviceprovider.com]</li>
  <li><code class="language-plaintext highlighter-rouge">Port</code>:      default 2775</li>
  <li><code class="language-plaintext highlighter-rouge">System Id</code>: [username]</li>
  <li><code class="language-plaintext highlighter-rouge">Password</code>:  [password]</li>
  <li><code class="language-plaintext highlighter-rouge">BindType</code>:  TRANSCEIVER, TRANSMITTER or RECEIVER</li>
  <li><code class="language-plaintext highlighter-rouge">Version</code>:   3.3, 3.4, 5.0</li>
</ul>

<p>Configuring this class will look something like the following:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="nc">SmppSessionConfiguration</span> <span class="nf">sessionConfiguration</span><span class="o">()</span> <span class="o">{</span>
  <span class="nc">SmppSessionConfiguration</span> <span class="n">sessionConfig</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">SmppSessionConfiguration</span><span class="o">();</span>
  <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setName</span><span class="o">(</span><span class="s">"smpp.session"</span><span class="o">);</span>
  <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setInterfaceVersion</span><span class="o">(</span><span class="nc">SmppConstants</span><span class="o">.</span><span class="na">VERSION_3_4</span><span class="o">);</span>
  <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setType</span><span class="o">(</span><span class="nc">SmppBindType</span><span class="o">.</span><span class="na">TRANSCEIVER</span><span class="o">);</span>
  <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setHost</span><span class="o">(</span><span class="s">"&lt;replace&gt;"</span><span class="o">);</span>
  <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setPort</span><span class="o">(</span><span class="mi">2775</span><span class="o">);</span>
  <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setSystemId</span><span class="o">(</span><span class="s">"&lt;replace&gt;"</span><span class="o">);</span>
  <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setPassword</span><span class="o">(</span><span class="s">"&lt;replace&gt;"</span><span class="o">);</span>
  <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setSystemType</span><span class="o">(</span><span class="kc">null</span><span class="o">);</span>
  <span class="n">sessionConfig</span><span class="o">.</span><span class="na">getLoggingOptions</span><span class="o">().</span><span class="na">setLogBytes</span><span class="o">(</span><span class="kc">false</span><span class="o">);</span>
  <span class="n">sessionConfig</span><span class="o">.</span><span class="na">getLoggingOptions</span><span class="o">().</span><span class="na">setLogPdu</span><span class="o">(</span><span class="kc">true</span><span class="o">);</span>

  <span class="k">return</span> <span class="n">sessionConfig</span><span class="o">;</span>
<span class="o">}</span></code></pre></figure>

<blockquote>
  <p>NOTE: Be sure to replace the values for <code class="language-plaintext highlighter-rouge">Host</code>, <code class="language-plaintext highlighter-rouge">SystemId</code> and <code class="language-plaintext highlighter-rouge">Password</code>.</p>
</blockquote>

<p>I have set the bind-type as <code class="language-plaintext highlighter-rouge">TRANSCEIVER</code> because I want to be able to send SMS and receive delivery 
receipts.</p>

<p>What I have to do next is create the <code class="language-plaintext highlighter-rouge">SmppClient</code>:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="nc">SmppClient</span> <span class="nf">clientBootstrap</span><span class="o">()</span> <span class="o">{</span>
  <span class="k">return</span> <span class="k">new</span> <span class="nf">DefaultSmppClient</span><span class="o">(</span><span class="nc">Executors</span><span class="o">.</span><span class="na">newCachedThreadPool</span><span class="o">(),</span> <span class="mi">2</span><span class="o">);</span>
<span class="o">}</span></code></pre></figure>

<p>The <code class="language-plaintext highlighter-rouge">DefaultSmppClient</code> constructor takes an <code class="language-plaintext highlighter-rouge">ExecutorService</code> and expected number of sessions. In the
example above I am creating a CachedThreadPoolExecutor and assigning 2 concurrent sessions.</p>

<p>With these two in place I can now establish my <code class="language-plaintext highlighter-rouge">SmppSession</code>:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@Bean</span><span class="o">(</span><span class="n">destroyMethod</span> <span class="o">=</span> <span class="s">"destroy"</span><span class="o">)</span>
<span class="kd">public</span> <span class="nc">SmppSession</span> <span class="nf">session</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">SmppBindException</span><span class="o">,</span> <span class="nc">SmppTimeoutException</span><span class="o">,</span> <span class="nc">SmppChannelException</span><span class="o">,</span>
    <span class="nc">UnrecoverablePduException</span><span class="o">,</span> <span class="nc">InterruptedException</span> <span class="o">{</span>
  <span class="nc">SmppSessionConfiguration</span> <span class="n">config</span> <span class="o">=</span> <span class="n">sessionConfiguration</span><span class="o">();</span>
  <span class="c1">// Will use the DefaultSmppSessionHandler for now</span>
  <span class="nc">SmppSession</span> <span class="n">session</span> <span class="o">=</span> <span class="n">clientBootstrap</span><span class="o">().</span><span class="na">bind</span><span class="o">(</span><span class="n">config</span><span class="o">,</span> <span class="k">new</span> <span class="nc">DefaultSmppSessionHandler</span><span class="o">());</span>

  <span class="k">return</span> <span class="n">session</span><span class="o">;</span>
<span class="o">}</span></code></pre></figure>

<p>In the above snippet, we are using a <code class="language-plaintext highlighter-rouge">DefaultSmppSessionHandler</code>. Later in this post I will create a 
custom <code class="language-plaintext highlighter-rouge">SmppSessionListener</code> that can handle delivery receipts.</p>

<p>At this point all necessary configuration is done. Everything wired up together until this point should
look like this:</p>

<p>file: <a href="https://github.com/juliuskrah/smpp/tree/master/src/main/java/com/juliuskrah/smpp/Application.java">
  <code class="highlighter-rouge">src/main/java/com/juliuskrah/smpp/Application.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@SpringBootApplication</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">Application</span> <span class="o">{</span>
  <span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="nc">Logger</span> <span class="n">log</span> <span class="o">=</span> <span class="nc">LoggerFactory</span><span class="o">.</span><span class="na">getLogger</span><span class="o">(</span><span class="nc">Application</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>

  <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">SpringApplication</span><span class="o">.</span><span class="na">run</span><span class="o">(</span><span class="nc">Application</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">args</span><span class="o">);</span>
  <span class="o">}</span>

  <span class="kd">public</span> <span class="nc">SmppSessionConfiguration</span> <span class="nf">sessionConfiguration</span><span class="o">()</span> <span class="o">{</span>
    <span class="nc">SmppSessionConfiguration</span> <span class="n">sessionConfig</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">SmppSessionConfiguration</span><span class="o">();</span>
    <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setName</span><span class="o">(</span><span class="s">"smpp.session"</span><span class="o">);</span>
    <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setInterfaceVersion</span><span class="o">(</span><span class="nc">SmppConstants</span><span class="o">.</span><span class="na">VERSION_3_4</span><span class="o">);</span>
    <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setType</span><span class="o">(</span><span class="nc">SmppBindType</span><span class="o">.</span><span class="na">TRANSCEIVER</span><span class="o">);</span>
    <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setHost</span><span class="o">(</span><span class="s">"&lt;replace&gt;"</span><span class="o">);</span>
    <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setPort</span><span class="o">(</span><span class="mi">2775</span><span class="o">);</span>
    <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setSystemId</span><span class="o">(</span><span class="s">"&lt;replace&gt;"</span><span class="o">);</span>
    <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setPassword</span><span class="o">(</span><span class="s">"&lt;replace&gt;"</span><span class="o">);</span>
    <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setSystemType</span><span class="o">(</span><span class="kc">null</span><span class="o">);</span>
    <span class="n">sessionConfig</span><span class="o">.</span><span class="na">getLoggingOptions</span><span class="o">().</span><span class="na">setLogBytes</span><span class="o">(</span><span class="kc">false</span><span class="o">);</span>
    <span class="n">sessionConfig</span><span class="o">.</span><span class="na">getLoggingOptions</span><span class="o">().</span><span class="na">setLogPdu</span><span class="o">(</span><span class="kc">true</span><span class="o">);</span>

    <span class="k">return</span> <span class="n">sessionConfig</span><span class="o">;</span>
  <span class="o">}</span>

  <span class="nd">@Bean</span><span class="o">(</span><span class="n">destroyMethod</span> <span class="o">=</span> <span class="s">"destroy"</span><span class="o">)</span>
  <span class="kd">public</span> <span class="nc">SmppSession</span> <span class="nf">session</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">SmppBindException</span><span class="o">,</span> <span class="nc">SmppTimeoutException</span><span class="o">,</span> <span class="nc">SmppChannelException</span><span class="o">,</span>
      <span class="nc">UnrecoverablePduException</span><span class="o">,</span> <span class="nc">InterruptedException</span> <span class="o">{</span>
    <span class="nc">SmppSessionConfiguration</span> <span class="n">config</span> <span class="o">=</span> <span class="n">sessionConfiguration</span><span class="o">();</span>
    <span class="nc">SmppSession</span> <span class="n">session</span> <span class="o">=</span> <span class="n">clientBootstrap</span><span class="o">().</span><span class="na">bind</span><span class="o">(</span><span class="n">config</span><span class="o">,</span> <span class="k">new</span> <span class="nc">DefaultSmppSessionHandler</span><span class="o">());</span>

    <span class="k">return</span> <span class="n">session</span><span class="o">;</span>
  <span class="o">}</span>

  <span class="kd">public</span> <span class="nc">SmppClient</span> <span class="nf">clientBootstrap</span><span class="o">()</span> <span class="o">{</span>
    <span class="k">return</span> <span class="k">new</span> <span class="nf">DefaultSmppClient</span><span class="o">(</span><span class="nc">Executors</span><span class="o">.</span><span class="na">newCachedThreadPool</span><span class="o">(),</span> <span class="mi">2</span><span class="o">);</span>
  <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>If you have setup your SMPP correctly with your service provider, run the code as a Spring-Boot app:</p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">mvn</span><span class="w"> </span><span class="nx">spring-boot:run</span></code></pre></figure>

<h2 id="send-an-sms">Send an SMS</h2>

<p>Stop the aplication if it is still running. I will add a simple method that sends an SMS on
application startup:</p>

<p>file: <a href="https://github.com/juliuskrah/smpp/tree/master/src/main/java/com/juliuskrah/smpp/Application.java">
  <code class="highlighter-rouge">src/main/java/com/juliuskrah/smpp/Application.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="c1">// ...</span>

<span class="kd">private</span> <span class="kt">void</span> <span class="nf">sendTextMessage</span><span class="o">(</span><span class="nc">SmppSession</span> <span class="n">session</span><span class="o">,</span> <span class="nc">String</span> <span class="n">sourceAddress</span><span class="o">,</span> <span class="nc">String</span> <span class="n">message</span><span class="o">,</span> <span class="nc">String</span> <span class="n">destinationAddress</span><span class="o">)</span> <span class="o">{</span>
  <span class="c1">// Check if session is still active</span>
  <span class="k">if</span> <span class="o">(</span><span class="n">session</span><span class="o">.</span><span class="na">isBound</span><span class="o">())</span> <span class="o">{</span>
    <span class="k">try</span> <span class="o">{</span>
      <span class="c1">// request delivery</span>
      <span class="kt">boolean</span> <span class="n">requestDlr</span> <span class="o">=</span> <span class="kc">true</span><span class="o">;</span>
      <span class="nc">SubmitSm</span> <span class="n">submit</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">SubmitSm</span><span class="o">();</span>
      <span class="kt">byte</span><span class="o">[]</span> <span class="n">textBytes</span><span class="o">;</span>
      <span class="n">textBytes</span> <span class="o">=</span> <span class="nc">CharsetUtil</span><span class="o">.</span><span class="na">encode</span><span class="o">(</span><span class="n">message</span><span class="o">,</span> <span class="nc">CharsetUtil</span><span class="o">.</span><span class="na">CHARSET_ISO_8859_1</span><span class="o">);</span>
      <span class="c1">// set encoding for sending SMS</span>
      <span class="n">submit</span><span class="o">.</span><span class="na">setDataCoding</span><span class="o">(</span><span class="nc">SmppConstants</span><span class="o">.</span><span class="na">DATA_CODING_LATIN1</span><span class="o">);</span>
      <span class="k">if</span> <span class="o">(</span><span class="n">requestDlr</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">submit</span><span class="o">.</span><span class="na">setRegisteredDelivery</span><span class="o">(</span><span class="nc">SmppConstants</span><span class="o">.</span><span class="na">REGISTERED_DELIVERY_SMSC_RECEIPT_REQUESTED</span><span class="o">);</span>
      <span class="o">}</span>

      <span class="k">if</span> <span class="o">(</span><span class="n">textBytes</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">&amp;&amp;</span> <span class="n">textBytes</span><span class="o">.</span><span class="na">length</span> <span class="o">&gt;</span> <span class="mi">255</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">submit</span><span class="o">.</span><span class="na">addOptionalParameter</span><span class="o">(</span>
            <span class="k">new</span> <span class="nf">Tlv</span><span class="o">(</span><span class="nc">SmppConstants</span><span class="o">.</span><span class="na">TAG_MESSAGE_PAYLOAD</span><span class="o">,</span> <span class="n">textBytes</span><span class="o">,</span> <span class="s">"message_payload"</span><span class="o">));</span>
      <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
        <span class="n">submit</span><span class="o">.</span><span class="na">setShortMessage</span><span class="o">(</span><span class="n">textBytes</span><span class="o">);</span>
      <span class="o">}</span>

      <span class="n">submit</span><span class="o">.</span><span class="na">setSourceAddress</span><span class="o">(</span><span class="k">new</span> <span class="nc">Address</span><span class="o">((</span><span class="kt">byte</span><span class="o">)</span> <span class="mh">0x05</span><span class="o">,</span> <span class="o">(</span><span class="kt">byte</span><span class="o">)</span> <span class="mh">0x01</span><span class="o">,</span> <span class="n">sourceAddress</span><span class="o">));</span>
      <span class="n">submit</span><span class="o">.</span><span class="na">setDestAddress</span><span class="o">(</span><span class="k">new</span> <span class="nc">Address</span><span class="o">((</span><span class="kt">byte</span><span class="o">)</span> <span class="mh">0x01</span><span class="o">,</span> <span class="o">(</span><span class="kt">byte</span><span class="o">)</span> <span class="mh">0x01</span><span class="o">,</span> <span class="n">destinationAddress</span><span class="o">));</span>
      <span class="c1">// submit message to SMSC for delivery with a timeout of 10000ms</span>
      <span class="nc">SubmitSmResp</span> <span class="n">submitResponse</span> <span class="o">=</span> <span class="n">session</span><span class="o">.</span><span class="na">submit</span><span class="o">(</span><span class="n">submit</span><span class="o">,</span> <span class="mi">10000</span><span class="o">);</span>
      <span class="k">if</span> <span class="o">(</span><span class="n">submitResponse</span><span class="o">.</span><span class="na">getCommandStatus</span><span class="o">()</span> <span class="o">==</span> <span class="nc">SmppConstants</span><span class="o">.</span><span class="na">STATUS_OK</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">log</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"SMS submitted, message id {}"</span><span class="o">,</span> <span class="n">submitResponse</span><span class="o">.</span><span class="na">getMessageId</span><span class="o">());</span>
      <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
        <span class="k">throw</span> <span class="k">new</span> <span class="nf">IllegalStateException</span><span class="o">(</span><span class="n">submitResponse</span><span class="o">.</span><span class="na">getResultMessage</span><span class="o">());</span>
      <span class="o">}</span>
    <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">RecoverablePduException</span> <span class="o">|</span> <span class="nc">UnrecoverablePduException</span> <span class="o">|</span> <span class="nc">SmppTimeoutException</span> <span class="o">|</span> 
        <span class="nc">SmppChannelException</span> <span class="o">|</span> <span class="nc">InterruptedException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">throw</span> <span class="k">new</span> <span class="nf">IllegalStateException</span><span class="o">(</span><span class="n">e</span><span class="o">);</span>
    <span class="o">}</span>
    <span class="k">return</span><span class="o">;</span>
  <span class="o">}</span>
  <span class="k">throw</span> <span class="k">new</span> <span class="nf">IllegalStateException</span><span class="o">(</span><span class="s">"SMPP session is not connected"</span><span class="o">);</span>
<span class="o">}</span></code></pre></figure>

<p>Finally, let us call the method to send SMS:</p>

<p>file: <a href="https://github.com/juliuskrah/smpp/tree/master/src/main/java/com/juliuskrah/smpp/Application.java">
  <code class="highlighter-rouge">src/main/java/com/juliuskrah/smpp/Application.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="c1">// ...</span>

<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
  <span class="nc">ConfigurableApplicationContext</span> <span class="n">ctx</span> <span class="o">=</span> <span class="nc">SpringApplication</span><span class="o">.</span><span class="na">run</span><span class="o">(</span><span class="nc">Application</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">args</span><span class="o">);</span>
  <span class="nc">SmppSession</span> <span class="n">session</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">.</span><span class="na">getBean</span><span class="o">(</span><span class="nc">SmppSession</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
  <span class="k">new</span> <span class="nf">Application</span><span class="o">().</span><span class="na">sendTextMessage</span><span class="o">(</span><span class="n">session</span><span class="o">,</span> <span class="s">"3299"</span><span class="o">,</span> <span class="s">"Hello World"</span><span class="o">,</span> <span class="s">"&lt;replace with phone number&gt;"</span><span class="o">);</span>
<span class="o">}</span></code></pre></figure>

<p>Add your phone number to <code class="language-plaintext highlighter-rouge">destinationAddress</code> and run the application. Remember to use the international
phone number format.</p>

<p>At this point you are done and can choose not to follow the rest of this post.</p>

<h2 id="making-it-better">Making it Better</h2>

<p>You may have noticed that, we hardcoded certain things like username, password and host in the source code.
This does not make the app very portable. Let’s make use of externalized configuration, which has extensive
support in Spring-Boot.</p>

<p>I will create a class <code class="language-plaintext highlighter-rouge">ApplicationProperties</code> which contains all the external properties we need:</p>

<p>file: <a href="https://github.com/juliuskrah/smpp/tree/master/src/main/java/com/juliuskrah/smpp/ApplicationProperties.java">
  <code class="highlighter-rouge">src/main/java/com/juliuskrah/smpp/ApplicationProperties.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@ConfigurationProperties</span><span class="o">(</span><span class="s">"sms"</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">ApplicationProperties</span> <span class="o">{</span>
  <span class="nd">@NestedConfigurationProperty</span>
  <span class="kd">private</span> <span class="kd">final</span> <span class="nc">Async</span> <span class="n">async</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Async</span><span class="o">();</span>
  <span class="nd">@NestedConfigurationProperty</span>
  <span class="kd">private</span> <span class="kd">final</span> <span class="no">SMPP</span> <span class="n">smpp</span> <span class="o">=</span> <span class="k">new</span> <span class="no">SMPP</span><span class="o">();</span>

  <span class="kd">public</span> <span class="nc">Async</span> <span class="nf">getAsync</span><span class="o">()</span> <span class="o">{</span>
    <span class="k">return</span> <span class="n">async</span><span class="o">;</span>
  <span class="o">}</span>

  <span class="kd">public</span> <span class="no">SMPP</span> <span class="nf">getSmpp</span><span class="o">()</span> <span class="o">{</span>
    <span class="k">return</span> <span class="n">smpp</span><span class="o">;</span>
  <span class="o">}</span>

  <span class="kd">public</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">Async</span> <span class="o">{</span>
    <span class="cm">/**
     * This number should be lower than the value assigned to the core-pool-size
     */</span>
    <span class="kd">private</span> <span class="kt">int</span> <span class="n">smppSessionSize</span> <span class="o">=</span> <span class="mi">2</span><span class="o">;</span>
    <span class="kd">private</span> <span class="kt">int</span> <span class="n">corePoolSize</span> <span class="o">=</span> <span class="mi">5</span><span class="o">;</span>
    <span class="kd">private</span> <span class="kt">int</span> <span class="n">maxPoolSize</span> <span class="o">=</span> <span class="mi">50</span><span class="o">;</span>
    <span class="kd">private</span> <span class="kt">int</span> <span class="n">queueCapacity</span> <span class="o">=</span> <span class="mi">10000</span><span class="o">;</span>
    <span class="kd">private</span> <span class="kt">int</span> <span class="n">initialDelay</span> <span class="o">=</span> <span class="mi">1000</span><span class="o">;</span>
    <span class="kd">private</span> <span class="kt">int</span> <span class="n">timeout</span> <span class="o">=</span> <span class="mi">10000</span><span class="o">;</span>

    <span class="c1">// omitted getters and setters</span>
  <span class="o">}</span>

  <span class="kd">public</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">SMPP</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="nc">String</span> <span class="n">host</span><span class="o">;</span>
    <span class="kd">private</span> <span class="nc">String</span> <span class="n">userId</span><span class="o">;</span>
    <span class="kd">private</span> <span class="nc">String</span> <span class="n">password</span><span class="o">;</span>
    <span class="kd">private</span> <span class="kt">int</span> <span class="n">port</span> <span class="o">=</span> <span class="mi">2775</span><span class="o">;</span>
    <span class="kd">private</span> <span class="kt">boolean</span> <span class="n">requestDelivery</span> <span class="o">=</span> <span class="kc">false</span><span class="o">;</span>
    <span class="kd">private</span> <span class="kt">boolean</span> <span class="n">detectDlrByOpts</span> <span class="o">=</span> <span class="kc">false</span><span class="o">;</span>

    <span class="c1">// omitted getters and setters</span>
  <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>I have added default values for most of the setings in the above class. I will override some of the 
defaults in a yaml file:</p>

<p>file: <a href="https://github.com/juliuskrah/smpp/tree/master/src/main/resources/application.yaml">
  <code class="highlighter-rouge">src/main/resources/application.yaml</code>
</a></p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="na">sms</span><span class="pi">:</span>
  <span class="na">smpp</span><span class="pi">:</span>
    <span class="na">host</span><span class="pi">:</span> <span class="s">&lt;replace&gt;</span>
    <span class="na">user-id</span><span class="pi">:</span> <span class="s">&lt;replace&gt;</span>
    <span class="na">password</span><span class="pi">:</span> <span class="s">&lt;replace&gt;</span>
    <span class="na">requestDelivery</span><span class="pi">:</span> <span class="no">true</span></code></pre></figure>

<p>In the above, I am overriding the default value of <code class="language-plaintext highlighter-rouge">requestDelivery</code> to <code class="language-plaintext highlighter-rouge">true</code>.</p>

<p>In order to use this in our simple application, I need to register the <code class="language-plaintext highlighter-rouge">ApplicationProperties</code>
configuration class:</p>

<p>file: <a href="https://github.com/juliuskrah/smpp/tree/master/src/main/java/com/juliuskrah/smpp/Application.java">
  <code class="highlighter-rouge">src/main/java/com/juliuskrah/smpp/Application.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@SpringBootApplication</span>
<span class="nd">@EnableConfigurationProperties</span><span class="o">(</span><span class="nc">ApplicationProperties</span><span class="o">.</span><span class="na">class</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">Application</span> <span class="o">{</span>
  <span class="c1">// ...</span>
<span class="o">}</span></code></pre></figure>

<p>I will rewrite <code class="language-plaintext highlighter-rouge">sessionConfiguration</code> method to use the externalized configuration:</p>

<p>file: <a href="https://github.com/juliuskrah/smpp/tree/master/src/main/java/com/juliuskrah/smpp/Application.java">
  <code class="highlighter-rouge">src/main/java/com/juliuskrah/smpp/Application.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="c1">// ...</span>

<span class="kd">public</span> <span class="nc">SmppSessionConfiguration</span> <span class="nf">sessionConfiguration</span><span class="o">(</span><span class="nc">ApplicationProperties</span> <span class="n">properties</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">SmppSessionConfiguration</span> <span class="n">sessionConfig</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">SmppSessionConfiguration</span><span class="o">();</span>
  <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setName</span><span class="o">(</span><span class="s">"smpp.session"</span><span class="o">);</span>
  <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setInterfaceVersion</span><span class="o">(</span><span class="nc">SmppConstants</span><span class="o">.</span><span class="na">VERSION_3_4</span><span class="o">);</span>
  <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setType</span><span class="o">(</span><span class="nc">SmppBindType</span><span class="o">.</span><span class="na">TRANSCEIVER</span><span class="o">);</span>
  <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setHost</span><span class="o">(</span><span class="n">properties</span><span class="o">.</span><span class="na">getSmpp</span><span class="o">().</span><span class="na">getHost</span><span class="o">());</span>
  <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setPort</span><span class="o">(</span><span class="n">properties</span><span class="o">.</span><span class="na">getSmpp</span><span class="o">().</span><span class="na">getPort</span><span class="o">());</span>
  <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setSystemId</span><span class="o">(</span><span class="n">properties</span><span class="o">.</span><span class="na">getSmpp</span><span class="o">().</span><span class="na">getUserId</span><span class="o">());</span>
  <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setPassword</span><span class="o">(</span><span class="n">properties</span><span class="o">.</span><span class="na">getSmpp</span><span class="o">().</span><span class="na">getPassword</span><span class="o">());</span>
  <span class="n">sessionConfig</span><span class="o">.</span><span class="na">setSystemType</span><span class="o">(</span><span class="kc">null</span><span class="o">);</span>
  <span class="n">sessionConfig</span><span class="o">.</span><span class="na">getLoggingOptions</span><span class="o">().</span><span class="na">setLogBytes</span><span class="o">(</span><span class="kc">false</span><span class="o">);</span>
  <span class="n">sessionConfig</span><span class="o">.</span><span class="na">getLoggingOptions</span><span class="o">().</span><span class="na">setLogPdu</span><span class="o">(</span><span class="kc">true</span><span class="o">);</span>

  <span class="k">return</span> <span class="n">sessionConfig</span><span class="o">;</span>
<span class="o">}</span></code></pre></figure>

<p>At the beginning of this post I talked about receiving delivery receipts. The default implementation of
<code class="language-plaintext highlighter-rouge">SmppSessionListener</code> is to discard received PDUs. So I will extend the default implementation class and
handle delivery receipts in there:</p>

<p>file: <a href="https://github.com/juliuskrah/smpp/tree/master/src/main/java/com/juliuskrah/smpp/ClientSmppSessionHandler.java">
  <code class="highlighter-rouge">src/main/java/com/juliuskrah/smpp/ClientSmppSessionHandler.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">ClientSmppSessionHandler</span> <span class="kd">extends</span> <span class="nc">DefaultSmppSessionHandler</span> <span class="o">{</span>
  <span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="nc">Logger</span> <span class="n">log</span> <span class="o">=</span> <span class="nc">LoggerFactory</span><span class="o">.</span><span class="na">getLogger</span><span class="o">(</span><span class="nc">ClientSmppSessionHandler</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
  <span class="kd">private</span> <span class="kd">final</span> <span class="nc">ApplicationProperties</span> <span class="n">properties</span><span class="o">;</span>

  <span class="kd">public</span> <span class="nf">ClientSmppSessionHandler</span><span class="o">(</span><span class="nc">ApplicationProperties</span> <span class="n">properties</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">this</span><span class="o">.</span><span class="na">properties</span> <span class="o">=</span> <span class="n">properties</span><span class="o">;</span>
  <span class="o">}</span>

  <span class="kd">private</span> <span class="nc">String</span> <span class="nf">mapDataCodingToCharset</span><span class="o">(</span><span class="kt">byte</span> <span class="n">dataCoding</span><span class="o">)</span> <span class="o">{</span>
    <span class="c1">// implementaion in the github repository</span>
  <span class="o">}</span>

  <span class="nd">@Override</span>
  <span class="nd">@SuppressWarnings</span><span class="o">(</span><span class="s">"rawtypes"</span><span class="o">)</span>
  <span class="kd">public</span> <span class="nc">PduResponse</span> <span class="nf">firePduRequestReceived</span><span class="o">(</span><span class="nc">PduRequest</span> <span class="n">request</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">PduResponse</span> <span class="n">response</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
    <span class="k">try</span> <span class="o">{</span>
      <span class="k">if</span> <span class="o">(</span><span class="n">request</span> <span class="k">instanceof</span> <span class="nc">DeliverSm</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">String</span> <span class="n">sourceAddress</span> <span class="o">=</span> <span class="o">((</span><span class="nc">DeliverSm</span><span class="o">)</span> <span class="n">request</span><span class="o">).</span><span class="na">getSourceAddress</span><span class="o">().</span><span class="na">getAddress</span><span class="o">();</span>
        <span class="nc">String</span> <span class="n">message</span> <span class="o">=</span> <span class="nc">CharsetUtil</span><span class="o">.</span><span class="na">decode</span><span class="o">(((</span><span class="nc">DeliverSm</span><span class="o">)</span> <span class="n">request</span><span class="o">).</span><span class="na">getShortMessage</span><span class="o">(),</span>
            <span class="n">mapDataCodingToCharset</span><span class="o">(((</span><span class="nc">DeliverSm</span><span class="o">)</span> <span class="n">request</span><span class="o">).</span><span class="na">getDataCoding</span><span class="o">()));</span>
        <span class="n">log</span><span class="o">.</span><span class="na">debug</span><span class="o">(</span><span class="s">"SMS Message Received: {}, Source Address: {}"</span><span class="o">,</span> <span class="n">message</span><span class="o">.</span><span class="na">trim</span><span class="o">(),</span> <span class="n">sourceAddress</span><span class="o">);</span>

        <span class="kt">boolean</span> <span class="n">isDeliveryReceipt</span> <span class="o">=</span> <span class="kc">false</span><span class="o">;</span>
        <span class="k">if</span> <span class="o">(</span><span class="n">properties</span><span class="o">.</span><span class="na">getSmpp</span><span class="o">().</span><span class="na">isDetectDlrByOpts</span><span class="o">())</span> <span class="o">{</span>
          <span class="n">isDeliveryReceipt</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="na">getOptionalParameters</span><span class="o">()</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">;</span>
        <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
          <span class="n">isDeliveryReceipt</span> <span class="o">=</span> <span class="nc">SmppUtil</span><span class="o">.</span><span class="na">isMessageTypeAnyDeliveryReceipt</span><span class="o">(</span>
            <span class="o">((</span><span class="nc">DeliverSm</span><span class="o">)</span> <span class="n">request</span><span class="o">).</span><span class="na">getEsmClass</span><span class="o">());</span>
        <span class="o">}</span>

        <span class="k">if</span> <span class="o">(</span><span class="n">isDeliveryReceipt</span><span class="o">)</span> <span class="o">{</span>
          <span class="nc">DeliveryReceipt</span> <span class="n">dlr</span> <span class="o">=</span> <span class="nc">DeliveryReceipt</span><span class="o">.</span><span class="na">parseShortMessage</span><span class="o">(</span><span class="n">message</span><span class="o">,</span> <span class="nc">ZoneOffset</span><span class="o">.</span><span class="na">UTC</span><span class="o">);</span>
          <span class="c1">// logging delivery here, but you can do something more useful over here</span>
          <span class="n">log</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Received delivery from {} at {} with message-id {} and status {}"</span><span class="o">,</span> <span class="n">sourceAddress</span><span class="o">,</span>
              <span class="n">dlr</span><span class="o">.</span><span class="na">getDoneDate</span><span class="o">(),</span> <span class="n">dlr</span><span class="o">.</span><span class="na">getMessageId</span><span class="o">(),</span> <span class="nc">DeliveryReceipt</span><span class="o">.</span><span class="na">toStateText</span><span class="o">(</span><span class="n">dlr</span><span class="o">.</span><span class="na">getState</span><span class="o">()));</span>
        <span class="o">}</span>
      <span class="o">}</span>
      <span class="n">response</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="na">createResponse</span><span class="o">();</span>
    <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">Throwable</span> <span class="n">error</span><span class="o">)</span> <span class="o">{</span>
      <span class="n">log</span><span class="o">.</span><span class="na">warn</span><span class="o">(</span><span class="s">"Error while handling delivery"</span><span class="o">,</span> <span class="n">error</span><span class="o">);</span>
      <span class="n">response</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="na">createResponse</span><span class="o">();</span>
      <span class="n">response</span><span class="o">.</span><span class="na">setResultMessage</span><span class="o">(</span><span class="n">error</span><span class="o">.</span><span class="na">getMessage</span><span class="o">());</span>
      <span class="n">response</span><span class="o">.</span><span class="na">setCommandStatus</span><span class="o">(</span><span class="nc">SmppConstants</span><span class="o">.</span><span class="na">STATUS_UNKNOWNERR</span><span class="o">);</span>
    <span class="o">}</span>
    <span class="k">return</span> <span class="n">response</span><span class="o">;</span>
  <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>The <code class="language-plaintext highlighter-rouge">DeliveryReceipt</code> class is a utility class I created to extract delivery details from <code class="language-plaintext highlighter-rouge">PduRequest</code>. 
I will not paste the contents of the class here (it is quite lengthy), you can view its contents in the 
<a href="https://github.com/juliuskrah/smpp/tree/master/src/main/java/com/juliuskrah/smpp/DeliveryReceipt.java">Github repository</a>.</p>

<p>We just need to register this handler to take advantage of the delivery receipt handling:</p>

<p>file: <a href="https://github.com/juliuskrah/smpp/tree/master/src/main/java/com/juliuskrah/smpp/Application.java">
  <code class="highlighter-rouge">src/main/java/com/juliuskrah/smpp/Application.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@Bean</span><span class="o">(</span><span class="n">destroyMethod</span> <span class="o">=</span> <span class="s">"destroy"</span><span class="o">)</span>
<span class="kd">public</span> <span class="nc">SmppSession</span> <span class="nf">session</span><span class="o">(</span><span class="nc">ApplicationProperties</span> <span class="n">properties</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">SmppBindException</span><span class="o">,</span> 
    <span class="nc">SmppTimeoutException</span><span class="o">,</span> <span class="nc">SmppChannelException</span><span class="o">,</span>
    <span class="nc">UnrecoverablePduException</span><span class="o">,</span> <span class="nc">InterruptedException</span> <span class="o">{</span>
  <span class="nc">SmppSessionConfiguration</span> <span class="n">config</span> <span class="o">=</span> <span class="n">sessionConfiguration</span><span class="o">(</span><span class="n">properties</span><span class="o">);</span>
  <span class="nc">SmppSession</span> <span class="n">session</span> <span class="o">=</span> <span class="n">clientBootstrap</span><span class="o">().</span><span class="na">bind</span><span class="o">(</span><span class="n">config</span><span class="o">,</span> <span class="k">new</span> <span class="nc">ClientSmppSessionHandler</span><span class="o">(</span><span class="n">properties</span><span class="o">));</span>

  <span class="k">return</span> <span class="n">session</span><span class="o">;</span>
<span class="o">}</span></code></pre></figure>

<p>If you run the application now, you will see delivery receipts printed in the console. This solution 
however is far from ideal. As I said earlier, the Sessions are short-lived; given a scenario where
a mobile device is switched off, the SMS will be delivered only when the device is switched back on.
In this same scenario, the SMPP Session may be closed when the delivery is received, leading to lost
delivery receipts. To overcome this limitation I have to design the application to periodically refresh
the session before it un-binds.</p>

<p>I will use <code class="language-plaintext highlighter-rouge">EnquireLinkResp</code> to periodically extend the session:</p>

<p>file: <a href="https://github.com/juliuskrah/smpp/tree/master/src/main/java/com/juliuskrah/smpp/Application.java">
  <code class="highlighter-rouge">src/main/java/com/juliuskrah/smpp/Application.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@EnableScheduling</span>
<span class="nd">@SpringBootApplication</span>
<span class="nd">@EnableConfigurationProperties</span><span class="o">(</span><span class="nc">ApplicationProperties</span><span class="o">.</span><span class="na">class</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">Application</span> <span class="o">{</span>
  <span class="c1">// ...</span>

  <span class="nd">@Scheduled</span><span class="o">(</span>
      <span class="n">initialDelayString</span> <span class="o">=</span> <span class="s">"${sms.async.initial-delay}"</span><span class="o">,</span> 
      <span class="n">fixedDelayString</span> <span class="o">=</span> <span class="s">"${sms.async.initial-delay}"</span><span class="o">)</span>
  <span class="kt">void</span> <span class="nf">enquireLinkJob</span><span class="o">()</span> <span class="o">{</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">session</span><span class="o">.</span><span class="na">isBound</span><span class="o">())</span> <span class="o">{</span>
      <span class="k">try</span> <span class="o">{</span>
        <span class="n">log</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"sending enquire_link"</span><span class="o">);</span>
        <span class="nc">EnquireLinkResp</span> <span class="n">enquireLinkResp</span> <span class="o">=</span> <span class="n">session</span><span class="o">.</span><span class="na">enquireLink</span><span class="o">(</span><span class="k">new</span> <span class="nc">EnquireLink</span><span class="o">(),</span>
            <span class="n">properties</span><span class="o">.</span><span class="na">getAsync</span><span class="o">().</span><span class="na">getTimeout</span><span class="o">());</span>
        <span class="n">log</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"enquire_link_resp: {}"</span><span class="o">,</span> <span class="n">enquireLinkResp</span><span class="o">);</span>
      <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">SmppTimeoutException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">log</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Enquire link failed, executing reconnect; "</span> <span class="o">+</span> <span class="n">e</span><span class="o">);</span>
        <span class="n">log</span><span class="o">.</span><span class="na">error</span><span class="o">(</span><span class="s">""</span><span class="o">,</span> <span class="n">e</span><span class="o">);</span>
      <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">SmppChannelException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">log</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Enquire link failed, executing reconnect; "</span> <span class="o">+</span> <span class="n">e</span><span class="o">);</span>
        <span class="n">log</span><span class="o">.</span><span class="na">warn</span><span class="o">(</span><span class="s">""</span><span class="o">,</span> <span class="n">e</span><span class="o">);</span>
      <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">InterruptedException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">log</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Enquire link interrupted, probably killed by reconnecting"</span><span class="o">);</span>
      <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">Exception</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">log</span><span class="o">.</span><span class="na">error</span><span class="o">(</span><span class="s">"Enquire link failed, executing reconnect"</span><span class="o">,</span> <span class="n">e</span><span class="o">);</span>
      <span class="o">}</span>
    <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
      <span class="n">log</span><span class="o">.</span><span class="na">error</span><span class="o">(</span><span class="s">"enquire link running while session is not connected"</span><span class="o">);</span>
    <span class="o">}</span>
  <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>I have added annotation on top of the class to <code class="language-plaintext highlighter-rouge">@EnableScheduling</code> which allows spring to process
the <code class="language-plaintext highlighter-rouge">@Scheduled</code> annotation. The fixedDelayString value <code class="language-plaintext highlighter-rouge">${sms.async.initial-delay}</code> is set in the 
<code class="language-plaintext highlighter-rouge">application.yaml</code> file:</p>

<p>file: <a href="https://github.com/juliuskrah/smpp/tree/master/src/main/resources/application.yaml">
  <code class="highlighter-rouge">src/main/resources/application.yaml</code>
</a></p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="na">sms</span><span class="pi">:</span>
  <span class="na">async</span><span class="pi">:</span>
    <span class="na">initial-delay</span><span class="pi">:</span> <span class="s">30000</span></code></pre></figure>

<p>This will cause the application to enquire link every 30 seconds. This solution is far from perfect. When 
internet connectivity is lost on the server running the application, this will not work. Also when the 
Session unexpectedly unbinds this solution will not work. I have implemented a more robust solution
on the <code class="language-plaintext highlighter-rouge">persistent</code> branch of the Github repository accompanying this post.</p>

<p>Before we wrap up, it is not very good practice to store sentive information in plain text on files. There 
are several best practices and solutions out there e.g. using Vault from Hashicorp. I am going to implement
the simplest solution by using environment variables:</p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">set</span><span class="w"> </span><span class="nx">SMS_SMPP_HOST</span><span class="o">=</span><span class="err">&lt;</span><span class="n">host</span><span class="err">&gt;</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">set</span><span class="w"> </span><span class="nx">SMS_SMPP_USER_ID</span><span class="o">=</span><span class="err">&lt;</span><span class="n">user</span><span class="err">&gt;</span><span class="w">
</span><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">set</span><span class="w"> </span><span class="nx">SMS_SMPP_PASSWORD</span><span class="o">=</span><span class="err">&lt;</span><span class="n">password</span><span class="err">&gt;</span></code></pre></figure>

<h1 id="conclusion">Conclusion</h1>

<p>In this post we looked briefly at the SMPP protocol and its usage within the JVM. We also covered how to 
use Spring Boot to make developing an SMPP client easier.</p>

<p>As usual you can find the full example to this guide <a href="https://github.com/juliuskrah/smpp/tree/master" target="_blank">in the github repository</a>. Until the next post, keep
doing cool things :+1:.</p>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;juliuskrah&quot;}</name></author><category term="blog" /><category term="java" /><category term="spring-boot" /><category term="maven" /><summary type="html"><![CDATA[Short Message Peer-to-Peer (SMPP) is a protocol used by the telecommunications industry for exchanging messages between Short Message Service Centers (SMSC) and/or External Short Messaging Entities (ESME).]]></summary></entry><entry><title type="html">Introduction to Microservices Using Spring-Boot</title><link href="http://juliuskrah.com/blog/2018/08/17/introduction-to-microservices-using-spring-boot/" rel="alternate" type="text/html" title="Introduction to Microservices Using Spring-Boot" /><published>2018-08-17T17:50:52+00:00</published><updated>2018-08-17T17:50:52+00:00</updated><id>http://juliuskrah.com/blog/2018/08/17/introduction-to-microservices-using-spring-boot</id><content type="html" xml:base="http://juliuskrah.com/blog/2018/08/17/introduction-to-microservices-using-spring-boot/"><![CDATA[<blockquote>
  <p>Microservices enable different teams to work on smaller pieces, using independent technologies, producing safer, more frequent 
  deployments</p>
</blockquote>

<h1 id="introduction">Introduction</h1>

<p>If you are not already using Microservices, you are safely out of the early adopter phase of the adoption curve, and it is probably time
to get started. In this article, we will demonstrate the essential components for creating RESTful microservices, using <code class="language-plaintext highlighter-rouge">Consul</code> service 
registry, <code class="language-plaintext highlighter-rouge">Spring Boot</code> for all the scaffolding, dependency injection, and dependencies, <code class="language-plaintext highlighter-rouge">Maven</code> for the build, and Spring REST.</p>

<p>Over the last two decades, enterprise has become very agile in our SDLC process, but our applications tend to still be rather monolith, 
with huge jars supporting all of the varied APIs and versions in play. But nowadays there is a push towards more Lean, DevOps-ey 
processes, and functionality is becoming “serverless”. Refactoring to Microservices can decouple code and resources, make builds smaller,
releases safer, and APIs more stable.</p>

<h1 id="prerequisites">Prerequisites</h1>

<ul>
  <li><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Java Development Kit</a></li>
  <li><a href="http://maven.apache.org" target="_blank">Maven</a></li>
  <li><a href="https://www.docker.com/" target="_blank">Docker</a> (Optional)</li>
</ul>

<h1 id="purpose">Purpose</h1>

<p>In this post, we will build a simple geospatial application that clients can call with two spatial points. The <code class="language-plaintext highlighter-rouge">points</code> microservice will
send the points the client submitted to a <code class="language-plaintext highlighter-rouge">distance</code> microservice to calculate the distance between the given points, and then return 
the result to the points service, exposing all that via a rest call.</p>

<p class="image-caption"><img src="https://i.imgur.com/a5rQivV.png" alt="Architecture" /></p>
<p><em>Microservice Architecture</em></p>

<h2 id="project-structure">Project Structure</h2>

<p>At the end of this guide our folder structure will look similar to the following:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.
|__distance/
|  |__src/
|  |  |__main/
|  |  |  |__java/
|  |  |  |  |__com/
|  |  |  |  |  |__juliuskrah/
|  |  |  |  |  |  |__distance
|  |  |  |  |  |  |  |__DistanceApplication.java
|  |  |  |__resources/
|  |  |  |  |__application.yaml
|  |  |  |  |__bootstrap.yaml
|  |__pom.xml
|__points/
|  |__src/
|  |  |__main/
|  |  |  |__java/
|  |  |  |  |__com/
|  |  |  |  |  |__juliuskrah/
|  |  |  |  |  |  |__point/
|  |  |  |  |  |  |  |__PointsApplication.java
|  |  |  |__resources/
|  |  |  |  |__application.yaml
|  |  |  |  |__bootstrap.yaml
|  |__pom.xml
</code></pre></div></div>

<p>Before we get to work on creating our microservices, let’s prepare our environment by setting up <code class="language-plaintext highlighter-rouge">Consul</code>.</p>

<h2 id="download-consul-service-registry">Download Consul Service Registry</h2>
<p>We will be using Hashicorp Consul for service discovery, so head over to <a href="https://www.consul.io/downloads.html" target="_blank">https://www.consul.io/downloads.html</a>
and download Consul, for Windows, Linux, Mac, etc. That will provide an executable that you will want to add to your path.</p>

<p>From a shell prompt, launch Consul in dev mode:</p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">consul</span><span class="w"> </span><span class="nx">agent</span><span class="w"> </span><span class="nt">-dev</span></code></pre></figure>

<p>If you prefer to use docker, here’s the command to start consul in dev mode:</p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">docker</span><span class="w"> </span><span class="nx">run</span><span class="w"> </span><span class="nt">-d</span><span class="w"> </span><span class="nt">--name</span><span class="o">=</span><span class="n">dev-consul</span><span class="w"> </span><span class="nt">-e</span><span class="w"> </span><span class="nx">CONSUL_BIND_INTERFACE</span><span class="o">=</span><span class="n">eth0</span><span class="w"> </span><span class="nx">consul</span></code></pre></figure>

<p>To verify that it is running, head over to a browser and access the consul UI <a href="http://localhost:8500" target="_blank">http://localhost:8500</a>. 
If all is well, consul should report that it is alive and well.</p>

<p class="image-caption"><img src="https://i.imgur.com/S2mPRhr.png" alt="Consul Up" /></p>
<p><em>Consul running on port 8500</em></p>

<p>If there are any issues at this point, be sure ports <code class="language-plaintext highlighter-rouge">8500</code> and <code class="language-plaintext highlighter-rouge">8600</code> are available.</p>

<h1 id="create-the-springboot-application">Create the SpringBoot application</h1>

<p>We will use <a href="https://start.spring.io/" target="_blank">Spring Intitializr</a> to create the scaffolding for our SpringBoot applications.
Head over to the <em>Spring Initializr</em> webapp and create the <em>distance microservice</em>. Select <strong>Web</strong> and <strong>Consul Discovery</strong> then
click <em>Generate Project</em> to download a zip file. Extract this zip file and load the project into your favorite IDE or text editor.</p>

<p class="image-caption"><img src="https://i.imgur.com/JUUH1N8.png" alt="Distance Service" /></p>
<p><em>Generate Distance Microservice</em></p>

<p>We can use the generated <code class="language-plaintext highlighter-rouge">application.properties</code>, but Spring-Boot also recognizes <code class="language-plaintext highlighter-rouge">YAML</code> format, and that’s a little easier to
visualize, so let’s rename it <code class="language-plaintext highlighter-rouge">application.yaml</code>. Also create a <code class="language-plaintext highlighter-rouge">bootstrap.yaml</code> file.</p>

<p>We will name the microservice <code class="language-plaintext highlighter-rouge">distance</code>. We can specify a port or use port <code class="language-plaintext highlighter-rouge">0</code> to have the application use an available port. In our 
case we will use <code class="language-plaintext highlighter-rouge">57116</code>. If you deploy this service as a Docker container you will be able to map that to any port of your choosing. 
Let’s name the application in <code class="language-plaintext highlighter-rouge">bootstrap.yaml</code> and specify our port by adding the following to our <code class="language-plaintext highlighter-rouge">application.yaml</code>:</p>

<p>file: <a href="https://github.com/juliuskrah/intro-microservice/tree/master/distance/src/main/resources/application.yaml">
  <code class="highlighter-rouge">distance/src/main/resources/application.yaml</code>
</a></p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="na">server</span><span class="pi">:</span>
  <span class="na">port</span><span class="pi">:</span> <span class="m">57116</span>
<span class="na">spring</span><span class="pi">:</span>
  <span class="na">cloud</span><span class="pi">:</span>
    <span class="na">consul</span><span class="pi">:</span>
      <span class="na">discovery</span><span class="pi">:</span>
        <span class="na">register-health-check</span><span class="pi">:</span> <span class="no">false</span></code></pre></figure>

<p>file: <a href="https://github.com/juliuskrah/intro-microservice/tree/master/distance/src/main/resources/bootstrap.yaml">
  <code class="highlighter-rouge">distance/src/main/resources/bootstrap.yaml</code>
</a></p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="na">spring</span><span class="pi">:</span>
  <span class="na">application</span><span class="pi">:</span>
    <span class="na">name</span><span class="pi">:</span> <span class="s">distance</span></code></pre></figure>

<p>Now build the project, and run it:</p>

<figure class="highlight"><pre><code class="language-posh" data-lang="posh"><span class="n">PS</span><span class="w"> </span><span class="nx">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="o">.</span><span class="nx">\mvnw</span><span class="w"> </span><span class="nx">spring-boot:run</span></code></pre></figure>

<p>We should now see this service in Consul, so let’s head back over to our browser, load up 
<a href="http://localhost:8500/ui/dc1/services" target="_blank">http://localhost:8500/ui/dc1/services</a>
(or refresh if you’re already there).</p>

<p class="image-caption"><img src="https://i.imgur.com/ifuSYBi.png" alt="Distance Consul" /></p>
<p><em>Distance Service registered in Consul</em></p>

<p>As you can see from the above diagram, the <code class="language-plaintext highlighter-rouge">distance</code> service has been registered with consul.</p>

<p>We need to add the <code class="language-plaintext highlighter-rouge">JTS</code> library to the application classpath to aid us with the distance measurement:</p>

<p>file: <a href="https://github.com/juliuskrah/intro-microservice/tree/master/distance/pom.xml">
  <code class="highlighter-rouge">distance/pom.xml</code>
</a></p>

<figure class="highlight"><pre><code class="language-xml" data-lang="xml">...
<span class="nt">&lt;dependency&gt;</span>
  <span class="nt">&lt;groupId&gt;</span>org.locationtech.jts<span class="nt">&lt;/groupId&gt;</span>
  <span class="nt">&lt;artifactId&gt;</span>jts-core<span class="nt">&lt;/artifactId&gt;</span>
  <span class="nt">&lt;version&gt;</span>1.15.1<span class="nt">&lt;/version&gt;</span>
<span class="nt">&lt;/dependency&gt;</span>
...</code></pre></figure>

<p>The <code class="language-plaintext highlighter-rouge">distance microservice</code> will serve one request <code class="language-plaintext highlighter-rouge">/distance/start/@{start}/dest/@{dest}</code> which returns the distance computed.</p>

<p>file: <a href="https://github.com/juliuskrah/intro-microservice/tree/master/distance/src/main/java/com/juliuskrah/distance/DistanceApplication.java">
  <code class="highlighter-rouge">distance/src/main/java/com/juliuskrah/distance/DistanceApplication.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@RestController</span>
<span class="nd">@SpringBootApplication</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">DistanceApplication</span> <span class="o">{</span>
  <span class="kd">static</span> <span class="nc">GeometryFactory</span> <span class="n">fact</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">GeometryFactory</span><span class="o">();</span>
  <span class="kd">static</span> <span class="nc">WKTReader</span> <span class="n">wktRdr</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WKTReader</span><span class="o">(</span><span class="n">fact</span><span class="o">);</span>

  <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">SpringApplication</span><span class="o">.</span><span class="na">run</span><span class="o">(</span><span class="nc">DistanceApplication</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">args</span><span class="o">);</span>
  <span class="o">}</span>
	
  <span class="nd">@GetMapping</span><span class="o">(</span><span class="n">path</span> <span class="o">=</span> <span class="s">"/distance/start/@{start}/dest/@{dest}"</span><span class="o">,</span> <span class="n">produces</span> <span class="o">=</span> <span class="s">"application/json"</span><span class="o">)</span>
  <span class="kd">public</span> <span class="kt">double</span> <span class="nf">points</span><span class="o">(</span><span class="nd">@PathVariable</span> <span class="nc">String</span> <span class="n">start</span><span class="o">,</span> <span class="nd">@PathVariable</span> <span class="nc">String</span> <span class="n">dest</span><span class="o">)</span> <span class="o">{</span>
    <span class="kt">double</span> <span class="n">distance</span> <span class="o">=</span> <span class="mf">0.0</span><span class="o">;</span>
    <span class="nc">String</span><span class="o">[]</span> <span class="n">pointA</span> <span class="o">=</span> <span class="n">start</span><span class="o">.</span><span class="na">split</span><span class="o">(</span><span class="s">","</span><span class="o">);</span>
    <span class="nc">String</span><span class="o">[]</span> <span class="n">pointB</span> <span class="o">=</span> <span class="n">dest</span><span class="o">.</span><span class="na">split</span><span class="o">(</span><span class="s">","</span><span class="o">);</span>
    <span class="nc">String</span> <span class="n">wktA</span> <span class="o">=</span> <span class="s">"POINT ("</span> <span class="o">+</span> <span class="n">pointA</span><span class="o">[</span><span class="mi">0</span><span class="o">]</span> <span class="o">+</span> <span class="s">" "</span> <span class="o">+</span> <span class="n">pointA</span><span class="o">[</span><span class="mi">1</span><span class="o">]</span> <span class="o">+</span><span class="s">")"</span><span class="o">;</span>
    <span class="nc">String</span> <span class="n">wktB</span> <span class="o">=</span> <span class="s">"POINT ("</span> <span class="o">+</span> <span class="n">pointB</span><span class="o">[</span><span class="mi">0</span><span class="o">]</span> <span class="o">+</span> <span class="s">" "</span> <span class="o">+</span> <span class="n">pointB</span><span class="o">[</span><span class="mi">1</span><span class="o">]</span> <span class="o">+</span><span class="s">")"</span><span class="o">;</span>
		
    <span class="k">try</span> <span class="o">{</span>
      <span class="nc">Geometry</span> <span class="no">A</span> <span class="o">=</span> <span class="n">wktRdr</span><span class="o">.</span><span class="na">read</span><span class="o">(</span><span class="n">wktA</span><span class="o">);</span>
      <span class="nc">Geometry</span> <span class="no">B</span> <span class="o">=</span> <span class="n">wktRdr</span><span class="o">.</span><span class="na">read</span><span class="o">(</span><span class="n">wktB</span><span class="o">);</span>

      <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Geometry A: "</span> <span class="o">+</span> <span class="no">A</span><span class="o">);</span>
      <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Geometry B: "</span> <span class="o">+</span> <span class="no">B</span><span class="o">);</span>
      <span class="nc">DistanceOp</span> <span class="n">distOp</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DistanceOp</span><span class="o">(</span><span class="no">A</span><span class="o">,</span> <span class="no">B</span><span class="o">);</span>
      <span class="n">distance</span> <span class="o">=</span> <span class="n">distOp</span><span class="o">.</span><span class="na">distance</span><span class="o">();</span>
			
    <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">ParseException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
      <span class="c1">// ignore</span>
    <span class="o">}</span>	
    <span class="k">return</span> <span class="n">distance</span><span class="o">;</span>
  <span class="o">}</span>	
<span class="o">}</span></code></pre></figure>

<p>Restart the distance service and test the endpoint <code class="language-plaintext highlighter-rouge">http://localhost:57116/distance/start/@50.8307467,-1.2099742/dest/@5.5790564,-0.7073872</code>,
and you should see <code class="language-plaintext highlighter-rouge">45.25448120020473</code>.</p>

<p>Our first microservice is open for business!</p>

<h2 id="points-microservice">Points Microservice</h2>

<p>Head over to <a href="https://start.spring.io/" target="_blank">Spring Intitializr</a> to create the <code class="language-plaintext highlighter-rouge">points microservice</code>. 
Select <strong>Web</strong> and <strong>Consul Discovery</strong>, change “Artifact” to <em>points</em> then click <em>Generate Project</em> to download a zip file. 
Extract the contents of the zip file and load the project into your favorite IDE or text editor.</p>

<p>We will name the microservice <code class="language-plaintext highlighter-rouge">points</code> in <code class="language-plaintext highlighter-rouge">bootstrap.yaml</code>. We will use port <code class="language-plaintext highlighter-rouge">57216</code> for the points microservice:</p>

<p>file: <a href="https://github.com/juliuskrah/intro-microservice/tree/master/points/src/main/resources/application.yaml">
  <code class="highlighter-rouge">points/src/main/resources/application.yaml</code>
</a></p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="na">server</span><span class="pi">:</span>
  <span class="na">port</span><span class="pi">:</span> <span class="m">57216</span>
<span class="na">spring</span><span class="pi">:</span>
  <span class="na">cloud</span><span class="pi">:</span>
    <span class="na">consul</span><span class="pi">:</span>
      <span class="na">discovery</span><span class="pi">:</span>
        <span class="na">register-health-check</span><span class="pi">:</span> <span class="no">false</span></code></pre></figure>

<p>file: <a href="https://github.com/juliuskrah/intro-microservice/tree/master/points/src/main/resources/bootstrap.yaml">
  <code class="highlighter-rouge">points/src/main/resources/bootstrap.yaml</code>
</a></p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="na">spring</span><span class="pi">:</span>
  <span class="na">application</span><span class="pi">:</span>
    <span class="na">name</span><span class="pi">:</span> <span class="s">points</span></code></pre></figure>

<p>Give it a spin <code class="language-plaintext highlighter-rouge">.\mvnw spring-boot:run</code> to ensure everything is working.</p>

<p>If it’s all good we can implement the <code class="language-plaintext highlighter-rouge">points microservice</code>:</p>

<p>file: <a href="https://github.com/juliuskrah/intro-microservice/tree/master/points/src/main/java/com/juliuskrah/point/PointsApplication.java">
  <code class="highlighter-rouge">points/src/main/java/com/juliuskrah/point/PointsApplication.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@RestController</span>
<span class="nd">@SpringBootApplication</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">PointsApplication</span> <span class="o">{</span>
  <span class="nd">@Autowired</span>
  <span class="kd">private</span> <span class="nc">RestTemplate</span> <span class="n">restTemplate</span><span class="o">;</span>

  <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">SpringApplication</span><span class="o">.</span><span class="na">run</span><span class="o">(</span><span class="nc">PointsApplication</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">args</span><span class="o">);</span>
  <span class="o">}</span>

  <span class="nd">@GetMapping</span><span class="o">(</span><span class="n">path</span> <span class="o">=</span> <span class="s">"/points/start/@{start}/dest/@{dest}"</span><span class="o">,</span> <span class="n">produces</span> <span class="o">=</span> <span class="s">"application/json"</span><span class="o">)</span>
  <span class="kd">public</span> <span class="kt">double</span> <span class="nf">points</span><span class="o">(</span><span class="nd">@PathVariable</span> <span class="nc">String</span> <span class="n">start</span><span class="o">,</span> <span class="nd">@PathVariable</span> <span class="nc">String</span> <span class="n">dest</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">return</span> <span class="n">restTemplate</span><span class="o">.</span><span class="na">getForObject</span><span class="o">(</span><span class="s">"http://distance/distance/start/@{start}/dest/@{dest}"</span><span class="o">,</span>
      <span class="kt">double</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">start</span><span class="o">,</span> <span class="n">dest</span><span class="o">);</span>
  <span class="o">}</span>

  <span class="nd">@Bean</span>
  <span class="nd">@LoadBalanced</span>
  <span class="kd">public</span> <span class="nc">RestTemplate</span> <span class="nf">loadBalancedRestTemplate</span><span class="o">(</span><span class="nc">RestTemplateBuilder</span> <span class="n">builder</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">return</span> <span class="n">builder</span><span class="o">.</span><span class="na">build</span><span class="o">();</span>
  <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>A few things to note about the snippet above – <code class="language-plaintext highlighter-rouge">@LoadBalanced</code>, annotation to mark a <code class="language-plaintext highlighter-rouge">RestTemplate</code> bean to be configured to use 
a round-robin <code class="language-plaintext highlighter-rouge">LoadBalancerClient</code> for client-side load-balancing. This same annotation allows <code class="language-plaintext highlighter-rouge">RestTemplate</code> to determine the URI
of the downstream microservice by name. This is how the <code class="language-plaintext highlighter-rouge">http://DISTANCE/distance/start/@{start}/dest/@{dest}</code> seemingly works despite
missing a <code class="language-plaintext highlighter-rouge">host</code> and <code class="language-plaintext highlighter-rouge">port</code> in the URI passed to <code class="language-plaintext highlighter-rouge">RestTemplate#getForObject</code>.</p>

<p>This approach is efficient as we leave the job of discovery the services’ host and port to the discovery server (consul); we don’t
have to worry about knowing the IPs of all microservices. In a large project consisting of thousands of microservices, you will soon
come to agree that knowing all IPs of services starts to become a jarring task; this is where service discovery starts to shine.</p>

<p>Let’s put the <code class="language-plaintext highlighter-rouge">points microservice</code> to the test <code class="language-plaintext highlighter-rouge">http://localhost:57216/points/start/@5.8307467,-1.2099742/dest/@5.5790564,-0.7073872</code>.</p>

<p>This completes out points service using Spring-Boot.</p>

<h1 id="conclusion">Conclusion</h1>
<p>In this tutorial we learned the fundamentals of Microservices. We learned what is a Discovery client, we also built two microservices
to demonstrate how service discovery allows microservices to find each other.<br />
As usual you can find the full example to this guide <a href="https://github.com/juliuskrah/intro-microservice/tree/master" target="_blank">in the github repository</a>. Until the next post, keep doing cool things :+1:.</p>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;juliuskrah&quot;}</name></author><category term="blog" /><category term="java" /><category term="maven" /><category term="spring-boot" /><category term="microservices" /><summary type="html"><![CDATA[Microservices enable different teams to work on smaller pieces, using independent technologies, producing safer, more frequent deployments]]></summary></entry><entry><title type="html">CDI Interceptors</title><link href="http://juliuskrah.com/gist/2018/07/23/cdi-interceptors/" rel="alternate" type="text/html" title="CDI Interceptors" /><published>2018-07-23T23:24:55+00:00</published><updated>2018-07-23T23:24:55+00:00</updated><id>http://juliuskrah.com/gist/2018/07/23/cdi-interceptors</id><content type="html" xml:base="http://juliuskrah.com/gist/2018/07/23/cdi-interceptors/"><![CDATA[<p><a href="/tag/cdi">CDI</a> Interceptor functionality is defined in the Java Interceptors specification.</p>

<p>The Interceptors specification defines three kinds of interception points:</p>

<ul>
  <li>business method interception,</li>
  <li>lifecycle callback interception, and</li>
  <li>timeout method interception (EJB only).</li>
</ul>

<p>We will explore the basics of using interceptors in CDI. A simple interceptor will be created that 
initializes a cutomer’s account with 10 USD.</p>

<script src="https://gist.github.com/52709b25f5e9fa9a71d135ace1ad9875.js?file=AccountOpeningInterceptor.java"> </script>

<p>In the above snippet we create the <code class="language-plaintext highlighter-rouge">@InterceptorBinding</code> which can be applied to a <code class="language-plaintext highlighter-rouge">TYPE</code> or a <code class="language-plaintext highlighter-rouge">METHOD</code>.</p>

<script src="https://gist.github.com/52709b25f5e9fa9a71d135ace1ad9875.js?file=AccountCreditOpeningInterceptor.java"> </script>

<p>Next is to create the actual Interceptor class with a binding to the <code class="language-plaintext highlighter-rouge">AccountOpeningInterceptor</code>.</p>

<script src="https://gist.github.com/52709b25f5e9fa9a71d135ace1ad9875.js?file=CustomerService.java"> </script>

<p>Then we apply the Interceptor to the method call that requires interception.</p>

<p>On that note and until the next post; keep doing cool things :smile:.</p>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;juliuskrah&quot;}</name></author><category term="gist" /><category term="java" /><category term="cdi" /><category term="javaee" /><summary type="html"><![CDATA[CDI Interceptor functionality is defined in the Java Interceptors specification.]]></summary></entry><entry><title type="html">Exploring Apache DeltaSpike Data Module</title><link href="http://juliuskrah.com/blog/2018/05/25/exploring-apache-deltaspike-data-module/" rel="alternate" type="text/html" title="Exploring Apache DeltaSpike Data Module" /><published>2018-05-25T16:51:00+00:00</published><updated>2018-05-25T16:51:00+00:00</updated><id>http://juliuskrah.com/blog/2018/05/25/exploring-apache-deltaspike-data-module</id><content type="html" xml:base="http://juliuskrah.com/blog/2018/05/25/exploring-apache-deltaspike-data-module/"><![CDATA[<blockquote>
  <p><a href="https://deltaspike.apache.org/" target="_blank">Apache DeltaSpike</a> is a collection of portable 
  <a href="/blog/2018/05/18/a-beginner-s-guide-to-cdi/">CDI</a> extensions.</p>
</blockquote>

<h1 id="introduction">Introduction</h1>

<p>DeltaSpike Data Module provides capabilities for implementing repository patterns and thereby simplifying the 
repository layer not unlike <a href="/tag/spring-data">Spring Data</a>. In this post we will take a JPA project and 
rewrite the repository layer to use DeltaSpike Data. Basically, we will strip off the boilerplate 
<code class="language-plaintext highlighter-rouge">EntityManager</code> queries and enable centralization of query logic and consequently reducing code duplication 
and improve testability.</p>

<h1 id="prerequisites">Prerequisites</h1>

<ul>
  <li><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Java Development Kit</a></li>
  <li><a href="http://maven.apache.org" target="_blank">Maven</a></li>
</ul>

<h2 id="project-structure">Project Structure</h2>

<p>At the end of this guide our folder structure will look similar to the following:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.
|__src/
|  |__main/
|  |  |__java/
|  |  |  |__com/
|  |  |  |  |__juliuskrah/
|  |  |  |  |  |__cdi/
|  |  |  |  |  |  |__ApplicationResources.java
|  |  |  |  |  |  |__business/
|  |  |  |  |  |  |  |__CustomerService.java
|  |  |  |  |  |  |  |__dto/
|  |  |  |  |  |  |  |  |__CustomerBean.java
|  |  |  |  |  |  |  |__mapper/
|  |  |  |  |  |  |  |  |__CustomerMapper.java
|  |  |  |  |  |  |__entity/
|  |  |  |  |  |  |  |__Customer.java
|  |  |  |  |  |  |__repository/
|  |  |  |  |  |  |  |__CustomerRepository.java
|  |  |  |  |  |  |__web/
|  |  |  |  |  |  |  |__IndexController.java
|  |  |__resources/
|  |  |  |__db/
|  |  |  |  |__migration/
|  |  |  |  |  |__`V1__Create_customer_table.sql`
|  |  |  |__META-INF/
|  |  |  |  |__persistence.xml
|  |  |  |__modules/
|  |  |  |  |__com/
|  |  |  |  |  |__h2database/
|  |  |  |  |  |  |__h2/
|  |  |  |  |  |  |  |__main/
|  |  |  |  |  |  |  |  |__module.xml
|  |  |  |__project-defaults.yaml
|  |  |__webapp/
|  |  |  |__WEB-INF/
|  |  |  |  |__templates/
|  |  |  |  |  |__default.xhtml
|  |  |  |  |__beans.xml
|  |  |  |  |__web.xml
|  |  |  |__index.html
|  |  |  |__index.xhtml
|__pom.xml
</code></pre></div></div>

<h2 id="setting-up">Setting Up</h2>

<p>Download the initial project (<a href="https://github.com/juliuskrah/cdi/archive/v2.0.zip">zip</a>|
<a href="https://github.com/juliuskrah/cdi/archive/v2.0.tar.gz">tar.gz</a>) and extract. From the extracted directory
run the following command:</p>

<div class="language-posh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">C:\</span><span class="err">&gt;</span><span class="w"> </span><span class="nx">mvn</span><span class="w"> </span><span class="nx">clean</span><span class="w"> </span><span class="nx">wildfly-swarm:run</span><span class="w">
</span></code></pre></div></div>

<p>Wait for all the dependencies to download and <code class="language-plaintext highlighter-rouge">swarm</code> to start.</p>

<h1 id="deltaspike">DeltaSpike</h1>

<p>Add the DeltaSpike Data dependencies:</p>

<p>file: <a href="https://github.com/juliuskrah/cdi/tree/delta-spike/pom.xml">
  <code class="highlighter-rouge">pom.xml</code>
</a></p>

<figure class="highlight"><pre><code class="language-xml" data-lang="xml">...
<span class="nt">&lt;dependency&gt;</span>
  <span class="nt">&lt;groupId&gt;</span>org.apache.deltaspike.modules<span class="nt">&lt;/groupId&gt;</span>
  <span class="nt">&lt;artifactId&gt;</span>deltaspike-data-module-api<span class="nt">&lt;/artifactId&gt;</span>
  <span class="nt">&lt;version&gt;</span>1.8.1<span class="nt">&lt;/version&gt;</span>
  <span class="nt">&lt;scope&gt;</span>compile<span class="nt">&lt;/scope&gt;</span>
<span class="nt">&lt;/dependency&gt;</span>
<span class="nt">&lt;dependency&gt;</span>
  <span class="nt">&lt;groupId&gt;</span>org.apache.deltaspike.modules<span class="nt">&lt;/groupId&gt;</span>
  <span class="nt">&lt;artifactId&gt;</span>deltaspike-data-module-impl<span class="nt">&lt;/artifactId&gt;</span>
  <span class="nt">&lt;version&gt;</span>1.8.1<span class="nt">&lt;/version&gt;</span>
  <span class="nt">&lt;scope&gt;</span>runtime<span class="nt">&lt;/scope&gt;</span>
<span class="nt">&lt;/dependency&gt;</span>
...</code></pre></figure>

<p>Replace the code in <code class="language-plaintext highlighter-rouge">CustomerRepository</code>:</p>

<p>file: <a href="https://github.com/juliuskrah/cdi/tree/delta-spike/src/main/java/com/juliuskrah/cdi/repository/CustomerRepository.java">
  <code class="highlighter-rouge">src/main/java/com/juliuskrah/cdi/repository/CustomerRepository.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@Repository</span>
<span class="kd">public</span> <span class="kd">interface</span> <span class="nc">CustomerRepository</span> <span class="kd">extends</span> <span class="nc">EntityRepository</span><span class="o">&lt;</span><span class="nc">Customer</span><span class="o">,</span> <span class="no">UUID</span><span class="o">&gt;</span> <span class="o">{</span>

  <span class="nd">@Query</span><span class="o">(</span><span class="s">"SELECT c FROM Customer c WHERE c.id = :id"</span><span class="o">)</span>
  <span class="nc">Optional</span><span class="o">&lt;</span><span class="nc">Customer</span><span class="o">&gt;</span> <span class="nf">findOne</span><span class="o">(</span><span class="nd">@QueryParam</span><span class="o">(</span><span class="s">"id"</span><span class="o">)</span> <span class="no">UUID</span> <span class="n">id</span><span class="o">);</span>
<span class="o">}</span></code></pre></figure>

<p>There are a few things to note here. The <code class="language-plaintext highlighter-rouge">@Repository</code> annotation tells the extension that this is a 
repository for the <code class="language-plaintext highlighter-rouge">Customer</code> entity. Any method defined on the repository will be processed by the framework.</p>

<p>The <code class="language-plaintext highlighter-rouge">EntityRepository</code> Interface is mainly intended to hold complex query logic, working with both a 
repository and an <code class="language-plaintext highlighter-rouge">EntityManager</code> in the service layer might unnecessarily clutter code. 
The top base type is the <code class="language-plaintext highlighter-rouge">EntityRepository</code> interface, providing common methods used with an <code class="language-plaintext highlighter-rouge">EntityManager</code>.</p>

<p>DeltaSpike Data module supports also annotating methods for more control on the generated query using 
<code class="language-plaintext highlighter-rouge">@Query</code>. If the JPQL query requires named parameters to be used, this can be done by annotating the
arguments with the <code class="language-plaintext highlighter-rouge">@QueryParam</code> annotation.</p>

<p>For all these to work, DeltaSpike Data requires an <code class="language-plaintext highlighter-rouge">EntityManager</code> exposed via a CDI producer - which is 
common practice in Java EE applications:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Produces</span>
<span class="nd">@PersistenceContext</span>
<span class="nc">EntityManager</span> <span class="n">em</span><span class="o">;</span>
</code></pre></div></div>

<h2 id="transactions">Transactions</h2>

<p>DeltaSpike Data module uses a <code class="language-plaintext highlighter-rouge">ResourceLocalTransactionStrategy</code> as default <code class="language-plaintext highlighter-rouge">TransactionStrategy</code> when 
demarcating transactions. Our example is configured to use <code class="language-plaintext highlighter-rouge">jta-data-source</code>, and the 
<code class="language-plaintext highlighter-rouge">ResourceLocalTransactionStrategy</code> does not quite fit our needs here.</p>

<p>Let’s talk a little about JPA transactions to understand our decision not to use <code class="language-plaintext highlighter-rouge">ResourceLocalTransactionStrategy</code>.
A transaction is a set of operations that either fail or succeed as a unit. Transactions are a fundamental
part of persistence. A database transaction consists of a set of SQL DML (Data Manipulation Language) 
operations that are committed or rolled back as a single unit. An object level transaction is one in which a
set of changes made to a set of objects are committed to the database as a single unit.</p>

<p>JPA provides two mechanisms for transactions. When used in Java EE JPA provides integration with JTA (Java
Transaction API). JPA also provides its own <code class="language-plaintext highlighter-rouge">EntityTransaction</code> implementation for Java SE and for use in a
non-managed mode in Java EE. Transactions in JPA are always at the object level, this means that all changes 
made to all persistent objects in the persistence context are part of the transaction.</p>

<p>Resource local transactions are used in Java SE, or in application managed (non-managed) mode in Java EE. To 
use resource local transactions the transaction-type attribute in the <code class="language-plaintext highlighter-rouge">persistence.xml</code> is set to 
<code class="language-plaintext highlighter-rouge">RESOURCE_LOCAL</code>. Local JPA transactions are defined through the <code class="language-plaintext highlighter-rouge">EntityTransaction</code> class. It contains basic 
transaction API including <code class="language-plaintext highlighter-rouge">begin</code>, <code class="language-plaintext highlighter-rouge">commit</code> and <code class="language-plaintext highlighter-rouge">rollback</code>.</p>

<p>JTA transactions are used in Java EE, in managed mode (CMT). To use JTA transactions the transaction-type 
attribute in the <code class="language-plaintext highlighter-rouge">persistence.xml</code> is set to <code class="language-plaintext highlighter-rouge">JTA</code>. JTA transactions are defined through the JTA 
<code class="language-plaintext highlighter-rouge">UserTransaction</code> class.</p>

<p>JTA transactions can be used in two modes in Java EE. In Java EE managed mode such as an <code class="language-plaintext highlighter-rouge">EntityManager</code> 
injected through <code class="language-plaintext highlighter-rouge">@PersistenceContext</code>, this mode is also known as Container Managed Transaction (CMT).</p>

<p>The second mode allows the <code class="language-plaintext highlighter-rouge">EntityManager</code> to be application managed, (normally obtained from an injected 
EntityManagerFactory, or directly from JPA Persistence) also known as Bean Managed Transaction (BMT). This 
allows the persistence context to survive transaction boundaries, and follow the normal <code class="language-plaintext highlighter-rouge">EntityManager</code>
life-cycle similar to resource local.</p>

<p>DeltaSpike has three implementations of <code class="language-plaintext highlighter-rouge">TransactionStrategy</code>:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">ResourceLocalTransactionStrategy</code> which uses <code class="language-plaintext highlighter-rouge">EntityTransaction</code></li>
  <li><code class="language-plaintext highlighter-rouge">BeanManagedUserTransactionStrategy</code> which uses <code class="language-plaintext highlighter-rouge">UserTransaction</code></li>
  <li><code class="language-plaintext highlighter-rouge">ContainerManagedTransactionStrategy</code></li>
</ul>

<p>We have to tell DeltaSpike to use <code class="language-plaintext highlighter-rouge">ContainerManagedTransactionStrategy</code>:</p>

<p>file: <a href="https://github.com/juliuskrah/cdi/tree/delta-spike/src/main/resources/META-INF/apache-deltaspike.properties">
  <code class="highlighter-rouge">src/main/resources/META-INF/apache-deltaspike.properties</code>
</a></p>

<figure class="highlight"><pre><code class="language-properties" data-lang="properties"><span class="py">globalAlternatives.org.apache.deltaspike.jpa.spi.transaction.TransactionStrategy</span> <span class="p">=</span> <span class="s">org.apache.deltaspike.jpa.impl.transaction.ContainerManagedTransactionStrategy</span></code></pre></figure>

<h1 id="conclusion">Conclusion</h1>

<p>We have been introduced to DeltaSpike Data Module, and we saw how easy it is to use for contructing queries.
We also did a quick introduction to Transactions in JPA.</p>

<p>As usual you can find the full example to this guide <a href="https://github.com/juliuskrah/cdi/tree/delta-spike" target="_blank">in the github repository</a>. Until the next post, keep 
doing cool things :+1:.</p>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;juliuskrah&quot;}</name></author><category term="blog" /><category term="java" /><category term="maven" /><category term="javaee" /><category term="cdi" /><category term="jpa" /><summary type="html"><![CDATA[Apache DeltaSpike is a collection of portable CDI extensions.]]></summary></entry><entry><title type="html">A Beginner’s Guide to CDI</title><link href="http://juliuskrah.com/blog/2018/05/18/a-beginner-s-guide-to-cdi/" rel="alternate" type="text/html" title="A Beginner’s Guide to CDI" /><published>2018-05-18T00:27:12+00:00</published><updated>2018-05-18T00:27:12+00:00</updated><id>http://juliuskrah.com/blog/2018/05/18/a-beginner-s-guide-to-cdi</id><content type="html" xml:base="http://juliuskrah.com/blog/2018/05/18/a-beginner-s-guide-to-cdi/"><![CDATA[<blockquote>
  <p><a href="http://cdi-spec.org/" target="_blank">Contexts and Dependency Injection for the Java EE Platform</a> is a 
  <a href="https://jcp.org/en/home/index" target="_blank">JCP</a> standard for dependency injection and contextual lifecycle management and one of 
  the most important and popular parts of <a href="/tag/javaee/">Java EE</a>.</p>
</blockquote>

<h1 id="introduction">Introduction</h1>

<p>Contexts and Dependency Injection for Java EE (CDI) was introduced as part of the Java EE platform, and 
has quickly become one of the most important and popular components of the platform.</p>

<p>The CDI specification defines a set of complementary services that help improve the structure of application 
code. CDI layers an enhanced lifecycle and interaction model over existing Java component types, including 
managed beans and <code class="language-plaintext highlighter-rouge">Enterprise Java Beans</code>.</p>

<p>You can run CDI in a Java EE or SE environment. However to leverage the full capabilities of CDI, it is 
recommended to use a Java EE container. In this tutorial, we will cover just the EE approach and we will be
using <code class="language-plaintext highlighter-rouge">Wildfly-Swarm</code>, a lighweight alternative to the Wildfly Java EE container which is also a very good
fit for deploying microservices.</p>

<h2 id="what-we-will-cover">What We will Cover</h2>

<p>CDI is quite broad; as it provides integration and contracts with the wider Java EE ecosystem. This being an 
introductory post, we limit the scope of what is covered to:</p>

<ul>
  <li>Bean Scope</li>
  <li>Producer</li>
  <li>Inject</li>
  <li>Event</li>
</ul>

<h1 id="prerequisites">Prerequisites</h1>

<ul>
  <li><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Java Development Kit</a></li>
  <li><a href="http://maven.apache.org" target="_blank">Maven</a></li>
  <li><a href="https://www.eclipse.org/downloads/" target="_blank">Eclipse</a> 4.6.0+</li>
</ul>

<h2 id="project-structure">Project Structure</h2>

<p>At the end of this guide our folder structure will look similar to the following:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.
|__src/
|  |__main/
|  |  |__java/
|  |  |  |__com/
|  |  |  |  |__juliuskrah/
|  |  |  |  |  |__cdi/
|  |  |  |  |  |  |__ApplicationContext.java
|  |  |  |  |  |  |__ApplicationResources.java
|  |  |  |  |  |  |__business/
|  |  |  |  |  |  |  |__CustomerService.java
|  |  |  |  |  |  |  |__dto/
|  |  |  |  |  |  |  |  |__CustomerBean.java
|  |  |  |  |  |  |  |__mapper/
|  |  |  |  |  |  |  |  |__CustomerMapper.java
|  |  |  |  |  |  |__entity/
|  |  |  |  |  |  |  |__Customer.java
|  |  |  |  |  |  |__repository/
|  |  |  |  |  |  |  |__CustomerRepository.java
|  |  |  |  |  |  |__web/
|  |  |  |  |  |  |  |__IndexController.java
|  |  |__resources/
|  |  |  |__db/
|  |  |  |  |__migration/
|  |  |  |  |  |__`V1__Create_customer_table.sql`
|  |  |  |__META-INF/
|  |  |  |  |__persistence.xml
|  |  |  |__modules/
|  |  |  |  |__com/
|  |  |  |  |  |__h2database/
|  |  |  |  |  |  |__h2/
|  |  |  |  |  |  |  |__main/
|  |  |  |  |  |  |  |  |__module.xml
|  |  |  |__project-defaults.yaml
|  |  |__webapp/
|  |  |  |__WEB-INF/
|  |  |  |  |__views/
|  |  |  |  |  |__index.xhtml
|  |  |  |  |  |__templates/
|  |  |  |  |  |  |__default.xhtml
|__pom.xml
</code></pre></div></div>

<h2 id="setting-up">Setting Up</h2>

<p>Download the initial project (<a href="https://github.com/juliuskrah/cdi/archive/v1.0.zip">zip</a>|
<a href="https://github.com/juliuskrah/cdi/archive/v1.0.tar.gz">tar.gz</a>) and extract.
Import the extracted project into Eclipse and follow the <a href="http://mapstruct.org/documentation/ide-support/" target="_blank">Mapstruct instructions</a>
to generate mappers in Eclipse.</p>

<p>Run the application as a Java application; use <code class="language-plaintext highlighter-rouge">org.wildfly.swarm.Swarm</code> as the main class. ince it is 
up, access the application in your browser <a href="http://localhost:8080">http://localhost:8080</a>. Let’s start by understanding what a bean
scope is.</p>

<h2 id="bean-scopes">Bean Scopes</h2>

<p>A bean is exactly what you think it is. Only now, it has a true identity in the container environment.</p>

<p>Managed Beans are defined as container-managed objects with minimal programming restrictions, otherwise known 
by the acronym POJO (Plain Old Java Object). They support a small set of basic services, such as resource 
injection, lifecycle callbacks and interceptors. Companion specifications, such as EJB and CDI, build on this 
basic model.</p>

<p>A bean is usually an application class that contains business logic. It may be called directly from Java code,
or it may be invoked via the Unified EL. A bean may access transactional resources. Dependencies between 
beans are managed automatically by the container. Most beans are stateful and contextual. The lifecycle of a 
bean is managed by the container.</p>

<p>The scope of a bean determines:</p>

<ul>
  <li>the lifecycle of each instance of the bean and</li>
  <li>which clients share a reference to a particular instance of the bean.</li>
</ul>

<p>For a given thread in a CDI application, there may be an active context associated with the scope of the 
bean. This context may be unique to the thread (for example, if the bean is request scoped), or it may be 
shared with certain other threads (for example, if the bean is session scoped) or even all other threads (if 
it is application scoped).</p>

<p>The scope of a bean defines the lifecycle and visibility of its instances. The CDI context model is 
extensible, accommodating arbitrary scopes. However, certain important scopes are built into the 
specification, and provided by the container. Each scope is represented by an annotation type.</p>

<p>According to the CDI specification, a scope determines:</p>

<ul>
  <li>When a new instance of any bean with that scope is created</li>
  <li>When an existing instance of any bean with that scope is destroyed</li>
  <li>Which injected references refer to any instance of a bean with that scope</li>
</ul>

<p>For example, if we have a session-scoped bean, <code class="language-plaintext highlighter-rouge">CustomerRepository</code> , all beans that are called in the 
context of the same <code class="language-plaintext highlighter-rouge">HttpSession</code> will see the same instance of <code class="language-plaintext highlighter-rouge">CustomerRepository</code>. This instance will be 
automatically created the first time a <code class="language-plaintext highlighter-rouge">CustomerRepository</code> is needed in that session, and automatically
destroyed when the session ends.</p>

<h3 id="built-in-scopes">Built-in Scopes</h3>

<p>CDI defines four built-in scopes:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">@RequestScoped</code>: A bean instance is created for each request.</li>
  <li><code class="language-plaintext highlighter-rouge">@SessionScoped</code>: Creates a bean bound to the HTTP Session.</li>
  <li><code class="language-plaintext highlighter-rouge">@ApplicationScoped</code>: A single bean instance is shared by the application.</li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">@ConversationScoped</code>: The conversation scope is a bit like the traditional session scope in that it holds
 state associated with a user of the system, and spans multiple requests to the server.</p>

    <p>A conversation represents a task—a unit of work from the point of view of the user. The conversation 
 context holds state associated with what the user is currently working on. If the user is doing multiple 
 things at the same time, there are multiple conversations.</p>

    <p>The conversation context is active during any servlet request (since CDI 1.1). Most conversations are 
 destroyed at the end of the request. If a conversation should hold state across multiple requests, it must 
 be explicitly promoted to a long-running conversation.</p>
  </li>
</ul>

<p>Let’s start by creating some Application-Scoped beans:</p>

<p>file: <a href="https://github.com/juliuskrah/cdi/tree/2018.5.0/src/main/java/com/juliuskrah/cdi/repository/CustomerRepository.java">
  <code class="highlighter-rouge">src/main/java/com/juliuskrah/cdi/repository/CustomerRepository.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@ApplicationScoped</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">CustomerRepository</span> <span class="o">{</span>
  <span class="c1">// ...</span>
<span class="o">}</span></code></pre></figure>

<p>file: <a href="https://github.com/juliuskrah/cdi/tree/2018.5.0/src/main/java/com/juliuskrah/cdi/business/CustomerService.java">
  <code class="highlighter-rouge">src/main/java/com/juliuskrah/cdi/business/CustomerService.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@ApplicationScoped</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">CustomerService</span> <span class="o">{</span>
  <span class="c1">// ...</span>
<span class="o">}</span></code></pre></figure>

<p>We can <code class="language-plaintext highlighter-rouge">Inject</code> these beans into other beans. We will cover this later in this post.</p>

<h2 id="producers">Producers</h2>

<p>CDI distinguishes between  two types of producers:</p>

<ul>
  <li>Producer methods let us overcome certain limitations that arise when a container, instead of the 
application, is responsible for instantiating objects. They’re also the easiest way to integrate objects 
which are not beans into the CDI environment.</li>
  <li>A producer field is a simpler alternative to a producer method. A producer field is declared by annotating 
a field of a bean class with the <code class="language-plaintext highlighter-rouge">@Produces</code> annotation — the same annotation used for producer methods.
A producer field is really just a shortcut that lets us avoid writing a useless getter method.</li>
</ul>

<p>Let’s demonstrate that with an example:</p>

<p>file: <a href="https://github.com/juliuskrah/cdi/tree/2018.5.0/src/main/java/com/juliuskrah/cdi/ApplicationResources.java">
  <code class="highlighter-rouge">src/main/java/com/juliuskrah/cdi/ApplicationResources.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@RequestScoped</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">ApplicationResources</span> <span class="o">{</span>

  <span class="nd">@Produces</span>
  <span class="nd">@PersistenceContext</span>
  <span class="nc">EntityManager</span> <span class="n">em</span><span class="o">;</span>

  <span class="nd">@Produces</span>
  <span class="kd">public</span> <span class="nc">Logger</span> <span class="nf">produceLog</span><span class="o">(</span><span class="nc">InjectionPoint</span> <span class="n">injectionPoint</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">return</span> <span class="nc">Logger</span><span class="o">.</span><span class="na">getLogger</span><span class="o">(</span><span class="n">injectionPoint</span><span class="o">.</span><span class="na">getMember</span><span class="o">().</span><span class="na">getDeclaringClass</span><span class="o">());</span>
  <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>We created a producer field <code class="language-plaintext highlighter-rouge">EntityManager</code>, which will enable us <code class="language-plaintext highlighter-rouge">inject</code> an EntityManager into CDI beans.
We also created a producer method <code class="language-plaintext highlighter-rouge">Logger</code> to easily inject a logger into bean classes.</p>

<h2 id="inject">Inject</h2>

<p>The <code class="language-plaintext highlighter-rouge">@Inject</code> annotation lets us define an injection point that is injected during bean instantiation. 
Injection can occur via three different mechanisms.</p>

<ul>
  <li><em>Bean constructor</em> parameter injection: A bean can only have one injectable constructor.</li>
  <li><em>Initializer method</em> parameter injection: A bean can have multiple initializer methods.</li>
  <li>And direct field injection: Getter and setter methods are not required for field injection to work.</li>
</ul>

<p>Dependency injection always occurs when the bean instance is first instantiated by the container. Simplifying
just a little, things happen in this order:</p>

<ul>
  <li>First, the container calls the bean constructor (the default constructor or the one annotated <code class="language-plaintext highlighter-rouge">@Inject</code>), 
to obtain an instance of the bean.</li>
  <li>Next, the container initializes the values of all injected fields of the bean.</li>
  <li>Next, the container calls all initializer methods of bean (the call order is not portable, don’t rely on it).</li>
  <li>Finally, the <code class="language-plaintext highlighter-rouge">@PostConstruct</code> method, if any, is called.</li>
</ul>

<p>file: <a href="https://github.com/juliuskrah/cdi/tree/2018.5.0/src/main/java/com/juliuskrah/cdi/repository/CustomerRepository.java">
  <code class="highlighter-rouge">src/main/java/com/juliuskrah/cdi/repository/CustomerRepository.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@ApplicationScoped</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">CustomerRepository</span> <span class="o">{</span>
  <span class="kd">private</span> <span class="nc">EntityManager</span> <span class="n">em</span><span class="o">;</span>

  <span class="kd">public</span> <span class="nf">CustomerRepository</span><span class="o">()</span> <span class="o">{}</span>

  <span class="nd">@Inject</span>
  <span class="kd">public</span> <span class="nf">CustomerRepository</span><span class="o">(</span><span class="nc">EntityManager</span> <span class="n">em</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">this</span><span class="o">.</span><span class="na">em</span> <span class="o">=</span> <span class="n">em</span><span class="o">;</span>
  <span class="o">}</span>

  <span class="c1">// ...</span>
<span class="o">}</span></code></pre></figure>

<p>file: <a href="https://github.com/juliuskrah/cdi/tree/2018.5.0/src/main/java/com/juliuskrah/cdi/web/IndexController.java">
  <code class="highlighter-rouge">src/main/java/com/juliuskrah/cdi/web/IndexController.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@Path</span><span class="o">(</span><span class="s">"/"</span><span class="o">)</span>
<span class="nd">@Controller</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">IndexController</span> <span class="o">{</span>
  <span class="nd">@Inject</span>
  <span class="kd">private</span> <span class="nc">CustomerService</span> <span class="n">customerService</span><span class="o">;</span>
  <span class="nd">@Inject</span>
  <span class="kd">private</span> <span class="nc">Logger</span> <span class="n">log</span><span class="o">;</span>

  <span class="c1">// ...</span>
<span class="o">}</span></code></pre></figure>

<h2 id="events">Events</h2>

<p>Dependency injection enables loose-coupling by allowing the implementation of the injected bean type to vary,
either at deployment time or runtime. Events go one step further, allowing beans to interact with no compile 
time dependency at all. Event producers raise events that are delivered to event observers by the container.</p>

<p>This basic schema might sound like the familiar observer/observable pattern, but there are a couple of twists:</p>

<ul>
  <li>not only are event producers decoupled from observers; observers are completely decoupled from producers,</li>
  <li>observers can specify a combination of “selectors” to narrow the set of event notifications they will 
receive, and</li>
  <li>observers can be notified immediately, or can specify that delivery of the event should be delayed until 
the end of the current transaction.</li>
</ul>

<p>CDI events are made up of:</p>

<ul>
  <li>Event Payload: The event object carries state from producer to consumer. The event object is nothing more 
than an instance of a concrete Java class. (The only restriction is that an event type may not contain type 
variables).</li>
  <li>Event Observers: An observer method is a method of a bean with a parameter annotated <code class="language-plaintext highlighter-rouge">@Observes</code> or 
<code class="language-plaintext highlighter-rouge">@ObservesAsync</code>. The annotated parameter is called the <em>event parameter</em>. The type of the event parameter
is the observed <em>event type</em>.</li>
  <li>Event Producers: Event producers fire events either synchronously or asynchronously using an instance of 
the parameterized <code class="language-plaintext highlighter-rouge">Event</code> interface. An instance of this interface is obtained by injection.</li>
</ul>

<p>file: <a href="https://github.com/juliuskrah/cdi/tree/2018.5.0/src/main/java/com/juliuskrah/cdi/business/CustomerService.java">
  <code class="highlighter-rouge">src/main/java/com/juliuskrah/cdi/business/CustomerService.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@ApplicationScoped</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">CustomerService</span> <span class="o">{</span>
  <span class="nd">@Inject</span> <span class="c1">// Inject event</span>
  <span class="kd">private</span> <span class="nc">Event</span><span class="o">&lt;</span><span class="nc">CustomerBean</span><span class="o">&gt;</span> <span class="n">customerEventSrc</span><span class="o">;</span>

  <span class="kd">public</span> <span class="nc">CustomerBean</span> <span class="nf">createCustomer</span><span class="o">(</span><span class="nc">CustomerBean</span> <span class="n">customer</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">Customer</span> <span class="n">c</span> <span class="o">=</span> <span class="c1">// ...</span>
    <span class="c1">// Produce customer event</span>
    <span class="n">customerEventSrc</span><span class="o">.</span><span class="na">fire</span><span class="o">(</span><span class="n">customer</span><span class="o">);</span>
    <span class="k">return</span> <span class="n">customer</span><span class="o">;</span>
  <span class="o">}</span>

  <span class="cm">/**
   * The producer and observer do not necessarily have to be in the same class
   */</span>
  <span class="kd">public</span> <span class="kt">void</span> <span class="nf">onCustomerListChanged</span><span class="o">(</span>
    <span class="c1">// Observe customer event </span>
    <span class="nd">@Observes</span><span class="o">(</span><span class="n">notifyObserver</span> <span class="o">=</span> <span class="nc">Reception</span><span class="o">.</span><span class="na">IF_EXISTS</span><span class="o">,</span> 
    <span class="n">during</span> <span class="o">=</span> <span class="nc">TransactionPhase</span><span class="o">.</span><span class="na">AFTER_COMPLETION</span><span class="o">)</span> 
    <span class="kd">final</span> <span class="nc">CustomerBean</span> <span class="n">customer</span><span class="o">)</span> <span class="o">{</span>
    <span class="c1">// Add your logic here</span>
  <span class="o">}</span>
  <span class="c1">// ...</span>
<span class="o">}</span></code></pre></figure>

<h1 id="conclusion">Conclusion</h1>

<p>This is an introductory post to CDI. We covered the basics of CDI with <code class="language-plaintext highlighter-rouge">@Inject</code>, <code class="language-plaintext highlighter-rouge">@Produces</code> and bean scopes.
As usual you can find the full example to this guide <a href="https://github.com/juliuskrah/cdi/tree/2018.5.0" target="_blank">in the github repository</a>. Until the next post, keep 
doing cool things :+1:.</p>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;juliuskrah&quot;}</name></author><category term="blog" /><category term="java" /><category term="maven" /><category term="javaee" /><category term="cdi" /><category term="rest" /><category term="jax-rs" /><category term="jpa" /><summary type="html"><![CDATA[Contexts and Dependency Injection for the Java EE Platform is a JCP standard for dependency injection and contextual lifecycle management and one of the most important and popular parts of Java EE.]]></summary></entry><entry><title type="html">Sping PDF REST API with JasperReports</title><link href="http://juliuskrah.com/blog/2018/04/30/sping-pdf-rest-api-with-jasperreports/" rel="alternate" type="text/html" title="Sping PDF REST API with JasperReports" /><published>2018-04-30T18:33:45+00:00</published><updated>2018-04-30T18:33:45+00:00</updated><id>http://juliuskrah.com/blog/2018/04/30/sping-pdf-rest-api-with-jasperreports</id><content type="html" xml:base="http://juliuskrah.com/blog/2018/04/30/sping-pdf-rest-api-with-jasperreports/"><![CDATA[<blockquote>
  <p><a href="/tag/jasperreports/">JasperReports</a> is a Java class library, and it is meant for those Java developers
  who need to add reporting capabilities to their applications.</p>
</blockquote>

<h1 id="introduction">Introduction</h1>

<p>In this post, we will create a PDF report that is exposed over a RESTful endpoint using Spring Boot. This is also
a good place to start for those of you trying to figure out how to integrate JasperReports with Spring Framework 5. To serve excel over REST, <a href="/blog/2020/03/27/sping-excel-rest-api-with-jasperreports/">refer to this Excel Post</a>.</p>

<h2 id="prerequisites">Prerequisites</h2>

<ul>
  <li><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Java Development Kit</a></li>
  <li><a href="http://maven.apache.org" target="_blank">Maven</a></li>
</ul>

<h2 id="project-structure">Project Structure</h2>

<p>At the end of this guide our folder structure will look similar to the following:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.
|__src/
|  |__main/
|  |  |__java/
|  |  |  |__com/
|  |  |  |  |__juliuskrah/
|  |  |  |  |  |__jasper/
|  |  |  |  |  |  |__Application.java
|  |  |  |  |  |  |__ApplicationProperties.java
|  |  |  |  |  |  |__report/
|  |  |  |  |  |  |  |__JasperReportsService.java
|  |  |  |  |  |  |  |__ReportService.java
|  |  |  |  |  |  |__storage/
|  |  |  |  |  |  |  |__FileSystemStorageService.java
|  |  |  |  |  |  |  |__StorageException.java
|  |  |  |  |  |  |  |__StorageFileNotFoundException.java
|  |  |  |  |  |  |  |__StorageService.java
|  |  |  |  |  |  |__web/
|  |  |  |  |  |  |  |__rest/
|  |  |  |  |  |  |  |  |__ApplicationResource.java
|  |  |__resources/
|  |  |  |__reports/
|  |  |  |  |__pdf_rest_resource.jrxml
|  |  |  |  |__pdf_rest.jrxml
|  |  |  |__application.yaml
|  |  |  |__cherry.png
|  |  |  |__logo.png
|__pom.xml
</code></pre></div></div>

<h2 id="how-to-complete-this-guide">How to complete this guide</h2>

<p>To complete this guide, download (<a href="https://github.com/juliuskrah/jasper-html-mail/archive/v2.0.zip">zip</a>|
<a href="https://github.com/juliuskrah/jasper-html-mail/archive/v2.0.tar.gz">tar.gz</a>) 
and unzip the source repository for this guide.</p>

<h2 id="create-pdf-report">Create PDF Report</h2>

<p>Let us start by implementing a solution to generate PDFs in JasperReports:</p>

<p>file: <a href="https://github.com/juliuskrah/jasper-html-mail/tree/jasper-rest/src/main/java/com/juliuskrah/jasper/report/JasperReportsService.java">
  <code class="highlighter-rouge">src/main/java/com/juliuskrah/jasper/report/JasperReportsService.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@Component</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">JasperReportsService</span> <span class="kd">implements</span> <span class="nc">ReportService</span> <span class="o">{</span>
  <span class="c1">// ...</span>
  <span class="nd">@Override</span>
  <span class="kd">public</span> <span class="kt">byte</span><span class="o">[]</span> <span class="nf">generatePDFReport</span><span class="o">(</span><span class="nc">String</span> <span class="n">inputFileName</span><span class="o">,</span> <span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Object</span><span class="o">&gt;</span> <span class="n">params</span><span class="o">,</span>
    <span class="nc">JRDataSource</span> <span class="n">dataSource</span><span class="o">)</span> <span class="o">{</span>
    <span class="kt">byte</span><span class="o">[]</span> <span class="n">bytes</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
    <span class="nc">JasperReport</span> <span class="n">jasperReport</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
    <span class="k">try</span> <span class="o">(</span><span class="nc">ByteArrayOutputStream</span> <span class="n">byteArray</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ByteArrayOutputStream</span><span class="o">())</span> <span class="o">{</span>
      <span class="c1">// Check if a compiled report exists</span>
      <span class="k">if</span> <span class="o">(</span><span class="n">storageService</span><span class="o">.</span><span class="na">jasperFileExists</span><span class="o">(</span><span class="n">inputFileName</span><span class="o">))</span> <span class="o">{</span>
        <span class="n">jasperReport</span> <span class="o">=</span> <span class="o">(</span><span class="nc">JasperReport</span><span class="o">)</span> <span class="nc">JRLoader</span><span class="o">.</span><span class="na">loadObject</span><span class="o">(</span><span class="n">storageService</span><span class="o">.</span><span class="na">loadJasperFile</span><span class="o">(</span><span class="n">inputFileName</span><span class="o">));</span>
      <span class="o">}</span>
      <span class="c1">// Compile report from source and save</span>
      <span class="k">else</span> <span class="o">{</span>
        <span class="nc">String</span> <span class="n">jrxml</span> <span class="o">=</span> <span class="n">storageService</span><span class="o">.</span><span class="na">loadJrxmlFile</span><span class="o">(</span><span class="n">inputFileName</span><span class="o">);</span>
        <span class="n">jasperReport</span> <span class="o">=</span> <span class="nc">JasperCompileManager</span><span class="o">.</span><span class="na">compileReport</span><span class="o">(</span><span class="n">jrxml</span><span class="o">);</span>
        <span class="c1">// Save compiled report. Compiled report is loaded next time</span>
        <span class="nc">JRSaver</span><span class="o">.</span><span class="na">saveObject</span><span class="o">(</span><span class="n">jasperReport</span><span class="o">,</span> <span class="n">storageService</span><span class="o">.</span><span class="na">loadJasperFile</span><span class="o">(</span><span class="n">inputFileName</span><span class="o">));</span>
      <span class="o">}</span>
      <span class="nc">JasperPrint</span> <span class="n">jasperPrint</span> <span class="o">=</span> <span class="nc">JasperFillManager</span><span class="o">.</span><span class="na">fillReport</span><span class="o">(</span><span class="n">jasperReport</span><span class="o">,</span> <span class="n">params</span><span class="o">,</span> <span class="n">dataSource</span><span class="o">);</span>
      <span class="c1">// return the PDF in bytes</span>
      <span class="n">bytes</span> <span class="o">=</span> <span class="nc">JasperExportManager</span><span class="o">.</span><span class="na">exportReportToPdf</span><span class="o">(</span><span class="n">jasperPrint</span><span class="o">);</span>
    <span class="o">}</span>
    <span class="k">catch</span> <span class="o">(</span><span class="nc">JRException</span> <span class="o">|</span> <span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
      <span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
    <span class="o">}</span>
    <span class="k">return</span> <span class="n">bytes</span><span class="o">;</span>
  <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<h2 id="render-the-pdf-rest-endpoint">Render the PDF REST Endpoint</h2>

<p>We will create the REST endpoint:</p>

<p>file: <a href="https://github.com/juliuskrah/jasper-html-mail/tree/jasper-rest/src/main/java/com/juliuskrah/jasper/web/rest/ApplicationResource.java">
  <code class="highlighter-rouge">src/main/java/com/juliuskrah/jasper/web/rest/ApplicationResource.java</code>
</a></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@RestController</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">ApplicationResource</span> <span class="o">{</span>
  <span class="c1">// ...</span>
  <span class="nd">@GetMapping</span><span class="o">(</span><span class="s">"/{username}"</span><span class="o">)</span>
  <span class="kd">public</span> <span class="nc">ResponseEntity</span><span class="o">&lt;</span><span class="kt">byte</span><span class="o">[]&gt;</span> <span class="nf">report</span><span class="o">(</span><span class="nd">@PathVariable</span><span class="o">(</span><span class="n">required</span> <span class="o">=</span> <span class="kc">false</span><span class="o">)</span> <span class="nc">String</span> <span class="n">username</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Object</span><span class="o">&gt;</span> <span class="n">params</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HashMap</span><span class="o">&lt;&gt;();</span>
    <span class="n">params</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"username"</span><span class="o">,</span> <span class="n">username</span><span class="o">);</span>
    <span class="kt">byte</span><span class="o">[]</span> <span class="n">bytes</span> <span class="o">=</span> <span class="n">reportService</span><span class="o">.</span><span class="na">generatePDFReport</span><span class="o">(</span><span class="s">"pdf_rest_resource"</span><span class="o">,</span> <span class="n">params</span><span class="o">);</span>
    <span class="k">return</span> <span class="nc">ResponseEntity</span>
      <span class="o">.</span><span class="na">ok</span><span class="o">()</span>
      <span class="c1">// Specify content type as PDF</span>
      <span class="o">.</span><span class="na">header</span><span class="o">(</span><span class="s">"Content-Type"</span><span class="o">,</span> <span class="s">"application/pdf; charset=UTF-8"</span><span class="o">)</span>
      <span class="c1">// Tell browser to display PDF if it can</span>
      <span class="o">.</span><span class="na">header</span><span class="o">(</span><span class="s">"Content-Disposition"</span><span class="o">,</span> <span class="s">"inline; filename=\""</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s">".pdf\""</span><span class="o">)</span>
      <span class="o">.</span><span class="na">body</span><span class="o">(</span><span class="n">bytes</span><span class="o">);</span>
  <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>Now navigate to <a href="http://localhost:8080/:username">http://localhost:8080/:username</a> to view your report.</p>

<h1 id="conclusion">Conclusion</h1>

<p>In this post we learned how to generate PDF with JasperReports and serve it over HTTP with Spring Boot.    <br />
As usual you can find the full example to this guide <a href="https://github.com/juliuskrah/jasper-html-mail/tree/jasper-rest" target="_blank">in the github repository</a>. Until the next post, keep doing cool 
things :+1:.</p>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;juliuskrah&quot;}</name></author><category term="blog" /><category term="java" /><category term="maven" /><category term="jasperreports" /><category term="rest" /><category term="spring-boot" /><summary type="html"><![CDATA[JasperReports is a Java class library, and it is meant for those Java developers who need to add reporting capabilities to their applications.]]></summary></entry></feed>