<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title></title>
    <subtitle></subtitle>
    <link href="https://iamninad.comfeed.xml" rel="self"/>
    <link href="https://iamninad.com/"/>
    <updated>2023-05-23T00:00:00Z</updated>
    <id>https://iamninad.com</id>
    <author>
        <name>neenad ingole</name>
        <email></email>
    </author>
    
        
        <entry>
            <title>Improve Visibility Even While Pair Programming</title>
            <link href="https://iamninad.com/posts/improve-visibility-even-while-pair-programming/"/>
            <updated>2023-05-23T00:00:00Z</updated>
            <id>https://iamninad.com/posts/improve-visibility-even-while-pair-programming/</id>
            <content type="html">
                <![CDATA[
                <h2 id="what-is-pair-programming%3F" tabindex="-1">What is Pair Programming? <a class="header-anchor" href="#what-is-pair-programming%3F"></a></h2>
<p>From Wikipedia's definition::</p>
<blockquote>
<p>Pair programming is
a <a href="https://medium.com/r/?url=https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FSoftware_development">software development</a>
technique in which two programmers work together at one workstation. One, the driver, writes code while the other, the
observer or navigator,[1] reviews each line of code as it is typed in. The
two programmers switch roles frequently.</p>
</blockquote>
<p>A lot of companies these days are adopting the Pair Programming practice. Some have pioneered the way of working using
Pair Programming like <a href="https://www.thoughtworks.com/">ThoughtWorks</a> where I used to work before. But, some are new to
this and are slowly getting into
it.</p>
<p>Pairing is challenging when you start in itself. The real challenge becomes when the manager evaluates performance on
the wrong measures. It bothers all the devs in a team. Managers only see one person commit logs in git or one person
assigned to JIRA tasks and thus, accounts for work by only one developer.</p>
<p>In such scenarios, the other developer is not visible to the manager. Managers flag developers as “low-performance” team
members.</p>
<p>Not all managers have this problem. Eg. In ThoughtWorks, managers know that a pair works on a task. They are well aware
of how each person contributes to the complete delivery of the project. But, for the companies where the practices are
being adopted, the managers are not aware of how to measure a developer’s performance. They use the same old metrics
like Git log and Jira Tasks to check how many tasks are being completed by the developers. As such, one dev suffers if
the commits or the tasks are not directly assigned to them while pairing.</p>
<p>This plays badly with the annual reviews too. When the manager shows them that their performance is not meeting the
threshold. This becomes a barrier to pair programming. It certainly creates a picture that pairing is not a good thing
because they are being evaluated on the wrong grounds. Ultimately the entire team give up the practice of Pair
programming.</p>
<p>Git logs and Jira tasks are the wrong metrics to measure a developer’s performance while adopting pair programming.
Managers who are using it should avoid such measuring criteria.</p>
<p>You could also talk to your manager if they are friendly and open to new ideas and new learnings. But, not all managers
are like that. Giving feedback sometimes backfires and you are not on good terms with them.</p>
<p>So what should one do to be visible for the work they are doing while Pairing? From my own experience, there are three
things which I will share with you that would work well in such cases</p>
<h2 id="1.-add-pariee-in-jira-task" tabindex="-1">1. Add Pariee in Jira Task <a class="header-anchor" href="#1.-add-pariee-in-jira-task"></a></h2>
<p>When selecting a task on Jira or any other project management software. Make sure to have an extra attribute of
“Pariee”. Select the person you are paring with you.</p>
<p>This will help when the manager is generating a report on how many tasks each developer is working on. They will have to
calculate the report based on aggregated value of tasks which are directly assigned to you as well as tasks which you
were part of as a Pariee.</p>
<figure><img src="/images/improve-visibility-even-while-pair-programming/jira.png" alt="Jira Task with Pariee"></figure>
<p>The above context section of Jira shows a sample task. I have configured my JIRA workflow to have Pairee as another
attribute for the task.</p>
<h2 id="2.-git-co-authored-commit" tabindex="-1">2. Git Co-Authored Commit <a class="header-anchor" href="#2.-git-co-authored-commit"></a></h2>
<p>You could attribute a commit to more than one developer using co-authored commit. Both Github and Gitlab support this
feature. When working as a pair make sure you follow the below commit message format</p>
<pre class="language-bash"><code class="language-bash">  This is your normal commit message
  
  Co-authored-by: Ninad Ingole <span class="token operator">&lt;</span>myemail@gmail.com<span class="token operator">></span></code></pre>
<p>With this, you will see both authors in the commit history on GitHub. It will show the commits done to the repository by
both the developer in their individual GitHub contribution section.</p>
<figure><img src="/images/improve-visibility-even-while-pair-programming/contribution.webp" alt="Git Co-Authored Commit"></figure>
<p>For people using tools
like <a href="https://docs.github.com/en/desktop/contributing-and-collaborating-using-github-desktop/making-changes-in-a-branch/committing-and-reviewing-changes-to-your-project-in-github-desktop#write-a-commit-message-and-push-your-changes">GitHub Desktop</a>.
The GUI shows the option to include another author as a contributor eg</p>
<figure><img src="/images/improve-visibility-even-while-pair-programming/add-co-author-commit.webp" alt="GitHub Desktop Commit"></figure>
<p>For managers who are doing micro-management. This will be your proof. Proof that you were always pairing and that you
share equal contributions to the tasks.</p>
<p>Also for PR Workflows, the Reviewer is aware of the people involved in the change. This helps to reach out to any one of
the dev for review comments.</p>
<h2 id="3.-pair-names-in-commit-message" tabindex="-1">3. Pair Names in Commit Message <a class="header-anchor" href="#3.-pair-names-in-commit-message"></a></h2>
<p>Not all platforms of Version control support co-authored commits. This last piece of advice is for such platforms.
For old commits, having the Pair names in the messages is a quick navigation tool.</p>
<p>I simply like to keep the Pair names in the format [First/Second] in the commit message. This also shows nicely when I
am doing <code>git log --oneline</code></p>
<figure><img src="/images/improve-visibility-even-while-pair-programming/gitlog.png" alt="Git Log with Pair Names"></figure>
<hr>
<h2 id="conclusion" tabindex="-1">Conclusion <a class="header-anchor" href="#conclusion"></a></h2>
<p>I hope the practices I shared help you to keep developing pair programming skills. It would also help you to avoid any
problems with your manager.</p>
<p>I haven’t shared the benefits of Pair programming in this post. Advantages like knowledge sharing, quick reviews, proper
planning etc. are a few to list. I would encourage others who are not doing it to try it out.</p>
<p>For any more questions related to pair programming or any problems please reach out to me. I would be happy to help you
in the journey of pair programming 😊</p>

                ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Secret For Testing UUID Generation In Golang</title>
            <link href="https://iamninad.com/posts/secret-for-testing-uuid-generation-in-golang/"/>
            <updated>2023-05-06T00:00:00Z</updated>
            <id>https://iamninad.com/posts/secret-for-testing-uuid-generation-in-golang/</id>
            <content type="html">
                <![CDATA[
                <p>In today's fast-paced world of software development, generating unique identifiers is an absolute necessity. In golang,
there are various packages available that can help you achieve this. One such package is the Google UUID package.</p>
<p>To get started, you first need to import the Google UUID library into your Golang project.</p>
<pre class="language-bash"><code class="language-bash">go get <span class="token parameter variable">-u</span> github.com/google/uuid</code></pre>
<p>Once you have imported the library, you could use the <code>uuid.New()</code> method to generate a random UUID.
This method takes no arguments and is the easiest one to get started. 🆒</p>
<p>The challenge with using this is how to create a Unit Test for the code 👊. In the Unit Test, we expect to get a constant
known behaviour from our code. But, the behaviour of uuid.New() method is to generate random sequences on each
execution.</p>
<p>Let me show you what I mean by using a small code. Below, I am writing a very simple test. I will run this test many
times and we will check the output. All the generated UUIDs for each different run will be random.</p>
<pre class="language-go"><code class="language-go"><span class="token keyword">func</span> <span class="token function">Test_UUIDGeneration</span><span class="token punctuation">(</span>t <span class="token operator">*</span>testing<span class="token punctuation">.</span>T<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  uuid <span class="token operator">:=</span> uuid<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  
  fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>fmt<span class="token punctuation">.</span><span class="token function">Sprintf</span><span class="token punctuation">(</span><span class="token string">"UUID: %s"</span><span class="token punctuation">,</span> uuid<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span> OUTPUT <span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">-</span>

  UUID<span class="token punctuation">:</span> c26a1010<span class="token operator">-</span>a207<span class="token operator">-</span>47cb<span class="token operator">-</span>b399<span class="token operator">-</span>9de8acad3bba
  UUID<span class="token punctuation">:</span> e4c1776f<span class="token operator">-</span>cd94<span class="token operator">-</span><span class="token number">4710</span><span class="token operator">-</span>b5eb<span class="token operator">-</span>710c081df916
  UUID<span class="token punctuation">:</span> 923c129c<span class="token operator">-</span>ba0b<span class="token operator">-</span><span class="token number">4534</span><span class="token operator">-</span>aadf<span class="token operator">-</span>db98470fd99c</code></pre>
<blockquote>
<p>Note:: If you run the above test locally with go test make sure to disable the cache. Use <code>--count=1</code> in the command to
disable caching otherwise the test will generate same uuids</p>
</blockquote>
<p>Consider you are writing a service layer that generates the UUID and persist it in the DB. You write a Unit Test but
cannot assert the value of the generated UUID. Because, on every new execution on the CI, the value will be different.
How will you test the code and avoid randomness?</p>
<p>Here is a small code to mimic a service layer and the test::</p>
<pre class="language-go"><code class="language-go"><span class="token keyword">type</span> Employee <span class="token keyword">struct</span> <span class="token punctuation">{</span>
  ID        uuid<span class="token punctuation">.</span>UUID <span class="token string">`json:"id"`</span>
  FirstName <span class="token builtin">string</span>    <span class="token string">`json:"first_name"`</span>
  LastName  <span class="token builtin">string</span>    <span class="token string">`json:"last_name"`</span>
<span class="token punctuation">}</span>

<span class="token comment">// Storage interface is used to persist employee to DB</span>
<span class="token keyword">type</span> Storage <span class="token keyword">interface</span> <span class="token punctuation">{</span>
    <span class="token function">Save</span><span class="token punctuation">(</span>employee Employee<span class="token punctuation">)</span> <span class="token builtin">error</span>
<span class="token punctuation">}</span>

<span class="token comment">// Employee service orchestrate the creation of employee</span>
<span class="token keyword">type</span> EmployeeService <span class="token keyword">struct</span> <span class="token punctuation">{</span>
    storage Storage
<span class="token punctuation">}</span>

<span class="token comment">// For simplicity the layer only calls the storage layer to persist the value.</span>
<span class="token comment">// However, in a real world the service layer will do more than this.</span>
<span class="token keyword">func</span> <span class="token punctuation">(</span>e <span class="token operator">*</span>EmployeeService<span class="token punctuation">)</span> <span class="token function">Create</span><span class="token punctuation">(</span>firstName<span class="token punctuation">,</span> lastName <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span>
  employee <span class="token operator">:=</span> Employee<span class="token punctuation">{</span>
    ID<span class="token punctuation">:</span>        uuid<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    FirstName<span class="token punctuation">:</span> firstName<span class="token punctuation">,</span>
    LastName<span class="token punctuation">:</span>  lastName<span class="token punctuation">,</span>
  <span class="token punctuation">}</span>
  
  <span class="token keyword">return</span> e<span class="token punctuation">.</span>storage<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>employee<span class="token punctuation">)</span>
<span class="token punctuation">}</span></code></pre>
<pre class="language-go"><code class="language-go"><span class="token keyword">type</span> mockStorage <span class="token keyword">struct</span> <span class="token punctuation">{</span>
    mock<span class="token punctuation">.</span>Mock
<span class="token punctuation">}</span>

<span class="token comment">// We mock the storage layer to see if the value and type is correctly passed</span>
<span class="token comment">// to the method</span>
<span class="token keyword">func</span> <span class="token punctuation">(</span>m <span class="token operator">*</span>mockStorage<span class="token punctuation">)</span> <span class="token function">Save</span><span class="token punctuation">(</span>employee Employee<span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span>
  args <span class="token operator">:=</span> m<span class="token punctuation">.</span><span class="token function">Called</span><span class="token punctuation">(</span>employee<span class="token punctuation">)</span>
  <span class="token keyword">return</span> args<span class="token punctuation">.</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token function">TestEmployeeService_Create</span><span class="token punctuation">(</span>t <span class="token operator">*</span>testing<span class="token punctuation">.</span>T<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  t<span class="token punctuation">.</span><span class="token function">Parallel</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  
  expectedEmployee <span class="token operator">:=</span> Employee<span class="token punctuation">{</span>
    ID<span class="token punctuation">:</span>        uuid<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token comment">// This will always generate new random uuid</span>
    FirstName<span class="token punctuation">:</span> <span class="token string">"John"</span><span class="token punctuation">,</span>
    LastName<span class="token punctuation">:</span>  <span class="token string">"Doe"</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span>
  
  storage <span class="token operator">:=</span> <span class="token operator">&amp;</span>mockStorage<span class="token punctuation">{</span><span class="token punctuation">}</span>
  employeeService <span class="token operator">:=</span> EmployeeService<span class="token punctuation">{</span>storage<span class="token punctuation">:</span> storage<span class="token punctuation">}</span>
  
  storage<span class="token punctuation">.</span><span class="token function">On</span><span class="token punctuation">(</span><span class="token string">"Save"</span><span class="token punctuation">,</span> mock<span class="token punctuation">.</span><span class="token function">MatchedBy</span><span class="token punctuation">(</span><span class="token keyword">func</span> <span class="token punctuation">(</span>x <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">{</span>
    employee<span class="token punctuation">,</span> ok <span class="token operator">:=</span> x<span class="token punctuation">.</span><span class="token punctuation">(</span>Employee<span class="token punctuation">)</span>
    
    <span class="token keyword">if</span> <span class="token operator">!</span>ok <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">false</span>
    <span class="token punctuation">}</span>
    
    <span class="token keyword">return</span> assert<span class="token punctuation">.</span><span class="token function">EqualValues</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> expectedEmployee<span class="token punctuation">,</span> employee<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Return</span><span class="token punctuation">(</span><span class="token boolean">nil</span><span class="token punctuation">)</span>
  
  err <span class="token operator">:=</span> employeeService<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span><span class="token string">"John"</span><span class="token punctuation">,</span> <span class="token string">"Doe"</span><span class="token punctuation">)</span>
  
  assert<span class="token punctuation">.</span><span class="token function">NoError</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> err<span class="token punctuation">)</span>
  storage<span class="token punctuation">.</span><span class="token function">AssertExpectations</span><span class="token punctuation">(</span>t<span class="token punctuation">)</span>
<span class="token punctuation">}</span></code></pre>
<p>If I run the above test it will fail 🔴::</p>
<pre class="language-bash"><code class="language-bash"><span class="token operator">==</span><span class="token operator">=</span> RUN   TestEmployeeService_Create
<span class="token operator">==</span><span class="token operator">=</span> PAUSE TestEmployeeService_Create
<span class="token operator">==</span><span class="token operator">=</span> CONT  TestEmployeeService_Create
/tests/data_test.go:89:
      Error Trace:    /tests/data_test.go:89
                      /tests/value.go:586
                      /tests/value.go:370
                      /tests/data_test.go:66
                      /tests/data_test.go:58
                      /tests/data_test.go:92
      Error:          Not equal:
                      expected: tests.Employee<span class="token punctuation">{</span>ID:uuid.UUID<span class="token punctuation">{</span>0xeb, 0x5, 0x6f, 0x11, 0x47, 0x8, 0x42, 0x2d, 0xb5, 0x23, 0x47, 0x2, 0x40, 0x18, 0x85, 0x94<span class="token punctuation">}</span>, FirstName:<span class="token string">"John"</span>, LastName:<span class="token string">"Doe"</span><span class="token punctuation">}</span>
                      actual  <span class="token builtin class-name">:</span> tests.Employee<span class="token punctuation">{</span>ID:uuid.UUID<span class="token punctuation">{</span>0xb4, 0xb7, 0x8f, 0x21, 0x36, 0xc8, 0x4e, 0x3e, 0x9a, 0xa3, 0x96, 0x79, 0xd3, 0xcc, 0xbc, 0xdc<span class="token punctuation">}</span>, FirstName:<span class="token string">"John"</span>, LastName:<span class="token string">"Doe"</span><span class="token punctuation">}</span>

                      Diff:
                      --- Expected
                      +++ Actual
                      @@ -2,3 +2,3 @@
                        ID: <span class="token punctuation">(</span>uuid.UUID<span class="token punctuation">)</span> <span class="token punctuation">(</span>len<span class="token operator">=</span><span class="token number">16</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                      -  00000000  eb 05 6f <span class="token number">11</span> <span class="token number">47</span> 08 <span class="token number">42</span> 2d  b5 <span class="token number">23</span> <span class="token number">47</span> 02 <span class="token number">40</span> <span class="token number">18</span> <span class="token number">85</span> <span class="token number">94</span>  <span class="token operator">|</span><span class="token punctuation">..</span>o.G.B-.<span class="token comment">#G.@...|</span>
                      +  00000000  b4 b7 8f <span class="token number">21</span> <span class="token number">36</span> c8 4e 3e  9a a3 <span class="token number">96</span> <span class="token number">79</span> d3 cc <span class="token function">bc</span> <span class="token function">dc</span>  <span class="token operator">|</span><span class="token punctuation">..</span>.<span class="token operator">!</span><span class="token number">6</span>.N<span class="token operator">></span><span class="token punctuation">..</span>.y<span class="token punctuation">..</span><span class="token punctuation">..</span><span class="token operator">|</span>
                        <span class="token punctuation">}</span>,
      Test:           TestEmployeeService_Create</code></pre>
<p>You could see that the UUIDs were generated by the service layer in the logs. To use <code>assert.EqualValues</code>
or <code>assert.Equals</code>
on a struct, all the attribute values should match. The UUID in the <code>expected</code> employee instance is different.</p>
<h2 id="what-would-you-do-to-avoid-this%3F" tabindex="-1">What would you do to avoid this? <a class="header-anchor" href="#what-would-you-do-to-avoid-this%3F"></a></h2>
<p>Many people to avoid the problem will think of not writing the test 😅. Let's see the different ways to overcome this
problem.</p>
<img src="https://media0.giphy.com/media/v1.Y2lkPTc5MGI3NjExMTc2MjRiODg4MzIxYzg1MTk2NTFmMDdjNTM4ZGNlM2MwYzFhMzljYSZlcD12MV9pbnRlcm5hbF9naWZzX2dpZklkJmN0PWc/w89ak63KNl0nJl80ig/giphy.gif" alt="gif" class="Gif" />
<hr>
<h2 id="1.-manually-check-all-the-struct-attributes-and-avoid-the-uuid-check" tabindex="-1">1. Manually check all the struct attributes and avoid the UUID check <a class="header-anchor" href="#1.-manually-check-all-the-struct-attributes-and-avoid-the-uuid-check"></a></h2>
<p>Our assumption is that this library is open-source and well-maintained by the community. We can rely on the fact that
things will work fine. We skip the UUID check part but check other attributes eg::</p>
<pre class="language-go"><code class="language-go">storage<span class="token punctuation">.</span><span class="token function">On</span><span class="token punctuation">(</span><span class="token string">"Save"</span><span class="token punctuation">,</span> mock<span class="token punctuation">.</span><span class="token function">MatchedBy</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span>x <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">{</span>
  employee<span class="token punctuation">,</span> ok <span class="token operator">:=</span> x<span class="token punctuation">.</span><span class="token punctuation">(</span>Employee<span class="token punctuation">)</span>
  
  <span class="token keyword">if</span> <span class="token operator">!</span>ok <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token boolean">false</span>
  <span class="token punctuation">}</span>
  
  <span class="token keyword">return</span> employee<span class="token punctuation">.</span>ID <span class="token operator">!=</span> uuid<span class="token punctuation">.</span>Nil <span class="token operator">&amp;&amp;</span> employee<span class="token punctuation">.</span>FirstName <span class="token operator">==</span> expectedEmployee<span class="token punctuation">.</span>FirstName <span class="token operator">&amp;&amp;</span> employee<span class="token punctuation">.</span>LastName <span class="token operator">==</span> expectedEmployee<span class="token punctuation">.</span>LastName
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Return</span><span class="token punctuation">(</span><span class="token boolean">nil</span><span class="token punctuation">)</span></code></pre>
<p>This is ok if you have a struct with few attributes. But, this will become a headache if you have 15–20 attributes. This
indeed is not a scalable approach.</p>
<h2 id="2.-parse-the-uuid-to-check-for-error" tabindex="-1">2. Parse the UUID To Check For Error <a class="header-anchor" href="#2.-parse-the-uuid-to-check-for-error"></a></h2>
<p>Parse the UUID to check if the service generates the UUID and if there is no issue. For other attributes do exactly what
we did in the previous example. This will also suffer from the same problem as the previous solution</p>
<pre class="language-go"><code class="language-go">    <span class="token boolean">_</span><span class="token punctuation">,</span> err <span class="token operator">:=</span> uuid<span class="token punctuation">.</span><span class="token function">Parse</span><span class="token punctuation">(</span>employee<span class="token punctuation">.</span>ID<span class="token punctuation">.</span><span class="token function">String</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  
    <span class="token keyword">return</span> err <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token operator">&amp;&amp;</span> employee<span class="token punctuation">.</span>FirstName <span class="token operator">==</span> expectedEmployee<span class="token punctuation">.</span>FirstName <span class="token operator">&amp;&amp;</span> employee<span class="token punctuation">.</span>LastName <span class="token operator">==</span> expectedEmployee<span class="token punctuation">.</span>LastName</code></pre>
<h2 id="3.-pass-a-uuid-generator-function-type" tabindex="-1">3. Pass a UUID Generator Function Type <a class="header-anchor" href="#3.-pass-a-uuid-generator-function-type"></a></h2>
<p>A separate uuid generator function is passed to the struct to generate the uuid. A test generator is then used in the
unit test to mock and pass a static UUID. An assertion on this static value will verify the behaviour of the code. Eg::</p>
<pre class="language-go"><code class="language-go"><span class="token keyword">type</span> UUIDGenerator <span class="token keyword">func</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> uuid<span class="token punctuation">.</span>UUID

<span class="token keyword">var</span> DefaultUUIDGenerator <span class="token operator">=</span> <span class="token keyword">func</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> uuid<span class="token punctuation">.</span>UUID <span class="token punctuation">{</span>
    <span class="token keyword">return</span> uuid<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">type</span> EmployeeService <span class="token keyword">struct</span> <span class="token punctuation">{</span>
  storage       Storage
  uuidGenerator UUIDGenerator
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>e <span class="token operator">*</span>EmployeeService<span class="token punctuation">)</span> <span class="token function">Create</span><span class="token punctuation">(</span>firstName<span class="token punctuation">,</span> lastName <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span>
  employee <span class="token operator">:=</span> Employee<span class="token punctuation">{</span>
    ID<span class="token punctuation">:</span>        e<span class="token punctuation">.</span><span class="token function">uuidGenerator</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    FirstName<span class="token punctuation">:</span> firstName<span class="token punctuation">,</span>
    LastName<span class="token punctuation">:</span>  lastName<span class="token punctuation">,</span>
  <span class="token punctuation">}</span>
  
  <span class="token keyword">return</span> e<span class="token punctuation">.</span>storage<span class="token punctuation">.</span><span class="token function">Save</span><span class="token punctuation">(</span>employee<span class="token punctuation">)</span>
<span class="token punctuation">}</span></code></pre>
<pre class="language-go"><code class="language-go"><span class="token keyword">func</span> <span class="token function">TestEmployeeService_Create</span><span class="token punctuation">(</span>t <span class="token operator">*</span>testing<span class="token punctuation">.</span>T<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  t<span class="token punctuation">.</span><span class="token function">Parallel</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  
  expectedID <span class="token operator">:=</span> uuid<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  
  expectedEmployee <span class="token operator">:=</span> Employee<span class="token punctuation">{</span>
    ID<span class="token punctuation">:</span>        expectedID<span class="token punctuation">,</span>
    FirstName<span class="token punctuation">:</span> <span class="token string">"John"</span><span class="token punctuation">,</span>
    LastName<span class="token punctuation">:</span>  <span class="token string">"Doe"</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span>
  
  storage <span class="token operator">:=</span> <span class="token operator">&amp;</span>mockStorage<span class="token punctuation">{</span><span class="token punctuation">}</span>
  
  uuidGenerator <span class="token operator">:=</span> <span class="token keyword">func</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> uuid<span class="token punctuation">.</span>UUID <span class="token punctuation">{</span>
    <span class="token keyword">return</span> expectedID
  <span class="token punctuation">}</span>
  
  employeeService <span class="token operator">:=</span> EmployeeService<span class="token punctuation">{</span>storage<span class="token punctuation">:</span> storage<span class="token punctuation">,</span> uuidGenerator<span class="token punctuation">:</span> uuidGenerator<span class="token punctuation">}</span>
  
  storage<span class="token punctuation">.</span><span class="token function">On</span><span class="token punctuation">(</span><span class="token string">"Save"</span><span class="token punctuation">,</span> mock<span class="token punctuation">.</span><span class="token function">MatchedBy</span><span class="token punctuation">(</span><span class="token keyword">func</span> <span class="token punctuation">(</span>x <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">{</span>
    employee<span class="token punctuation">,</span> ok <span class="token operator">:=</span> x<span class="token punctuation">.</span><span class="token punctuation">(</span>Employee<span class="token punctuation">)</span>
    
    <span class="token keyword">if</span> <span class="token operator">!</span>ok <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">false</span>
    <span class="token punctuation">}</span>
    
    <span class="token keyword">return</span> assert<span class="token punctuation">.</span><span class="token function">EqualValues</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> expectedEmployee<span class="token punctuation">,</span> employee<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Return</span><span class="token punctuation">(</span><span class="token boolean">nil</span><span class="token punctuation">)</span>
  
  err <span class="token operator">:=</span> employeeService<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span><span class="token string">"John"</span><span class="token punctuation">,</span> <span class="token string">"Doe"</span><span class="token punctuation">)</span>
  
  assert<span class="token punctuation">.</span><span class="token function">NoError</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> err<span class="token punctuation">)</span>
  storage<span class="token punctuation">.</span><span class="token function">AssertExpectations</span><span class="token punctuation">(</span>t<span class="token punctuation">)</span>
<span class="token punctuation">}</span></code></pre>
<p>This solution is also good. It will allow us to assert the entire entity and don't have to check every field like in the
previous two examples. This may become a problem if you have to use it at many places in your code base.</p>
<p>You could create an abstraction that will help to reuse and it will work fine. But what if I tell you there is a *
<em><em>secret</em></em>* way and you don't have to do all these shenanigans?</p>
<h2 id="use-setrand-%F0%9F%9A%80" tabindex="-1">Use SetRand 🚀 <a class="header-anchor" href="#use-setrand-%F0%9F%9A%80"></a></h2>
<p>Let's look at the <a href="https://pkg.go.dev/github.com/google/uuid#SetRand">documentation of the library</a>. There is a way to
generate deterministic UUID, using <code>uuid.SetRand()</code>. If we use the correct Seed Source to the <code>SetRand</code> function it will
allow us to get deterministic UUIDs.</p>
<p>Let’s see how::</p>
<pre class="language-go"><code class="language-go"><span class="token keyword">func</span> <span class="token function">Test_uuidTest</span><span class="token punctuation">(</span>t <span class="token operator">*</span>testing<span class="token punctuation">.</span>T<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  uuid<span class="token punctuation">.</span><span class="token function">SetRand</span><span class="token punctuation">(</span>rand<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span>rand<span class="token punctuation">.</span><span class="token function">NewSource</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  
  val1 <span class="token operator">:=</span> uuid<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  val2 <span class="token operator">:=</span> uuid<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  
  assert<span class="token punctuation">.</span><span class="token function">EqualValues</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> uuid<span class="token punctuation">.</span><span class="token function">MustParse</span><span class="token punctuation">(</span><span class="token string">"52fdfc07-2182-454f-963f-5f0f9a621d72"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> val1<span class="token punctuation">,</span> fmt<span class="token punctuation">.</span><span class="token function">Sprintf</span><span class="token punctuation">(</span><span class="token string">"generated %v"</span><span class="token punctuation">,</span> val1<span class="token punctuation">)</span><span class="token punctuation">)</span>
  assert<span class="token punctuation">.</span><span class="token function">EqualValues</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> uuid<span class="token punctuation">.</span><span class="token function">MustParse</span><span class="token punctuation">(</span><span class="token string">"9566c74d-1003-4c4d-bbbb-0407d1e2c649"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> val2<span class="token punctuation">,</span> fmt<span class="token punctuation">.</span><span class="token function">Sprintf</span><span class="token punctuation">(</span><span class="token string">"generated %v"</span><span class="token punctuation">,</span> val2<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre>
<p>I add another test above to show how to use the <code>SetRand</code> method. I pass a new <code>*rand.Rand</code> instance by setting the seed
value to the <code>rand.NewSource(1)</code>. When you do this the UUIDs generated will be deterministic in nature. They will be
exactly the same on each run irrespective of the platform you run on.</p>
<p>To verify this, I ran the same example on the go playground <a href="https://go.dev/play/p/Eaa5OR0P9f6">here</a>. You will see
below that the generated UUIDs match our assertion value.</p>
<figure><img src="/images/secret-for-testing-uuid-generation-in-golang/code.webp" alt="code"></figure>
<p>So let’s update our existing test to see how to use this new trick.</p>
<pre class="language-go"><code class="language-go"><span class="token keyword">func</span> <span class="token function">TestEmployeeService_Create</span><span class="token punctuation">(</span>t <span class="token operator">*</span>testing<span class="token punctuation">.</span>T<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  uuid<span class="token punctuation">.</span><span class="token function">SetRand</span><span class="token punctuation">(</span>rand<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span>rand<span class="token punctuation">.</span><span class="token function">NewSource</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  
  expectedEmployee <span class="token operator">:=</span> Employee<span class="token punctuation">{</span>
    ID<span class="token punctuation">:</span>        uuid<span class="token punctuation">.</span><span class="token function">MustParse</span><span class="token punctuation">(</span><span class="token string">"52fdfc07-2182-454f-963f-5f0f9a621d72"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    FirstName<span class="token punctuation">:</span> <span class="token string">"John"</span><span class="token punctuation">,</span>
    LastName<span class="token punctuation">:</span>  <span class="token string">"Doe"</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span>
  
  storage <span class="token operator">:=</span> <span class="token operator">&amp;</span>mockStorage<span class="token punctuation">{</span><span class="token punctuation">}</span>
  
  employeeService <span class="token operator">:=</span> EmployeeService<span class="token punctuation">{</span>storage<span class="token punctuation">:</span> storage<span class="token punctuation">}</span>
  
  storage<span class="token punctuation">.</span><span class="token function">On</span><span class="token punctuation">(</span><span class="token string">"Save"</span><span class="token punctuation">,</span> mock<span class="token punctuation">.</span><span class="token function">MatchedBy</span><span class="token punctuation">(</span><span class="token keyword">func</span> <span class="token punctuation">(</span>x <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">{</span>
    employee<span class="token punctuation">,</span> ok <span class="token operator">:=</span> x<span class="token punctuation">.</span><span class="token punctuation">(</span>Employee<span class="token punctuation">)</span>
    
    <span class="token keyword">if</span> <span class="token operator">!</span>ok <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">false</span>
    <span class="token punctuation">}</span>
    
    <span class="token keyword">return</span> assert<span class="token punctuation">.</span><span class="token function">EqualValues</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> expectedEmployee<span class="token punctuation">,</span> employee<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Return</span><span class="token punctuation">(</span><span class="token boolean">nil</span><span class="token punctuation">)</span>
  
  err <span class="token operator">:=</span> employeeService<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span><span class="token string">"John"</span><span class="token punctuation">,</span> <span class="token string">"Doe"</span><span class="token punctuation">)</span>
  
  assert<span class="token punctuation">.</span><span class="token function">NoError</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> err<span class="token punctuation">)</span>
  storage<span class="token punctuation">.</span><span class="token function">AssertExpectations</span><span class="token punctuation">(</span>t<span class="token punctuation">)</span>
<span class="token punctuation">}</span></code></pre>
<p>There is one caveat with this approach. The <code>math/rand</code> source that we have used is not thread-safe. As per the
documentation::</p>
<pre class="language-go"><code class="language-go"><span class="token comment">// NewSource returns a new pseudo-random Source seeded with the given value.</span>
<span class="token comment">// Unlike the default Source used by top-level functions, this source is not</span>
<span class="token comment">// safe for concurrent use by multiple goroutines.</span>
<span class="token comment">// The returned Source implements Source64.</span></code></pre>
<p>So having multiple tests running parallel would cause a data race issue. I tried to overcome this but there’s no
straightforward way. I don’t want to add another layer of complexity to avoid the first one 😅 it’s not productive at
all.</p>
<p>I looked into how these libraries did the unit test. I realised that
both <a href="https://github.com/google/uuid/blob/master/uuid_test.go#L501">google/uuid</a> and
golang <a href="https://github.com/golang/go/blob/master/src/math/rand/rand_test.go#L371">math/rand package</a> do not use
<code>t.Parallel()</code> for the tests. So, The simplest way to fix the issue would be to remove <code>t.Parallel()</code> from all such unit
tests ✅.</p>
<h2 id="5.-use-google%2Fgo-cmp" tabindex="-1">5. Use google/go-cmp <a class="header-anchor" href="#5.-use-google%2Fgo-cmp"></a></h2>
<p>After publishing this post, my awesome readers reached out to me with one more approach.
I am really thankful to all those feedback. The <a href="https://blog.iamninad.com/github.com/google/go-cmp">google/go-cmp</a> library allows to skip/ignore fields from comparison.</p>
<p>There are two kind of people, one who wants to compare all the fields of the struct and some would prefer to ignore the
UUID check because the google/uuid library is battle tested. So based on which category you belong to you could use the previous
approach or you could use this approach.</p>
<p>Let’s rewrite our existing test to use the <code>cmpopts.IgnoreFields</code></p>
<pre class="language-go"><code class="language-go"><span class="token keyword">func</span> <span class="token function">TestEmployeeService_Create</span><span class="token punctuation">(</span>t <span class="token operator">*</span>testing<span class="token punctuation">.</span>T<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 expectedEmployee <span class="token operator">:=</span> Employee<span class="token punctuation">{</span>
  FirstName<span class="token punctuation">:</span> <span class="token string">"John"</span><span class="token punctuation">,</span>
  LastName<span class="token punctuation">:</span>  <span class="token string">"Doe"</span><span class="token punctuation">,</span>
 <span class="token punctuation">}</span>

 storage <span class="token operator">:=</span> <span class="token operator">&amp;</span>mockStorage<span class="token punctuation">{</span><span class="token punctuation">}</span>

 employeeService <span class="token operator">:=</span> EmployeeService<span class="token punctuation">{</span>storage<span class="token punctuation">:</span> storage<span class="token punctuation">}</span>

 storage<span class="token punctuation">.</span><span class="token function">On</span><span class="token punctuation">(</span><span class="token string">"Save"</span><span class="token punctuation">,</span> mock<span class="token punctuation">.</span><span class="token function">MatchedBy</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span>x <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">{</span>
  actual<span class="token punctuation">,</span> ok <span class="token operator">:=</span> x<span class="token punctuation">.</span><span class="token punctuation">(</span>Employee<span class="token punctuation">)</span>

  <span class="token keyword">if</span> <span class="token operator">!</span>ok <span class="token punctuation">{</span>
   <span class="token keyword">return</span> <span class="token boolean">false</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">var</span> diff <span class="token builtin">string</span>
  <span class="token keyword">if</span> diff <span class="token operator">=</span> cmp<span class="token punctuation">.</span><span class="token function">Diff</span><span class="token punctuation">(</span>expectedEmployee<span class="token punctuation">,</span> actual<span class="token punctuation">,</span> cmpopts<span class="token punctuation">.</span><span class="token function">IgnoreFields</span><span class="token punctuation">(</span>Employee<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">"ID"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> diff <span class="token operator">!=</span> <span class="token string">""</span> <span class="token punctuation">{</span>
   t<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"Save() mismatch (-want +got):\n%s"</span><span class="token punctuation">,</span> diff<span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">return</span> diff <span class="token operator">==</span> <span class="token string">""</span>
 <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Return</span><span class="token punctuation">(</span><span class="token boolean">nil</span><span class="token punctuation">)</span>

 err <span class="token operator">:=</span> employeeService<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span><span class="token string">"John"</span><span class="token punctuation">,</span> <span class="token string">"Doe"</span><span class="token punctuation">)</span>

 assert<span class="token punctuation">.</span><span class="token function">NoError</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> err<span class="token punctuation">)</span>
 storage<span class="token punctuation">.</span><span class="token function">AssertExpectations</span><span class="token punctuation">(</span>t<span class="token punctuation">)</span>
<span class="token punctuation">}</span></code></pre>
<p>On failure ☠️ the test will show a diff comparison of the fields that didn’t match like below</p>
<pre class="language-go"><code class="language-go"><span class="token operator">==</span><span class="token operator">=</span> RUN   TestEmployeeService_Create
    <span class="token operator">/</span>Users<span class="token operator">/</span>neenadingole<span class="token operator">/</span>codes<span class="token operator">/</span>opensource<span class="token operator">/</span>gotest<span class="token operator">-</span>ls<span class="token operator">/</span>main_test<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span><span class="token number">275</span><span class="token punctuation">:</span> <span class="token function">Save</span><span class="token punctuation">(</span><span class="token punctuation">)</span> mismatch <span class="token punctuation">(</span><span class="token operator">-</span>want <span class="token operator">+</span>got<span class="token punctuation">)</span><span class="token punctuation">:</span>
          main<span class="token punctuation">.</span>Employee<span class="token punctuation">{</span>
                <span class="token operator">...</span> <span class="token comment">// 1 ignored field</span>
        <span class="token operator">-</span>       FirstName<span class="token punctuation">:</span> <span class="token string">"Face"</span><span class="token punctuation">,</span>
        <span class="token operator">+</span>       FirstName<span class="token punctuation">:</span> <span class="token string">"John"</span><span class="token punctuation">,</span>
                LastName<span class="token punctuation">:</span>  <span class="token string">"Doe"</span><span class="token punctuation">,</span>
          <span class="token punctuation">}</span>
    <span class="token operator">/</span>Users<span class="token operator">/</span>neenadingole<span class="token operator">/</span>codes<span class="token operator">/</span>opensource<span class="token operator">/</span>gotest<span class="token operator">-</span>ls<span class="token operator">/</span>main_test<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span><span class="token number">275</span><span class="token punctuation">:</span> <span class="token function">Save</span><span class="token punctuation">(</span><span class="token punctuation">)</span> mismatch <span class="token punctuation">(</span><span class="token operator">-</span>want <span class="token operator">+</span>got<span class="token punctuation">)</span><span class="token punctuation">:</span>
          main<span class="token punctuation">.</span>Employee<span class="token punctuation">{</span>
                <span class="token operator">...</span> <span class="token comment">// 1 ignored field</span>
        <span class="token operator">-</span>       FirstName<span class="token punctuation">:</span> <span class="token string">"Face"</span><span class="token punctuation">,</span>
        <span class="token operator">+</span>       FirstName<span class="token punctuation">:</span> <span class="token string">"John"</span><span class="token punctuation">,</span>
                LastName<span class="token punctuation">:</span>  <span class="token string">"Doe"</span><span class="token punctuation">,</span>
          <span class="token punctuation">}</span>
<span class="token operator">--</span><span class="token operator">-</span> FAIL<span class="token punctuation">:</span> TestEmployeeService_Create <span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">.</span>00s<span class="token punctuation">)</span>
<span class="token builtin">panic</span><span class="token punctuation">:</span>

mock<span class="token punctuation">:</span> Unexpected Method Call
<span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">-</span>

<span class="token function">Save</span><span class="token punctuation">(</span>main<span class="token punctuation">.</span>Employee<span class="token punctuation">)</span>
                <span class="token number">0</span><span class="token punctuation">:</span> main<span class="token punctuation">.</span>Employee<span class="token punctuation">{</span>ID<span class="token punctuation">:</span>uuid<span class="token punctuation">.</span>UUID<span class="token punctuation">{</span><span class="token number">0x4d</span><span class="token punctuation">,</span> <span class="token number">0x8e</span><span class="token punctuation">,</span> <span class="token number">0x29</span><span class="token punctuation">,</span> <span class="token number">0x66</span><span class="token punctuation">,</span> <span class="token number">0x29</span><span class="token punctuation">,</span> <span class="token number">0xdd</span><span class="token punctuation">,</span> <span class="token number">0x4b</span><span class="token punctuation">,</span> <span class="token number">0xbe</span><span class="token punctuation">,</span> <span class="token number">0xa7</span><span class="token punctuation">,</span> <span class="token number">0x30</span><span class="token punctuation">,</span> <span class="token number">0x34</span><span class="token punctuation">,</span> <span class="token number">0xa0</span><span class="token punctuation">,</span> <span class="token number">0x7a</span><span class="token punctuation">,</span> <span class="token number">0xe7</span><span class="token punctuation">,</span> <span class="token number">0xb3</span><span class="token punctuation">,</span> <span class="token number">0x94</span><span class="token punctuation">}</span><span class="token punctuation">,</span> FirstName<span class="token punctuation">:</span><span class="token string">"John"</span><span class="token punctuation">,</span> LastName<span class="token punctuation">:</span><span class="token string">"Doe"</span><span class="token punctuation">}</span>

The closest call I have is<span class="token punctuation">:</span>

<span class="token function">Save</span><span class="token punctuation">(</span>mock<span class="token punctuation">.</span>argumentMatcher<span class="token punctuation">)</span>
                <span class="token number">0</span><span class="token punctuation">:</span> mock<span class="token punctuation">.</span>argumentMatcher<span class="token punctuation">{</span>fn<span class="token punctuation">:</span>reflect<span class="token punctuation">.</span>Value<span class="token punctuation">{</span>typ<span class="token punctuation">:</span><span class="token punctuation">(</span><span class="token operator">*</span>reflect<span class="token punctuation">.</span>rtype<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">0x12fd9e0</span><span class="token punctuation">)</span><span class="token punctuation">,</span> ptr<span class="token punctuation">:</span><span class="token punctuation">(</span>unsafe<span class="token punctuation">.</span>Pointer<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">0xc00010ce40</span><span class="token punctuation">)</span><span class="token punctuation">,</span> flag<span class="token punctuation">:</span><span class="token number">0x13</span><span class="token punctuation">}</span><span class="token punctuation">}</span>


Diff<span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">:</span> FAIL<span class="token punctuation">:</span>  <span class="token punctuation">(</span>main<span class="token punctuation">.</span>Employee<span class="token operator">=</span><span class="token punctuation">{</span>4d8e2966<span class="token operator">-</span>29dd<span class="token operator">-</span>4bbe<span class="token operator">-</span>a730<span class="token operator">-</span>34a07ae7b394 John Doe<span class="token punctuation">}</span><span class="token punctuation">)</span> not matched by <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token keyword">interface</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">[</span>recovered<span class="token punctuation">]</span>
        <span class="token builtin">panic</span><span class="token punctuation">:</span></code></pre>
<p>It becomes easy to navigate the test and fix the issue and the you could ignore multiple fields and from the struct comparison.</p>
<p>I am definitely going to use this library in my projects. This is also a great learning for me by writing and sharing this blog post.</p>
<h2 id="conclusion" tabindex="-1">Conclusion <a class="header-anchor" href="#conclusion"></a></h2>
<p>I hope this helps you to write better tests for your code when using the google uuid package. I am very keen on testing
code and finding ways to ease testing for developers. Having proper tests helps the team move faster. It also provides a
safety net to avoid accidental bug leaks or any dev mistakes.</p>
<p>There are different pros and cons to each of the methods discussed. It will depend on what works for you and what
doesn’t. For a small codebase, I don’t like using the generator function approach. I would use the <code>SetRand</code> for such
cases. For larger struct or ignoring the field comparison for some then I would also prefer the go-cmp library which
does a really good job.</p>
<p>I was curious to see if there is any simple way for unit testing. This post is my research on this topic, but I know
there may be some approaches I missed. So, I would like to hear those from others. I will definitely be happy to update
my findings with your thoughts 🙏.</p>
<hr>
<p>Thank you so much for taking the time to read my blog and sharing it with others. Your ❤️ support means a lot to me, and
I truly appreciate it. It’s people like you who inspire me to keep writing and sharing my thoughts with the world. Thank
you again for your kindness and support.</p>
<p><a href="https://blog.iamninad.com/membership">Click to become a medium member and read unlimited stories!</a></p>
<hr>
<h2 id="supporting-information" tabindex="-1">Supporting Information <a class="header-anchor" href="#supporting-information"></a></h2>
<p>A Sample Test From google/uuid package::</p>
<pre class="language-go"><code class="language-go"><span class="token comment">// No t.Parallel() used</span>
<span class="token keyword">func</span> <span class="token function">TestSetRand</span><span class="token punctuation">(</span>t <span class="token operator">*</span>testing<span class="token punctuation">.</span>T<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 myString <span class="token operator">:=</span> <span class="token string">"805-9dd6-1a877cb526c678e71d38-7122-44c0-9b7c-04e7001cc78783ac3e82-47a3-4cc3-9951-13f3339d88088f5d685a-11f7-4078-ada9-de44ad2daeb7"</span>

 <span class="token function">SetRand</span><span class="token punctuation">(</span>strings<span class="token punctuation">.</span><span class="token function">NewReader</span><span class="token punctuation">(</span>myString<span class="token punctuation">)</span><span class="token punctuation">)</span>
 uuid1 <span class="token operator">:=</span> <span class="token function">New</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
 uuid2 <span class="token operator">:=</span> <span class="token function">New</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

 <span class="token function">SetRand</span><span class="token punctuation">(</span>strings<span class="token punctuation">.</span><span class="token function">NewReader</span><span class="token punctuation">(</span>myString<span class="token punctuation">)</span><span class="token punctuation">)</span>
 uuid3 <span class="token operator">:=</span> <span class="token function">New</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
 uuid4 <span class="token operator">:=</span> <span class="token function">New</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

 <span class="token keyword">if</span> uuid1 <span class="token operator">!=</span> uuid3 <span class="token punctuation">{</span>
  t<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"expected duplicates, got %q and %q"</span><span class="token punctuation">,</span> uuid1<span class="token punctuation">,</span> uuid3<span class="token punctuation">)</span>
 <span class="token punctuation">}</span>
 <span class="token keyword">if</span> uuid2 <span class="token operator">!=</span> uuid4 <span class="token punctuation">{</span>
  t<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"expected duplicates, got %q and %q"</span><span class="token punctuation">,</span> uuid2<span class="token punctuation">,</span> uuid4<span class="token punctuation">)</span>
 <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>A sample test from golang <code>math/rand</code> package::</p>
<pre class="language-go"><code class="language-go"><span class="token comment">// No t.Parallel() used</span>
<span class="token keyword">func</span> <span class="token function">testReadUniformity</span><span class="token punctuation">(</span>t <span class="token operator">*</span>testing<span class="token punctuation">.</span>T<span class="token punctuation">,</span> n <span class="token builtin">int</span><span class="token punctuation">,</span> seed <span class="token builtin">int64</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
 r <span class="token operator">:=</span> <span class="token function">New</span><span class="token punctuation">(</span><span class="token function">NewSource</span><span class="token punctuation">(</span>seed<span class="token punctuation">)</span><span class="token punctuation">)</span>
 buf <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">byte</span><span class="token punctuation">,</span> n<span class="token punctuation">)</span>
 nRead<span class="token punctuation">,</span> err <span class="token operator">:=</span> r<span class="token punctuation">.</span><span class="token function">Read</span><span class="token punctuation">(</span>buf<span class="token punctuation">)</span>
 <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
  t<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"Read err %v"</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span>
 <span class="token punctuation">}</span>
 <span class="token keyword">if</span> nRead <span class="token operator">!=</span> n <span class="token punctuation">{</span>
  t<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"Read returned unexpected n; %d != %d"</span><span class="token punctuation">,</span> nRead<span class="token punctuation">,</span> n<span class="token punctuation">)</span>
 <span class="token punctuation">}</span>

 <span class="token comment">// Expect a uniform distribution of byte values, which lie in [0, 255].</span>
 <span class="token keyword">var</span> <span class="token punctuation">(</span>
  mean       <span class="token operator">=</span> <span class="token number">255.0</span> <span class="token operator">/</span> <span class="token number">2</span>
  stddev     <span class="token operator">=</span> <span class="token number">256.0</span> <span class="token operator">/</span> math<span class="token punctuation">.</span><span class="token function">Sqrt</span><span class="token punctuation">(</span><span class="token number">12.0</span><span class="token punctuation">)</span>
  errorScale <span class="token operator">=</span> stddev <span class="token operator">/</span> math<span class="token punctuation">.</span><span class="token function">Sqrt</span><span class="token punctuation">(</span><span class="token function">float64</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span><span class="token punctuation">)</span>
 <span class="token punctuation">)</span>

 expected <span class="token operator">:=</span> <span class="token operator">&amp;</span>statsResults<span class="token punctuation">{</span>mean<span class="token punctuation">,</span> stddev<span class="token punctuation">,</span> <span class="token number">0.10</span> <span class="token operator">*</span> errorScale<span class="token punctuation">,</span> <span class="token number">0.08</span> <span class="token operator">*</span> errorScale<span class="token punctuation">}</span>

 <span class="token comment">// Cast bytes as floats to use the common distribution-validity checks.</span>
 samples <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">float64</span><span class="token punctuation">,</span> n<span class="token punctuation">)</span>
 <span class="token keyword">for</span> i<span class="token punctuation">,</span> val <span class="token operator">:=</span> <span class="token keyword">range</span> buf <span class="token punctuation">{</span>
  samples<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">float64</span><span class="token punctuation">(</span>val<span class="token punctuation">)</span>
 <span class="token punctuation">}</span>
 <span class="token comment">// Make sure that the entire set matches the expected distribution.</span>
 <span class="token function">checkSampleDistribution</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> samples<span class="token punctuation">,</span> expected<span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token comment">// No t.Parallel() used</span>
<span class="token keyword">func</span> <span class="token function">TestReadUniformity</span><span class="token punctuation">(</span>t <span class="token operator">*</span>testing<span class="token punctuation">.</span>T<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 testBufferSizes <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span>
  <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">,</span> <span class="token number">64</span><span class="token punctuation">,</span> <span class="token number">1024</span><span class="token punctuation">,</span> <span class="token number">1</span> <span class="token operator">&lt;&lt;</span> <span class="token number">16</span><span class="token punctuation">,</span> <span class="token number">1</span> <span class="token operator">&lt;&lt;</span> <span class="token number">20</span><span class="token punctuation">,</span>
 <span class="token punctuation">}</span>
 <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> seed <span class="token operator">:=</span> <span class="token keyword">range</span> testSeeds <span class="token punctuation">{</span>
  <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> n <span class="token operator">:=</span> <span class="token keyword">range</span> testBufferSizes <span class="token punctuation">{</span>
   <span class="token function">testReadUniformity</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> n<span class="token punctuation">,</span> seed<span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
 <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre>
<h2 id="edits%3A%3A" tabindex="-1">Edits:: <a class="header-anchor" href="#edits%3A%3A"></a></h2>
<ul>
<li>Add google/go-cmp library usage as suggested by readers.</li>
</ul>

                ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Keep Watch On Sql Query In IntelliJ/Goland Or Data Grip</title>
            <link href="https://iamninad.com/posts/keep-watch-on-sql-query-in-intelli-j-goland-or-data-grip/"/>
            <updated>2023-04-17T00:00:00Z</updated>
            <id>https://iamninad.com/posts/keep-watch-on-sql-query-in-intelli-j-goland-or-data-grip/</id>
            <content type="html">
                <![CDATA[
                <p>Are you an Intellij, Goland or DataGrip User? Like me, are you running the SQL statements every time you want to see the
change reflected on the table?</p>
<p>If Yes, I found a small trick in Intellij and DataGrip that could watch your SQL query results. It was always there but
I overlooked it. Once I discovered it, it changed my life for debugging or development.</p>
<p>It’s not a trick actually 😅 but a feature built within the IntelliJ products. It could easily go ignored but let’s see
how to use it</p>
<p>When you run any query you will see the Result window below::</p>
<figure><img src="/images/keep-watch-on-sql-query-in-intelli-j-goland-or-data-grip/result-window.png" alt="Result Window"><figcaption>Result Window</figcaption></figure>
<p>You would see this clock icon in the toolbar that does all the trick. It was always there but I never thought it would
be so useful 😍</p>
<figure><img src="/images/keep-watch-on-sql-query-in-intelli-j-goland-or-data-grip/clock-icon.png" alt="Clock Icon"><figcaption>Clock Icon</figcaption></figure>
<p>When you click on it, the below options would be available. Each choice you select will refresh the query results after
the selected delay.</p>
<img src="/images/keep-watch-on-sql-query-in-intelli-j-goland-or-data-grip/predefined-options.png" alt="gif" class="Gif" />
<p>A small tip to remember is to make sure you “Pin” 📌 the result window. When you do it, you could run other queries along
with the watch window.</p>
<p>The below video shows a small demo of this feature. In the demo, I am watching the result of a SELECT query. When I
update a record it is shown in the result window without running the SELECT query again.</p>
<figure><img src="/images/keep-watch-on-sql-query-in-intelli-j-goland-or-data-grip/demo.gif" alt="Demo"><figcaption>Demo</figcaption></figure>
<p><code>5s</code> seems long? What if I want to keep the watch period lower than <code>5s</code>? You could use the <code>Custom</code> option provided.
With
this, you could also monitor your query changes at a 1s rate interval</p>
<figure><img src="/images/keep-watch-on-sql-query-in-intelli-j-goland-or-data-grip/custom.png" alt="Custom"><figcaption>Custom</figcaption></figure>
<p>Well, that's all for this post. I hope next time this small utility will come in handy for you. Don’t run the query
every time to see the change. IntelliJ tools are a powerhouse of such small utilities which are very easily ignored by
us.</p>
<p>Thanks! and Happy Coding!</p>

                ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Preventing DB Connection Leak in Golang</title>
            <link href="https://iamninad.com/posts/preventing-db-connection-leak-in-golang/"/>
            <updated>2023-04-01T00:00:00Z</updated>
            <id>https://iamninad.com/posts/preventing-db-connection-leak-in-golang/</id>
            <content type="html">
                <![CDATA[
                <h2 id="introduction" tabindex="-1">Introduction <a class="header-anchor" href="#introduction"></a></h2>
<p>In my previous blog post, <a href="https://www.iamninad.com/posts/a-billion-dollar-go-mistake/">&quot;A Billion Dollar Go Mistake&quot;</a>.
I discussed a common but naive mistake that developers make in Golang, which can lead to connection leaks.
Although I offered several ways to fix this problem, one issue still bothered both myself and my readers.
We can solve this problem by abstracting the transaction mechanism into a different layer.
Many people reached out to me to suggest this solution.</p>
<p>So, my first curiosity question I want to reason::</p>
<blockquote>
<h2 id="do-we-really-need-a-transaction-layer%3F" tabindex="-1">Do we really need a Transaction layer? <a class="header-anchor" href="#do-we-really-need-a-transaction-layer%3F"></a></h2>
</blockquote>
<p>I read several other blogs and GitHub codes. I noticed that many of them were great but did not include tests to prove
that the abstraction layer works. But, we cannot confirm that the transaction layer works without tests. A connection
leak may occur, and we cannot detect it by examining the code.</p>
<p>This led me to another important question::</p>
<blockquote>
<h2 id="how-can-i-prove-that-the-new-layer-have-no-connection-leask%3F" tabindex="-1">How can I prove that the new layer have no connection leask? <a class="header-anchor" href="#how-can-i-prove-that-the-new-layer-have-no-connection-leask%3F"></a></h2>
</blockquote>
<p>Testing is the only way to verify whether something works as expected.
I decided to start with two straightforward options that came to my mind::</p>
<p>1 - I will run some queries that change the table and verify that the code commits the data to the database.
2 - I will some mechanisms that expose the connection information. I could verify that the code closes the connections at
the end.</p>
<p>The first approach is simple, and I have used it many times in my projects 😅. But, the second approach is completely
unknown to me 👾. When I face difficulties in understanding how things work, I usually look at the source code of the
language.</p>
<p>To resolve my problem, I looked for help in the standard database library code of Golang.
I found something that could help me:: the <code>DBStats</code> struct.</p>
<pre class="language-go"><code class="language-go"><span class="token comment">// DBStats contains database statistics.</span>
<span class="token keyword">type</span> DBStats <span class="token keyword">struct</span> <span class="token punctuation">{</span>
  MaxOpenConnections <span class="token builtin">int</span> <span class="token comment">// Maximum number of open connections to the database.</span>
  
  <span class="token comment">// Pool Status</span>
  OpenConnections <span class="token builtin">int</span> <span class="token comment">// The number of established connections both in use and idle.</span>
  InUse           <span class="token builtin">int</span> <span class="token comment">// The number of connections currently in use.</span>
  Idle            <span class="token builtin">int</span> <span class="token comment">// The number of idle connections.</span>
  
  <span class="token comment">// Counters</span>
  WaitCount         <span class="token builtin">int64</span>         <span class="token comment">// The total number of connections waited for.</span>
  WaitDuration      time<span class="token punctuation">.</span>Duration <span class="token comment">// The total time blocked waiting for a new connection.</span>
  MaxIdleClosed     <span class="token builtin">int64</span> <span class="token comment">// The total number of connections closed due to SetMaxIdleConns.</span>
  MaxIdleTimeClosed <span class="token builtin">int64</span> <span class="token comment">// The total number of connections closed due to SetConnMaxIdleTime.</span>
  MaxLifetimeClosed <span class="token builtin">int64</span> <span class="token comment">// The total number of connections closed due to SetConnMaxLifetime.</span>
<span class="token punctuation">}</span></code></pre>
<p>This is precisely the solution I was searching for. Upon completion of the transaction, the <code>MaxOpenConnections</code>
and <code>InUse</code> counts should be <code>0</code>.
If this is not the case, it indicates a potential leak in the abstraction layer.</p>
<p>I am thrilled to have found the ideal solution to address the second scenario 🎉</p>
<p>To access the <code>DBStats</code>, we can use the <code>Stats()</code> method on the <code>sql.DB</code> instance, as shown below::</p>
<pre class="language-go"><code class="language-go">db<span class="token punctuation">,</span> <span class="token boolean">_</span> <span class="token operator">:=</span> sqlx<span class="token punctuation">.</span><span class="token function">Open</span><span class="token punctuation">(</span><span class="token string">"postgres"</span><span class="token punctuation">,</span> <span class="token string">"postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable"</span><span class="token punctuation">)</span>
db<span class="token punctuation">.</span><span class="token function">Stats</span><span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre>
<p>The source code for the <code>Stats()</code> method is below. You can read more about it's working and how go code records the
information by following the source code <a href="https://github.com/golang/go/blob/master/src/database/sql/sql.go#L1155">here</a></p>
<pre class="language-go"><code class="language-go"><span class="token comment">// Stats returns database statistics.</span>
<span class="token keyword">func</span> <span class="token punctuation">(</span>db <span class="token operator">*</span>DB<span class="token punctuation">)</span> <span class="token function">Stats</span><span class="token punctuation">(</span><span class="token punctuation">)</span> DBStats <span class="token punctuation">{</span>
  wait <span class="token operator">:=</span> db<span class="token punctuation">.</span>waitDuration<span class="token punctuation">.</span><span class="token function">Load</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  
  db<span class="token punctuation">.</span>mu<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token keyword">defer</span> db<span class="token punctuation">.</span>mu<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  
  stats <span class="token operator">:=</span> DBStats<span class="token punctuation">{</span>
    MaxOpenConnections<span class="token punctuation">:</span> db<span class="token punctuation">.</span>maxOpen<span class="token punctuation">,</span>
    
    Idle<span class="token punctuation">:</span>            <span class="token function">len</span><span class="token punctuation">(</span>db<span class="token punctuation">.</span>freeConn<span class="token punctuation">)</span><span class="token punctuation">,</span>
    OpenConnections<span class="token punctuation">:</span> db<span class="token punctuation">.</span>numOpen<span class="token punctuation">,</span>
    InUse<span class="token punctuation">:</span>           db<span class="token punctuation">.</span>numOpen <span class="token operator">-</span> <span class="token function">len</span><span class="token punctuation">(</span>db<span class="token punctuation">.</span>freeConn<span class="token punctuation">)</span><span class="token punctuation">,</span>
    
    WaitCount<span class="token punctuation">:</span>         db<span class="token punctuation">.</span>waitCount<span class="token punctuation">,</span>
    WaitDuration<span class="token punctuation">:</span>      time<span class="token punctuation">.</span><span class="token function">Duration</span><span class="token punctuation">(</span>wait<span class="token punctuation">)</span><span class="token punctuation">,</span>
    MaxIdleClosed<span class="token punctuation">:</span>     db<span class="token punctuation">.</span>maxIdleClosed<span class="token punctuation">,</span>
    MaxIdleTimeClosed<span class="token punctuation">:</span> db<span class="token punctuation">.</span>maxIdleTimeClosed<span class="token punctuation">,</span>
    MaxLifetimeClosed<span class="token punctuation">:</span> db<span class="token punctuation">.</span>maxLifetimeClosed<span class="token punctuation">,</span>
  <span class="token punctuation">}</span>
  
  <span class="token keyword">return</span> stats
<span class="token punctuation">}</span></code></pre>
<p>All this is enough for me to implement the Transaction Layer. So, Let's delve into the code now. But before we get started, let me introduce you to some of the libraries that I will be
using in the code::</p>
<ul>
<li><a href="https://github.com/jmoiron/sqlx">Sqlx</a></li>
<li><a href="https://github.com/ory/dockertest">dockertest</a></li>
<li><a href="https://github.com/stretchr/testify">testify</a></li>
<li><a href="https://github.com/DATA-DOG/go-sqlmock">go-sqlmock</a></li>
</ul>
<br />
<blockquote>
<h2 id="interestingly%2C-it's-hard-to-reproduce-the-connection-leak-scenario-in-a-transaction-layer.-trust-me%2C-i've-tried-and-failed.-%F0%9F%98%82" tabindex="-1">Interestingly, it's hard to reproduce the connection leak scenario in a transaction layer. Trust me, I've tried and failed. 😂 <a class="header-anchor" href="#interestingly%2C-it's-hard-to-reproduce-the-connection-leak-scenario-in-a-transaction-layer.-trust-me%2C-i've-tried-and-failed.-%F0%9F%98%82"></a></h2>
</blockquote>
<p>I'll show how to test the old code using <code>DBStats</code> assertions. With this example, people who will not abstract
the transaction layer could update their tests to avoid any connection leaks.
Later on, we'll explore how to extract the transaction layer and test it.</p>
<pre class="language-go"><code class="language-go"><span class="token keyword">package</span> apptest

<span class="token keyword">import</span> <span class="token punctuation">(</span>
  <span class="token string">"context"</span>
  <span class="token string">"database/sql"</span>
  <span class="token string">"github.com/jmoiron/sqlx"</span>
<span class="token punctuation">)</span>

<span class="token keyword">type</span> Subscription <span class="token keyword">struct</span> <span class="token punctuation">{</span>
  ID         <span class="token builtin">int64</span>        <span class="token string">`db:"id"`</span>
  Status     <span class="token builtin">string</span>       <span class="token string">`db:"status"`</span>
  CanceledAt sql<span class="token punctuation">.</span>NullTime <span class="token string">`db:"canceled_at"`</span>
<span class="token punctuation">}</span>

<span class="token comment">// ------------------------------ Repository ------------------------------</span>

<span class="token keyword">type</span> srepo <span class="token keyword">struct</span> <span class="token punctuation">{</span>
<span class="token punctuation">}</span>

<span class="token comment">// GetSubscription fetches the subscription by id</span>
<span class="token keyword">func</span> <span class="token punctuation">(</span>r <span class="token operator">*</span>srepo<span class="token punctuation">)</span> <span class="token function">GetSubscription</span><span class="token punctuation">(</span>tx <span class="token operator">*</span>sqlx<span class="token punctuation">.</span>Tx<span class="token punctuation">,</span> id <span class="token builtin">int64</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>Subscription<span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">var</span> sub Subscription
  err <span class="token operator">:=</span> tx<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>sub<span class="token punctuation">,</span> <span class="token string">"SELECT * FROM subscription WHERE id = $1"</span><span class="token punctuation">,</span> id<span class="token punctuation">)</span>
  <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> sub<span class="token punctuation">,</span> err
  <span class="token punctuation">}</span>

  <span class="token keyword">return</span> sub<span class="token punctuation">,</span> <span class="token boolean">nil</span>
<span class="token punctuation">}</span>

<span class="token comment">// CancelSubscription cancels a given subscription by setting canceled_at to now()</span>
<span class="token keyword">func</span> <span class="token punctuation">(</span>r <span class="token operator">*</span>srepo<span class="token punctuation">)</span> <span class="token function">CancelSubscription</span><span class="token punctuation">(</span>tx <span class="token operator">*</span>sqlx<span class="token punctuation">.</span>Tx<span class="token punctuation">,</span> id <span class="token builtin">int64</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>Subscription<span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">var</span> sub Subscription
  err <span class="token operator">:=</span> tx<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>sub<span class="token punctuation">,</span> <span class="token string">"UPDATE subscription SET canceled_at = NOW(), status='canceled' WHERE id = $1 RETURNING *"</span><span class="token punctuation">,</span> id<span class="token punctuation">)</span>
  <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> sub<span class="token punctuation">,</span> err
  <span class="token punctuation">}</span>

  <span class="token keyword">return</span> sub<span class="token punctuation">,</span> <span class="token boolean">nil</span>
<span class="token punctuation">}</span>

<span class="token comment">// ------------------------------ Service ------------------------------</span>

<span class="token keyword">type</span> Service <span class="token keyword">struct</span> <span class="token punctuation">{</span>
  db   <span class="token operator">*</span>sqlx<span class="token punctuation">.</span>DB
  repo <span class="token operator">*</span>srepo
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token function">NewService</span><span class="token punctuation">(</span>db <span class="token operator">*</span>sqlx<span class="token punctuation">.</span>DB<span class="token punctuation">,</span> repo <span class="token operator">*</span>srepo<span class="token punctuation">)</span> <span class="token operator">*</span>Service <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token operator">&amp;</span>Service<span class="token punctuation">{</span>repo<span class="token punctuation">:</span> repo<span class="token punctuation">,</span> db<span class="token punctuation">:</span> db<span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>s <span class="token operator">*</span>Service<span class="token punctuation">)</span> <span class="token function">CancelSubscription</span><span class="token punctuation">(</span>ctx context<span class="token punctuation">.</span>Context<span class="token punctuation">,</span> id <span class="token builtin">int64</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token operator">*</span>Subscription<span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  tx<span class="token punctuation">,</span> err <span class="token operator">:=</span> s<span class="token punctuation">.</span>db<span class="token punctuation">.</span><span class="token function">BeginTxx</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> <span class="token boolean">nil</span><span class="token punctuation">)</span>
  <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> err
  <span class="token punctuation">}</span>

  <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// !!! This would not work if the subscriptions is already canceled </span>
    <span class="token comment">// and the error is not returned</span>
    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
      <span class="token boolean">_</span> <span class="token operator">=</span> tx<span class="token punctuation">.</span><span class="token function">Rollback</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
      <span class="token keyword">return</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

  sub<span class="token punctuation">,</span> err <span class="token operator">:=</span> s<span class="token punctuation">.</span>repo<span class="token punctuation">.</span><span class="token function">GetSubscription</span><span class="token punctuation">(</span>tx<span class="token punctuation">,</span> id<span class="token punctuation">)</span>
  <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> err
  <span class="token punctuation">}</span>

  <span class="token keyword">if</span> sub<span class="token punctuation">.</span>Status <span class="token operator">!=</span> <span class="token string">"active"</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token operator">&amp;</span>sub<span class="token punctuation">,</span> <span class="token boolean">nil</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">if</span> sub<span class="token punctuation">.</span>CanceledAt<span class="token punctuation">.</span>Valid <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token operator">&amp;</span>sub<span class="token punctuation">,</span> <span class="token boolean">nil</span>
  <span class="token punctuation">}</span>

  sub<span class="token punctuation">,</span> err <span class="token operator">=</span> s<span class="token punctuation">.</span>repo<span class="token punctuation">.</span><span class="token function">CancelSubscription</span><span class="token punctuation">(</span>tx<span class="token punctuation">,</span> id<span class="token punctuation">)</span>
  <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> err
  <span class="token punctuation">}</span>

  err <span class="token operator">=</span> tx<span class="token punctuation">.</span><span class="token function">Commit</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

  <span class="token keyword">return</span> <span class="token operator">&amp;</span>sub<span class="token punctuation">,</span> err
<span class="token punctuation">}</span></code></pre>
<h2 id="what's-wrong-with-the-above-code%3F" tabindex="-1">What's wrong with the above code? <a class="header-anchor" href="#what's-wrong-with-the-above-code%3F"></a></h2>
<p>When the subscription is already cancelled it will return without error.
When the function returns without error the connection is neither rollback nor commits.
This causes the connection leak.</p>
<p>Below is the integration test to see how we can catch the leak.</p>
<pre class="language-go"><code class="language-go"><span class="token keyword">func</span> <span class="token function">Test_ConnectionLeak</span><span class="token punctuation">(</span>t <span class="token operator">*</span>testing<span class="token punctuation">.</span>T<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  pg<span class="token punctuation">,</span> err <span class="token operator">:=</span> apptest<span class="token punctuation">.</span><span class="token function">StartTestPostgres</span><span class="token punctuation">(</span>t<span class="token punctuation">)</span> <span class="token comment">// Please use the source code to learn more about this code</span>
  require<span class="token punctuation">.</span><span class="token function">NoError</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> err<span class="token punctuation">)</span>
  
  <span class="token boolean">_</span><span class="token punctuation">,</span> err <span class="token operator">=</span> pg<span class="token punctuation">.</span>DB<span class="token punctuation">.</span><span class="token function">Exec</span><span class="token punctuation">(</span><span class="token string">"CREATE TABLE IF NOT EXISTS subscription (id serial PRIMARY KEY, status varchar(25) NOT NULL, canceled_at timestamp NULL)"</span><span class="token punctuation">)</span>
  require<span class="token punctuation">.</span><span class="token function">NoError</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> err<span class="token punctuation">)</span>
  
  <span class="token boolean">_</span><span class="token punctuation">,</span> err <span class="token operator">=</span> pg<span class="token punctuation">.</span>DB<span class="token punctuation">.</span><span class="token function">Exec</span><span class="token punctuation">(</span><span class="token string">"INSERT INTO subscription (status, canceled_at) VALUES ('active', NULL)"</span><span class="token punctuation">)</span>
  require<span class="token punctuation">.</span><span class="token function">NoError</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> err<span class="token punctuation">)</span>
  
  <span class="token boolean">_</span><span class="token punctuation">,</span> err <span class="token operator">=</span> pg<span class="token punctuation">.</span>DB<span class="token punctuation">.</span><span class="token function">Exec</span><span class="token punctuation">(</span><span class="token string">"INSERT INTO subscription (status, canceled_at) VALUES ('canceled', '2023-02-02 01:00:00')"</span><span class="token punctuation">)</span>
  require<span class="token punctuation">.</span><span class="token function">NoError</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> err<span class="token punctuation">)</span>
  
  subscription<span class="token punctuation">,</span> err <span class="token operator">:=</span> <span class="token function">NewService</span><span class="token punctuation">(</span>pg<span class="token punctuation">.</span>DB<span class="token punctuation">,</span> <span class="token operator">&amp;</span>srepo<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">CancelSubscription</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">Background</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span>
  require<span class="token punctuation">.</span><span class="token function">NoError</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> err<span class="token punctuation">)</span>
  
  stats <span class="token operator">:=</span> pg<span class="token punctuation">.</span>DB<span class="token punctuation">.</span><span class="token function">Stats</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  require<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> stats<span class="token punctuation">.</span>InUse<span class="token punctuation">,</span> <span class="token string">"expected no connections in use"</span><span class="token punctuation">)</span>
  require<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> stats<span class="token punctuation">.</span>MaxOpenConnections<span class="token punctuation">,</span> <span class="token string">"expected no max open connection"</span><span class="token punctuation">)</span>
  
  require<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> <span class="token string">"canceled"</span><span class="token punctuation">,</span> subscription<span class="token punctuation">.</span>Status<span class="token punctuation">)</span>
  require<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> <span class="token string">"2023-02-02 01:00:00 +0000 +0000"</span><span class="token punctuation">,</span> subscription<span class="token punctuation">.</span>CanceledAt<span class="token punctuation">.</span>Time<span class="token punctuation">.</span><span class="token function">String</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span></code></pre>
<p>I am using an integration test here. I connect to a Postgres DB instance in docker and run the test.
From the test result below you could see that the code has a transaction problem. The actual count <code>InUse</code> is <code>1</code>.
The connection is not closed at the end of the function call. This is what we will solve using the transaction
abstraction layer in the next section.</p>
<pre class="language-bash"><code class="language-bash"><span class="token operator">==</span><span class="token operator">=</span> RUN   Test_ConnectionLeak
    service-connection-leak_test.go:27: 
         Error Trace: /pkg/service-connection-leak_test.go:27
         Error:       Not equal: 
                      expected: <span class="token number">0</span>
                      actual  <span class="token builtin class-name">:</span> <span class="token number">1</span>
         Test:        Test_ConnectionLeak
         Messages:    expected no connections <span class="token keyword">in</span> use
--- FAIL: Test_ConnectionLeak <span class="token punctuation">(</span><span class="token number">6</span>.69s<span class="token punctuation">)</span>

Expected :0
Actual   :1
<span class="token operator">&lt;</span>Click to see difference<span class="token operator">></span>

FAIL</code></pre>
<h2 id="extracting-the-transaction-layer" tabindex="-1">Extracting the Transaction Layer <a class="header-anchor" href="#extracting-the-transaction-layer"></a></h2>
<p>To address the connection leak issue, one way could be to fix what is failing. Close the connection by manually testing
the service and then reviewing the code. But that same issue could creep in again in future.
The right way is to extract a transaction layer.
The idea behind this extraction is simple:: we provide a public method</p>
<pre class="language-go"><code class="language-go"><span class="token keyword">func</span> <span class="token function">InTx</span><span class="token punctuation">(</span>ctx context<span class="token punctuation">.</span>Context<span class="token punctuation">,</span> db <span class="token operator">*</span>sqlx<span class="token punctuation">.</span>DB<span class="token punctuation">,</span> txFunc <span class="token keyword">func</span> <span class="token punctuation">(</span><span class="token operator">*</span>TxWrap<span class="token punctuation">)</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>err <span class="token builtin">error</span><span class="token punctuation">)</span></code></pre>
<p>which accepts the transaction-based business logic in the <code>txFunc</code> parameter.</p>
<p>With this approach, the developer no longer has to manually handle transactions, as the <code>InTx</code> method abstracts the
transaction mechanism away from the business logic.
By passing the <code>txFunc</code> parameter to <code>InTx</code>, the developer can focus on the actual business operations, without worrying
about the underlying transaction management.</p>
<blockquote>
<p>I am keeping the code simple and avoiding any complications for blogging purposes.</p>
</blockquote>
<pre class="language-go"><code class="language-go"><span class="token keyword">package</span> db

<span class="token keyword">import</span> <span class="token punctuation">(</span>
  <span class="token string">"context"</span>
  <span class="token string">"database/sql"</span>
  <span class="token string">"github.com/jmoiron/sqlx"</span>
<span class="token punctuation">)</span>

<span class="token comment">// TxWrap is a wrapper around sqlx.Tx that adds a context</span>
<span class="token comment">// and redirects calls to methods like Get, Select to GetContext and SelectContext</span>
<span class="token comment">// with the context it wraps.</span>
<span class="token keyword">type</span> TxWrap <span class="token keyword">struct</span> <span class="token punctuation">{</span>
  tx  <span class="token operator">*</span>sqlx<span class="token punctuation">.</span>Tx        <span class="token comment">// underlying transaction</span>
  ctx context<span class="token punctuation">.</span>Context <span class="token comment">// context to use for all calls</span>
<span class="token punctuation">}</span>

<span class="token comment">// Get is a wrapper around sqlx.Tx.GetContext</span>
<span class="token comment">// that uses the context it wraps.</span>
<span class="token keyword">func</span> <span class="token punctuation">(</span>tx <span class="token operator">*</span>TxWrap<span class="token punctuation">)</span> <span class="token function">Get</span><span class="token punctuation">(</span>dest <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> query <span class="token builtin">string</span><span class="token punctuation">,</span> args <span class="token operator">...</span><span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> tx<span class="token punctuation">.</span>tx<span class="token punctuation">.</span><span class="token function">GetContext</span><span class="token punctuation">(</span>tx<span class="token punctuation">.</span>ctx<span class="token punctuation">,</span> dest<span class="token punctuation">,</span> query<span class="token punctuation">,</span> args<span class="token operator">...</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token comment">// Select is a wrapper around sqlx.Tx.SelectContext</span>
<span class="token comment">// that uses the context it wraps.</span>
<span class="token keyword">func</span> <span class="token punctuation">(</span>tx <span class="token operator">*</span>TxWrap<span class="token punctuation">)</span> <span class="token function">Select</span><span class="token punctuation">(</span>dest <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> query <span class="token builtin">string</span><span class="token punctuation">,</span> args <span class="token operator">...</span><span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> tx<span class="token punctuation">.</span>tx<span class="token punctuation">.</span><span class="token function">SelectContext</span><span class="token punctuation">(</span>tx<span class="token punctuation">.</span>ctx<span class="token punctuation">,</span> dest<span class="token punctuation">,</span> query<span class="token punctuation">,</span> args<span class="token operator">...</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token comment">// IMPLEMENT OTHER RELATED sqlx Methods to use wrapped context</span>

<span class="token comment">// InTx executes a function in a transaction.</span>
<span class="token comment">// If the function returns an error, the transaction is rolled back.</span>
<span class="token comment">// If the function panics, the transaction is rolled back and the panic is re-raised.</span>
<span class="token comment">// If the function returns nil, the transaction is committed.</span>
<span class="token keyword">func</span> <span class="token function">InTx</span><span class="token punctuation">(</span>ctx context<span class="token punctuation">.</span>Context<span class="token punctuation">,</span> db <span class="token operator">*</span>sqlx<span class="token punctuation">.</span>DB<span class="token punctuation">,</span> txFunc <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token operator">*</span>TxWrap<span class="token punctuation">)</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>err <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  ctx<span class="token punctuation">,</span> cancel <span class="token operator">:=</span> context<span class="token punctuation">.</span><span class="token function">WithCancel</span><span class="token punctuation">(</span>ctx<span class="token punctuation">)</span>
  <span class="token keyword">defer</span> <span class="token function">cancel</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

  tx<span class="token punctuation">,</span> err <span class="token operator">:=</span> db<span class="token punctuation">.</span><span class="token function">BeginTxx</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> <span class="token boolean">nil</span><span class="token punctuation">)</span>
  <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> err
  <span class="token punctuation">}</span>

  txWrap <span class="token operator">:=</span> <span class="token operator">&amp;</span>TxWrap<span class="token punctuation">{</span>
    tx<span class="token punctuation">:</span>  tx<span class="token punctuation">,</span>
    ctx<span class="token punctuation">:</span> ctx<span class="token punctuation">,</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> p <span class="token operator">:=</span> <span class="token function">recover</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> p <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
      <span class="token boolean">_</span> <span class="token operator">=</span> txWrap<span class="token punctuation">.</span>tx<span class="token punctuation">.</span><span class="token function">Rollback</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
      <span class="token function">panic</span><span class="token punctuation">(</span>p<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
      <span class="token boolean">_</span> <span class="token operator">=</span> txWrap<span class="token punctuation">.</span>tx<span class="token punctuation">.</span><span class="token function">Rollback</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
      <span class="token keyword">return</span>
    <span class="token punctuation">}</span>
    err <span class="token operator">=</span> txWrap<span class="token punctuation">.</span>tx<span class="token punctuation">.</span><span class="token function">Commit</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

  <span class="token keyword">return</span> <span class="token function">txFunc</span><span class="token punctuation">(</span>txWrap<span class="token punctuation">)</span>
<span class="token punctuation">}</span></code></pre>
<p>The <code>InTx</code> wraps around the actual sqlx.Tx in <code>TxWrap</code> struct and encapsulates the transaction management logic within
the method. The <code>InTx</code> takes care of calling <code>Begin, Commit and Rollback</code>.</p>
<p>The <code>TxWrap</code> struct also contains a derived cancel context (<code>ctx</code>), which was discussed in my previous post to ensure
the context cancellation happens at the end of the method call.
Inside the <code>InTx</code> method, we have a <code>defer</code> block that handles three possible outcomes of the transaction
logic::</p>
<p>1 - Panic:: In case of any unhandled exception, the transaction will automatically roll back.
2 - Error:: If any error occurs during the transaction, it will also be rolled back.
3 - Success:: If everything goes as expected, the transaction will be committed.</p>
<p>To provide further safety, we also implement the same <code>Get</code> and <code>Select</code> functions as in the sqlx library, but we proxy
the
calls to the context version of these functions. This ensures that any in-process requests are cancelled if the context
is cancelled, if a client cancels an HTTP request.</p>
<p>Now the real excitement begins !!! TESTS !!! 🚀 🥹</p>
<img src="https://media0.giphy.com/media/v1.Y2lkPTc5MGI3NjExNzRjZjc2YzAxNWNhYzE0ODdlNjQ1MzNlZjg4MzkxNTRjMWJjMDgwNCZjdD1n/MNmyTin5qt5LSXirxd/giphy.gif" alt="gif" class="Gif" />
<p>I am doing both approaches, the Unit test and the Integration Test. It is up to you what you want to use. My own
preference is the Integration test. They mimic behaviour close to real infrastructure.</p>
<h3 id="unit-test" tabindex="-1">Unit Test <a class="header-anchor" href="#unit-test"></a></h3>
<p>For the unit test, I am using <code>sqlmock</code>. I set up the expectation as per the 3 behaviours of our code and assert if the
expectations are met. I also check the connection count resets <code>0</code> at the end. Unit Tests are pretty fast so we are also
doing <code>t.Parallel</code> and initiating a new sqlmock for every test.</p>
<pre class="language-go"><code class="language-go"><span class="token comment">// ------------------------------ UNIT Test ------------------------------</span>
<span class="token keyword">func</span> <span class="token function">Test_Unit</span><span class="token punctuation">(</span>t <span class="token operator">*</span>testing<span class="token punctuation">.</span>T<span class="token punctuation">)</span> <span class="token punctuation">{</span>
	t<span class="token punctuation">.</span><span class="token function">Parallel</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
	
  tests <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token keyword">struct</span> <span class="token punctuation">{</span>
    name      <span class="token builtin">string</span>
    fn        <span class="token keyword">func</span> <span class="token punctuation">(</span>tx <span class="token operator">*</span>TxWrap<span class="token punctuation">)</span> <span class="token builtin">error</span>
    setup     <span class="token keyword">func</span> <span class="token punctuation">(</span>mock sqlmock<span class="token punctuation">.</span>Sqlmock<span class="token punctuation">)</span>
    wantErr   <span class="token builtin">bool</span>
    wantPanic <span class="token builtin">bool</span>
  <span class="token punctuation">}</span><span class="token punctuation">{</span>
    <span class="token punctuation">{</span>
      name<span class="token punctuation">:</span> <span class="token string">"success path"</span><span class="token punctuation">,</span>
      fn<span class="token punctuation">:</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>tx <span class="token operator">*</span>TxWrap<span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span>
          <span class="token keyword">return</span> <span class="token boolean">nil</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      setup<span class="token punctuation">:</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>mock sqlmock<span class="token punctuation">.</span>Sqlmock<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        mock<span class="token punctuation">.</span><span class="token function">ExpectBegin</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        mock<span class="token punctuation">.</span><span class="token function">ExpectCommit</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
      name<span class="token punctuation">:</span> <span class="token string">"failure path"</span><span class="token punctuation">,</span>
      fn<span class="token punctuation">:</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>tx <span class="token operator">*</span>TxWrap<span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span>
          <span class="token keyword">return</span> errors<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token string">"some error"</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      setup<span class="token punctuation">:</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>mock sqlmock<span class="token punctuation">.</span>Sqlmock<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        mock<span class="token punctuation">.</span><span class="token function">ExpectBegin</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        mock<span class="token punctuation">.</span><span class="token function">ExpectRollback</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      wantErr<span class="token punctuation">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
      name<span class="token punctuation">:</span> <span class="token string">"panic"</span><span class="token punctuation">,</span>
      fn<span class="token punctuation">:</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>tx <span class="token operator">*</span>TxWrap<span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span>
        <span class="token function">panic</span><span class="token punctuation">(</span><span class="token string">"some panic"</span><span class="token punctuation">)</span>
        <span class="token keyword">return</span> <span class="token boolean">nil</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      setup<span class="token punctuation">:</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>mock sqlmock<span class="token punctuation">.</span>Sqlmock<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        mock<span class="token punctuation">.</span><span class="token function">ExpectBegin</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        mock<span class="token punctuation">.</span><span class="token function">ExpectRollback</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      wantPanic<span class="token punctuation">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> test <span class="token operator">:=</span> <span class="token keyword">range</span> tests <span class="token punctuation">{</span>
    test <span class="token operator">:=</span> test
    t<span class="token punctuation">.</span><span class="token function">Run</span><span class="token punctuation">(</span>test<span class="token punctuation">.</span>name<span class="token punctuation">,</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>t <span class="token operator">*</span>testing<span class="token punctuation">.</span>T<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      t<span class="token punctuation">.</span><span class="token function">Parallel</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
      
      db<span class="token punctuation">,</span> mock<span class="token punctuation">,</span> err <span class="token operator">:=</span> sqlmock<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
      require<span class="token punctuation">.</span><span class="token function">NoError</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> err<span class="token punctuation">)</span>
      
      dbx <span class="token operator">:=</span> sqlx<span class="token punctuation">.</span><span class="token function">NewDb</span><span class="token punctuation">(</span>db<span class="token punctuation">,</span> <span class="token string">"sqlmock"</span><span class="token punctuation">)</span>
      
	    <span class="token keyword">if</span> test<span class="token punctuation">.</span>setup <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        test<span class="token punctuation">.</span><span class="token function">setup</span><span class="token punctuation">(</span>mock<span class="token punctuation">)</span>
      <span class="token punctuation">}</span>
      
      <span class="token comment">// Only add this defer when we expect panic to take over the </span>
      <span class="token comment">// panic recovery and see if there is a valid error</span>
      <span class="token keyword">if</span> test<span class="token punctuation">.</span>wantPanic <span class="token punctuation">{</span>
        <span class="token keyword">defer</span> <span class="token keyword">func</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            require<span class="token punctuation">.</span><span class="token function">NotNil</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> <span class="token function">recover</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span>
      
      err <span class="token operator">=</span> <span class="token function">InTx</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">Background</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> dbx<span class="token punctuation">,</span> test<span class="token punctuation">.</span>fn<span class="token punctuation">)</span>
      
      require<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> test<span class="token punctuation">.</span>wantErr<span class="token punctuation">,</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span><span class="token punctuation">)</span>
      require<span class="token punctuation">.</span><span class="token function">NoError</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> mock<span class="token punctuation">.</span><span class="token function">ExpectationsWereMet</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
      
      stats <span class="token operator">:=</span> dbx<span class="token punctuation">.</span><span class="token function">Stats</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
      require<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> stats<span class="token punctuation">.</span>InUse<span class="token punctuation">)</span>
      require<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> stats<span class="token punctuation">.</span>MaxOpenConnections<span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="integration-test" tabindex="-1">Integration Test <a class="header-anchor" href="#integration-test"></a></h3>
<p>For the Integration test below, I am using Postgres DB. I create a dummy <code>Employees</code> table first. Then I execute some
inserts and selects statements for different scenario. In the end, check if the layer closes the connection for every
test.</p>
<p>A point to note here is that I am not doing <code>t.Parallel</code>. The shared connection between tests in the parallel run would
be a problem. The <code>InUse</code> and <code>MaxOpenConnections</code> will never be <code>0</code>.
It is up to you how you want to do it. You can do a similar thing we did in the Unit test to create a
<strong>separate connection</strong> for every test::</p>
<pre class="language-go"><code class="language-go"><span class="token comment">// ---------------------------------- INTEGRATION TEST -------------------------------------</span>
<span class="token keyword">type</span> Employee <span class="token keyword">struct</span> <span class="token punctuation">{</span>
  ID   <span class="token builtin">int64</span>  <span class="token string">`db:"id"`</span>
  Name <span class="token builtin">string</span> <span class="token string">`db:"name"`</span>
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token function">Test_Integration</span><span class="token punctuation">(</span>t <span class="token operator">*</span>testing<span class="token punctuation">.</span>T<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  pg<span class="token punctuation">,</span> err <span class="token operator">:=</span> apptest<span class="token punctuation">.</span><span class="token function">StartTestPostgres</span><span class="token punctuation">(</span>t<span class="token punctuation">)</span>
  require<span class="token punctuation">.</span><span class="token function">NoError</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> err<span class="token punctuation">)</span>

  <span class="token boolean">_</span><span class="token punctuation">,</span> err <span class="token operator">=</span> pg<span class="token punctuation">.</span>DB<span class="token punctuation">.</span><span class="token function">Exec</span><span class="token punctuation">(</span><span class="token string">"CREATE TABLE IF NOT EXISTS employee (id serial PRIMARY KEY, name varchar(25) NOT NULL)"</span><span class="token punctuation">)</span>
  require<span class="token punctuation">.</span><span class="token function">NoError</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> err<span class="token punctuation">)</span>

  tests <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token keyword">struct</span> <span class="token punctuation">{</span>
    name      <span class="token builtin">string</span>
    txfunc    <span class="token keyword">func</span> <span class="token punctuation">(</span>tx <span class="token operator">*</span>TxWrap<span class="token punctuation">)</span> <span class="token builtin">error</span>
    wantErr   <span class="token builtin">bool</span>
    wantPanic <span class="token builtin">bool</span>
  <span class="token punctuation">}</span><span class="token punctuation">{</span>
    <span class="token punctuation">{</span>
      name<span class="token punctuation">:</span> <span class="token string">"success path"</span><span class="token punctuation">,</span>
      txfunc<span class="token punctuation">:</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>tx <span class="token operator">*</span>TxWrap<span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span>
        <span class="token boolean">_</span><span class="token punctuation">,</span> err <span class="token operator">:=</span> tx<span class="token punctuation">.</span><span class="token function">Exec</span><span class="token punctuation">(</span><span class="token string">"INSERT INTO employee (name) VALUES ('John Doe')"</span><span class="token punctuation">)</span>
        <span class="token keyword">return</span> err
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
      name<span class="token punctuation">:</span> <span class="token string">"failure path"</span><span class="token punctuation">,</span>
      txfunc<span class="token punctuation">:</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>tx <span class="token operator">*</span>TxWrap<span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span>
        <span class="token keyword">var</span> employee Employee
        err <span class="token operator">:=</span> tx<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>employee<span class="token punctuation">,</span> <span class="token string">"SELECT * FROM employee WHERE id = $1"</span><span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">)</span>
        <span class="token keyword">return</span> err
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      wantErr<span class="token punctuation">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
      name<span class="token punctuation">:</span> <span class="token string">"panic"</span><span class="token punctuation">,</span>
      txfunc<span class="token punctuation">:</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>tx <span class="token operator">*</span>TxWrap<span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span>
        <span class="token function">panic</span><span class="token punctuation">(</span><span class="token string">"some panic"</span><span class="token punctuation">)</span>
        
        <span class="token keyword">return</span> <span class="token boolean">nil</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      wantPanic<span class="token punctuation">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> test <span class="token operator">:=</span> <span class="token keyword">range</span> tests <span class="token punctuation">{</span>
    test <span class="token operator">:=</span> test
    t<span class="token punctuation">.</span><span class="token function">Run</span><span class="token punctuation">(</span>test<span class="token punctuation">.</span>name<span class="token punctuation">,</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>t <span class="token operator">*</span>testing<span class="token punctuation">.</span>T<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token comment">// Wrap the function in a defer to catch panics</span>
      <span class="token comment">// and assert that the panic is not nil.</span>
      <span class="token keyword">defer</span> <span class="token keyword">func</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> test<span class="token punctuation">.</span>wantPanic <span class="token punctuation">{</span>
          require<span class="token punctuation">.</span><span class="token function">NotNil</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> <span class="token function">recover</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
        stats <span class="token operator">:=</span> pg<span class="token punctuation">.</span>DB<span class="token punctuation">.</span><span class="token function">Stats</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        require<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> stats<span class="token punctuation">.</span>InUse<span class="token punctuation">)</span>
        require<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> stats<span class="token punctuation">.</span>MaxOpenConnections<span class="token punctuation">)</span>
      <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
      
      err <span class="token operator">=</span> <span class="token function">InTx</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">Background</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> pg<span class="token punctuation">.</span>DB<span class="token punctuation">,</span> test<span class="token punctuation">.</span>txfunc<span class="token punctuation">)</span>
      
      require<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> test<span class="token punctuation">.</span>wantErr<span class="token punctuation">,</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="updating-the-service" tabindex="-1">Updating the Service <a class="header-anchor" href="#updating-the-service"></a></h2>
<p>We have the new transaction layer ready. Let's change our old code to use this new layer.</p>
<pre class="language-go"><code class="language-go"><span class="token comment">// ------------------------------ Repository ------------------------------</span>

<span class="token keyword">type</span> txRepo <span class="token keyword">struct</span> <span class="token punctuation">{</span>
<span class="token punctuation">}</span>

<span class="token comment">// GetSubscription is a repository method that does not leak connections</span>
<span class="token comment">// it uses *TxWrap to wrap the transaction</span>
<span class="token comment">// it uses the context to cancel the transaction if the context is canceled</span>
<span class="token comment">// but the context is inside the *TxWrap and not exposed to the service</span>
<span class="token keyword">func</span> <span class="token punctuation">(</span>r <span class="token operator">*</span>txRepo<span class="token punctuation">)</span> <span class="token function">GetSubscription</span><span class="token punctuation">(</span>tx <span class="token operator">*</span>db<span class="token punctuation">.</span>TxWrap<span class="token punctuation">,</span> id <span class="token builtin">int64</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>Subscription<span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">var</span> sub Subscription
  err <span class="token operator">:=</span> tx<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>sub<span class="token punctuation">,</span> <span class="token string">"SELECT * FROM subscription WHERE id = $1"</span><span class="token punctuation">,</span> id<span class="token punctuation">)</span>
  <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> sub<span class="token punctuation">,</span> err
  <span class="token punctuation">}</span>
  
  <span class="token keyword">return</span> sub<span class="token punctuation">,</span> <span class="token boolean">nil</span>
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>r <span class="token operator">*</span>txRepo<span class="token punctuation">)</span> <span class="token function">CancelSubscription</span><span class="token punctuation">(</span>tx <span class="token operator">*</span>db<span class="token punctuation">.</span>TxWrap<span class="token punctuation">,</span> id <span class="token builtin">int64</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>Subscription<span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">var</span> sub Subscription
  err <span class="token operator">:=</span> tx<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>sub<span class="token punctuation">,</span> <span class="token string">"UPDATE subscription SET canceled_at = NOW(), status='canceled' WHERE id = $1 RETURNING *"</span><span class="token punctuation">,</span> id<span class="token punctuation">)</span>
  <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> sub<span class="token punctuation">,</span> err
  <span class="token punctuation">}</span>
  
  <span class="token keyword">return</span> sub<span class="token punctuation">,</span> <span class="token boolean">nil</span>
<span class="token punctuation">}</span>

<span class="token comment">// ------------------------------ Service ------------------------------</span>

<span class="token keyword">type</span> txService <span class="token keyword">struct</span> <span class="token punctuation">{</span>
  db   <span class="token operator">*</span>sqlx<span class="token punctuation">.</span>DB
  repo <span class="token operator">*</span>txRepo
<span class="token punctuation">}</span>

<span class="token comment">// CancelSubscriptionWithoutLeak is a service method that does not leak connections</span>
<span class="token comment">// it uses InTx helper to wrap the transaction</span>
<span class="token keyword">func</span> <span class="token punctuation">(</span>s <span class="token operator">*</span>txService<span class="token punctuation">)</span> <span class="token function">CancelSubscriptionWithoutLeak</span><span class="token punctuation">(</span>ctx context<span class="token punctuation">.</span>Context<span class="token punctuation">,</span> id <span class="token builtin">int64</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token operator">*</span>Subscription<span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">var</span> sub Subscription
  <span class="token keyword">var</span> err <span class="token builtin">error</span>
  
  <span class="token comment">// So cool!!!!!!!! 🎸</span>
  err <span class="token operator">=</span> db<span class="token punctuation">.</span><span class="token function">InTx</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> s<span class="token punctuation">.</span>db<span class="token punctuation">,</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>tx <span class="token operator">*</span>db<span class="token punctuation">.</span>TxWrap<span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span>
    sub<span class="token punctuation">,</span> err <span class="token operator">=</span> s<span class="token punctuation">.</span>repo<span class="token punctuation">.</span><span class="token function">GetSubscription</span><span class="token punctuation">(</span>tx<span class="token punctuation">,</span> id<span class="token punctuation">)</span>
    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> err
    <span class="token punctuation">}</span>
    
    <span class="token keyword">if</span> sub<span class="token punctuation">.</span>Status <span class="token operator">!=</span> <span class="token string">"active"</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> <span class="token boolean">nil</span>
    <span class="token punctuation">}</span>
    
    <span class="token keyword">if</span> sub<span class="token punctuation">.</span>CanceledAt<span class="token punctuation">.</span>Valid <span class="token punctuation">{</span>
      <span class="token keyword">return</span> <span class="token boolean">nil</span>
    <span class="token punctuation">}</span>
    
    sub<span class="token punctuation">,</span> err <span class="token operator">=</span> s<span class="token punctuation">.</span>repo<span class="token punctuation">.</span><span class="token function">CancelSubscription</span><span class="token punctuation">(</span>tx<span class="token punctuation">,</span> id<span class="token punctuation">)</span>
    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> err
    <span class="token punctuation">}</span>
    
    <span class="token keyword">return</span> <span class="token boolean">nil</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
  
  <span class="token keyword">return</span> <span class="token operator">&amp;</span>sub<span class="token punctuation">,</span> err
<span class="token punctuation">}</span></code></pre>
<p>The Test::</p>
<pre class="language-go"><code class="language-go"><span class="token keyword">func</span> <span class="token function">Test_NoConnectionLeak</span><span class="token punctuation">(</span>t <span class="token operator">*</span>testing<span class="token punctuation">.</span>T<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  pg<span class="token punctuation">,</span> err <span class="token operator">:=</span> apptest<span class="token punctuation">.</span><span class="token function">StartTestPostgres</span><span class="token punctuation">(</span>t<span class="token punctuation">)</span>
  require<span class="token punctuation">.</span><span class="token function">NoError</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> err<span class="token punctuation">)</span>
  
  <span class="token boolean">_</span><span class="token punctuation">,</span> err <span class="token operator">=</span> pg<span class="token punctuation">.</span>DB<span class="token punctuation">.</span><span class="token function">Exec</span><span class="token punctuation">(</span><span class="token string">"CREATE TABLE IF NOT EXISTS subscription (id serial PRIMARY KEY, status varchar(25) NOT NULL, canceled_at timestamp NULL)"</span><span class="token punctuation">)</span>
  require<span class="token punctuation">.</span><span class="token function">NoError</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> err<span class="token punctuation">)</span>
  
  <span class="token boolean">_</span><span class="token punctuation">,</span> err <span class="token operator">=</span> pg<span class="token punctuation">.</span>DB<span class="token punctuation">.</span><span class="token function">Exec</span><span class="token punctuation">(</span><span class="token string">"INSERT INTO subscription (status, canceled_at) VALUES ('active', NULL)"</span><span class="token punctuation">)</span>
  require<span class="token punctuation">.</span><span class="token function">NoError</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> err<span class="token punctuation">)</span>
  
  <span class="token boolean">_</span><span class="token punctuation">,</span> err <span class="token operator">=</span> pg<span class="token punctuation">.</span>DB<span class="token punctuation">.</span><span class="token function">Exec</span><span class="token punctuation">(</span><span class="token string">"INSERT INTO subscription (status, canceled_at) VALUES ('canceled', '2023-02-02 01:00:00')"</span><span class="token punctuation">)</span>
  require<span class="token punctuation">.</span><span class="token function">NoError</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> err<span class="token punctuation">)</span>
  
  subscription<span class="token punctuation">,</span> err <span class="token operator">:=</span> <span class="token function">NewTxService</span><span class="token punctuation">(</span>pg<span class="token punctuation">.</span>DB<span class="token punctuation">,</span> <span class="token operator">&amp;</span>txRepo<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">CancelSubscriptionWithoutLeak</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">Background</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span>
  require<span class="token punctuation">.</span><span class="token function">NoError</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> err<span class="token punctuation">)</span>
  
  stats <span class="token operator">:=</span> pg<span class="token punctuation">.</span>DB<span class="token punctuation">.</span><span class="token function">Stats</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  require<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> stats<span class="token punctuation">.</span>InUse<span class="token punctuation">,</span> <span class="token string">"expected no connections in use"</span><span class="token punctuation">)</span>
  require<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> stats<span class="token punctuation">.</span>MaxOpenConnections<span class="token punctuation">,</span> <span class="token string">"expected no max open connection"</span><span class="token punctuation">)</span>
  
  require<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> <span class="token string">"canceled"</span><span class="token punctuation">,</span> subscription<span class="token punctuation">.</span>Status<span class="token punctuation">)</span>
  require<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> <span class="token string">"2023-02-02 01:00:00 +0000 +0000"</span><span class="token punctuation">,</span> subscription<span class="token punctuation">.</span>CanceledAt<span class="token punctuation">.</span>Time<span class="token punctuation">.</span><span class="token function">String</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">-</span>

<span class="token operator">==</span> <span class="token operator">=</span> RUN   Test_NoConnectionLeak
<span class="token operator">--</span><span class="token operator">-</span> PASS<span class="token punctuation">:</span> Test_NoConnectionLeak <span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">.</span>61s<span class="token punctuation">)</span>
PASS</code></pre>
<p>The test above is the exact test we used in our connection leak example. I have to tweak it for the new service and new
imports. Everything else in the test is the same.</p>
<p>You could see when we changed the service to use the new transaction layer our same test is green. 🥳🥳🥳</p>
<h2 id="do-we-really-need-a-transaction-layer%3F-1" tabindex="-1">Do We Really Need A Transaction Layer? <a class="header-anchor" href="#do-we-really-need-a-transaction-layer%3F-1"></a></h2>
<p>It was tough for me to create a connection leak with the transaction layer in the old code. It is close to impossible
that anything could go wrong.</p>
<p>Although, I felt that testing would be a challenge. The <code>DBStruct</code> provided an easy way for testing.</p>
<p>With different business operations within a transaction, a single line could cause problems and issues in production.
But a separate battle-tested layer would safeguard against any issues. Plus, the same layer could be shared with
different flows to avoid code repetition.</p>
<p>So, if you haven't yet extracted that transaction logic please do! You could write your own library or use something off
the shelf. I am also going to publish the lib on my GitHub which I would share with you 🚀</p>
<img src="https://media0.giphy.com/media/v1.Y2lkPTc5MGI3NjExZGVjYmY5Y2U1OWJlOTE1MjQzNDNkM2Q1MjA3MzA1ODcwMjRhODFlMSZjdD1n/yBwgX64KAPrHW2ltZ2/giphy.gif" alt="gif" class="Gif" />
<h2 id="conclusion" tabindex="-1">Conclusion <a class="header-anchor" href="#conclusion"></a></h2>
<p>With this proof, I am very confident that I will not cause another transaction-related production issue. And I hope this
blog post helps you to learn something new about Golang.</p>
<p>Some of my initial assumptions were proven wrong. The tests
could allow me to answer that the layer works and there will be no connection leak.</p>
<hr>

                ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>A Billion Dollar Go Mistake - Part 2</title>
            <link href="https://iamninad.com/posts/a-billion-dollar-go-mistake-part-2/"/>
            <updated>2023-03-01T00:00:00Z</updated>
            <id>https://iamninad.com/posts/a-billion-dollar-go-mistake-part-2/</id>
            <content type="html">
                <![CDATA[
                <p>This is the second part of the <a href="/posts/a-billion-dollar-go-mistake">A Billion Dollar Go Mistake</a> post.
If you haven't read the first part of the post, I would recommend you to read it first.</p>
<p>In the first part, we saw how to handle the DB transaction at the service level.
What if we still miss the <code>Rollback</code> call? To handle such cases, we could build another layer of safety.</p>
<p>There are two approaches I thought of to handle such cases::</p>
<ul>
<li>Using a context</li>
<li>Server side timeout</li>
</ul>
<h2 id="using-a-context" tabindex="-1">Using a context <a class="header-anchor" href="#using-a-context"></a></h2>
<p>We could use a cancel context to release the lock at the end of the transaction. Context is very helpful in many use cases.</p>
<p>Let’s see how to do things with context</p>
<pre class="language-go"><code class="language-go"><span class="token keyword">func</span> <span class="token punctuation">(</span>s <span class="token operator">*</span>service<span class="token punctuation">)</span> <span class="token function">CancelSubscription</span><span class="token punctuation">(</span>ctx context<span class="token punctuation">.</span>Context<span class="token punctuation">,</span> id uuid<span class="token punctuation">.</span>UUID<span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token operator">*</span>model<span class="token punctuation">.</span>Subscription<span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    ctx<span class="token punctuation">,</span> cancel <span class="token operator">:=</span> context<span class="token punctuation">.</span><span class="token function">WithCancel</span><span class="token punctuation">(</span>ctx<span class="token punctuation">)</span>
    <span class="token keyword">defer</span> <span class="token function">cancel</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    
    tx<span class="token punctuation">,</span> err <span class="token operator">:=</span> s<span class="token punctuation">.</span>db<span class="token punctuation">.</span><span class="token function">BeginTxx</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> <span class="token boolean">nil</span><span class="token punctuation">)</span>
    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> err
    <span class="token punctuation">}</span>
	
    <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
            tx<span class="token punctuation">.</span><span class="token function">Rollback</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    
    subscription<span class="token punctuation">,</span> err <span class="token operator">:=</span> s<span class="token punctuation">.</span>fetcher<span class="token punctuation">.</span><span class="token function">GetSubscription</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> tx<span class="token punctuation">,</span> id<span class="token punctuation">)</span>
    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> err
    <span class="token punctuation">}</span>

    <span class="token keyword">if</span> subscription<span class="token punctuation">.</span>CancelledAt <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> subscription<span class="token punctuation">,</span> <span class="token boolean">nil</span>
    <span class="token punctuation">}</span>
	
    subscription<span class="token punctuation">.</span>CancelledAt <span class="token operator">=</span> time<span class="token punctuation">.</span><span class="token function">Now</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

    err <span class="token operator">=</span> s<span class="token punctuation">.</span>updater<span class="token punctuation">.</span><span class="token function">UpdateSubscription</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> tx<span class="token punctuation">,</span> subscription<span class="token punctuation">)</span>
    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> err
    <span class="token punctuation">}</span>

    err <span class="token operator">=</span> tx<span class="token punctuation">.</span><span class="token function">Commit</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> err
    <span class="token punctuation">}</span>

    <span class="token keyword">return</span> subscription<span class="token punctuation">,</span> <span class="token boolean">nil</span>
<span class="token punctuation">}</span></code></pre>
<p>In the above code, we create a new cancel context from the parent context.
If the DB transaction is not released either using <code>Rollback</code> or <code>Commit</code>.
A <code>defer cancel()</code> happens at the end when the call returns.</p>
<p>The cancel call will notify the transaction that the operation is complete. The go runtime will close the transaction.</p>
<p>The <code>defer cancel()</code> call is important. If you miss that then the problem will still persist</p>
<p>At the go source code level transaction begin call starts a background go routine.
The go routine monitors context Done signal. Let's see how it happens using context as shown <a href="https://github.com/golang/go/blob/master/src/database/sql/sql.go#L1887">here</a></p>
<pre class="language-go"><code class="language-go"><span class="token keyword">func</span> <span class="token punctuation">(</span>db <span class="token operator">*</span>DB<span class="token punctuation">)</span> <span class="token function">beginDC</span><span class="token punctuation">(</span>ctx context<span class="token punctuation">.</span>Context<span class="token punctuation">,</span> dc <span class="token operator">*</span>driverConn<span class="token punctuation">,</span> release <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token builtin">error</span><span class="token punctuation">)</span><span class="token punctuation">,</span> opts <span class="token operator">*</span>TxOptions<span class="token punctuation">)</span> <span class="token punctuation">(</span>tx <span class="token operator">*</span>Tx<span class="token punctuation">,</span> err <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
     <span class="token keyword">var</span> txi driver<span class="token punctuation">.</span>Tx
     keepConnOnRollback <span class="token operator">:=</span> <span class="token boolean">false</span>
     <span class="token function">withLock</span><span class="token punctuation">(</span>dc<span class="token punctuation">,</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token boolean">_</span><span class="token punctuation">,</span> hasSessionResetter <span class="token operator">:=</span> dc<span class="token punctuation">.</span>ci<span class="token punctuation">.</span><span class="token punctuation">(</span>driver<span class="token punctuation">.</span>SessionResetter<span class="token punctuation">)</span>
      <span class="token boolean">_</span><span class="token punctuation">,</span> hasConnectionValidator <span class="token operator">:=</span> dc<span class="token punctuation">.</span>ci<span class="token punctuation">.</span><span class="token punctuation">(</span>driver<span class="token punctuation">.</span>Validator<span class="token punctuation">)</span>
      keepConnOnRollback <span class="token operator">=</span> hasSessionResetter <span class="token operator">&amp;&amp;</span> hasConnectionValidator
      txi<span class="token punctuation">,</span> err <span class="token operator">=</span> <span class="token function">ctxDriverBegin</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> opts<span class="token punctuation">,</span> dc<span class="token punctuation">.</span>ci<span class="token punctuation">)</span>
     <span class="token punctuation">}</span><span class="token punctuation">)</span>
     <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
      <span class="token function">release</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>
      <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> err
     <span class="token punctuation">}</span>

     ctx<span class="token punctuation">,</span> cancel <span class="token operator">:=</span> context<span class="token punctuation">.</span><span class="token function">WithCancel</span><span class="token punctuation">(</span>ctx<span class="token punctuation">)</span>
     tx <span class="token operator">=</span> <span class="token operator">&amp;</span>Tx<span class="token punctuation">{</span>
      db<span class="token punctuation">:</span>                 db<span class="token punctuation">,</span>
      dc<span class="token punctuation">:</span>                 dc<span class="token punctuation">,</span>
      releaseConn<span class="token punctuation">:</span>        release<span class="token punctuation">,</span>
      txi<span class="token punctuation">:</span>                txi<span class="token punctuation">,</span>
      cancel<span class="token punctuation">:</span>             cancel<span class="token punctuation">,</span>
      keepConnOnRollback<span class="token punctuation">:</span> keepConnOnRollback<span class="token punctuation">,</span>
      ctx<span class="token punctuation">:</span>                ctx<span class="token punctuation">,</span>
     <span class="token punctuation">}</span>
     <span class="token keyword">go</span> tx<span class="token punctuation">.</span><span class="token function">awaitDone</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// GO WAITS FOR THE CONTEXT TO DONE</span>
     <span class="token keyword">return</span> tx<span class="token punctuation">,</span> <span class="token boolean">nil</span>
<span class="token punctuation">}</span></code></pre>
<p>And inside the tx.awaitDone</p>
<pre class="language-go"><code class="language-go">  <span class="token keyword">func</span> <span class="token punctuation">(</span>tx <span class="token operator">*</span>Tx<span class="token punctuation">)</span> <span class="token function">awaitDone</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
   <span class="token comment">// Wait for either the transaction to be committed or rolled</span>
   <span class="token comment">// back, or for the associated context to be closed.</span>
   <span class="token operator">&lt;-</span>tx<span class="token punctuation">.</span>ctx<span class="token punctuation">.</span><span class="token function">Done</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  
   <span class="token comment">// Discard and close the connection used to ensure the</span>
   <span class="token comment">// transaction is closed and the resources are released.  This</span>
   <span class="token comment">// rollback does nothing if the transaction has already been</span>
   <span class="token comment">// committed or rolled back.</span>
   <span class="token comment">// Do not discard the connection if the connection knows</span>
   <span class="token comment">// how to reset the session.</span>
   discardConnection <span class="token operator">:=</span> <span class="token operator">!</span>tx<span class="token punctuation">.</span>keepConnOnRollback
   tx<span class="token punctuation">.</span><span class="token function">rollback</span><span class="token punctuation">(</span>discardConnection<span class="token punctuation">)</span>  <span class="token comment">// AT THE END THE TX WILL BE ROLLBACKED</span>
  <span class="token punctuation">}</span></code></pre>
<p>So transactions with a cancel context make more sense. Do not use the context coming from the HTTP request.
HTTP context works like a client-side timeout. The service layer has no control over cancelling the HTTP context.</p>
<p>A timeout context could also work but that will not be that reliable. Finding the right timeout value is a difficult task in itself.</p>
<h2 id="server-side-timeout" tabindex="-1">Server-side timeout <a class="header-anchor" href="#server-side-timeout"></a></h2>
<p>You set an optimal timeout for the request to complete and if the request is not completed within that time,
you cancel the operation and return an error.</p>
<pre class="language-go"><code class="language-go">
server <span class="token operator">:=</span> <span class="token operator">&amp;</span>http<span class="token punctuation">.</span>Server<span class="token punctuation">{</span>
    Addr<span class="token punctuation">:</span>         <span class="token string">":8080"</span><span class="token punctuation">,</span>
    Handler<span class="token punctuation">:</span>      router<span class="token punctuation">,</span>
    WriteTimeout<span class="token punctuation">:</span> <span class="token number">2</span> <span class="token operator">*</span> time<span class="token punctuation">.</span>Second<span class="token punctuation">,</span>
<span class="token punctuation">}</span>
</code></pre>
<p>In the above code, we are setting a server-side timeout of 2 seconds. If the entire request processing is not completed
within 2 seconds, we cancel the operation and return an error to the client. With this approach, you don't need to create
a timeout context for each request. But, you would still need to fine-tune the timeout value based on the traces and load testing.</p>
<h2 id="conclusion" tabindex="-1">Conclusion <a class="header-anchor" href="#conclusion"></a></h2>
<p>I hope you found this second part of the post useful. Adding a layer of safety is always a good idea, but it comes with a cost.
In this case, I would recommend using the context approach along with the <code>defer tx.Rollback()</code> after initiating the transaction.</p>
<p>Cancel context is the best approach for most application types.
And would serve most of the cases. The context in general has a lot of use cases and I would recommend you read more about it.</p>
<p>Also, for an extra layer of safety, I would recommend keeping a Server side timeout for HTTP services.</p>
<p>You would be also thinking about the client-side timeout.
Those are not reliable enough. For example, a client could keep the timeout for a long duration and with a high load,
the server could keep the connection open for a long time. This could again lead to the same problem we are trying to solve.</p>

                ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>A Billion Dollar Go Mistake</title>
            <link href="https://iamninad.com/posts/a-billion-dollar-go-mistake/"/>
            <updated>2023-02-26T00:00:00Z</updated>
            <id>https://iamninad.com/posts/a-billion-dollar-go-mistake/</id>
            <content type="html">
                <![CDATA[
                <blockquote>
<p>This post is about a real problem we faced in our project.</p>
</blockquote>
<p>I hope after reading this post you will be able to avoid the same mistake we did in our project 😅.
This small mistake didn't cost us a million dollars. But, It did cost us a few thousand, and the Prometheus alerts saved us.</p>
<p>But, it could cost you a Million if you are not careful 💸.</p>
<p>The scenario is a simple database transaction. We all have used database transactions at least once in our programming life.
If you don't know how transactions work you could read the docs <a href="https://www.postgresql.org/docs/current/tutorial-transactions.html">here</a> for Postgres.</p>
<p>Our service handles the management of some Subscriptions in the database. All the changes to the rows happen within a transaction.
The service is in Golang and the flow is like this::</p>
<ul>
<li>Start the transaction</li>
<li>Fetch the record by ID</li>
<li>Confirm if the operation for the change is possible</li>
<li>If Yes, then update the record</li>
<li>Commit the transaction</li>
<li>For any error, revert the transaction</li>
</ul>
<p>To fetch a record and acquire a lock on the record so that other flows would wait to update, we use <code>SELECT ... FOR UPDATE</code>
query to fetch the record from Postgres and lock it.</p>
<blockquote>
<p><strong>Note:</strong> We use <a href="https://github.com/jmoiron/sqlx">sqlx</a> lib for database access.</p>
</blockquote>
<p>The repository code is like this::</p>
<pre class="language-go"><code class="language-go">
<span class="token keyword">func</span> <span class="token punctuation">(</span>r <span class="token operator">*</span>fetcher<span class="token punctuation">)</span> <span class="token function">GetSubscription</span><span class="token punctuation">(</span>tx <span class="token operator">*</span>sqlx<span class="token punctuation">.</span>Tx<span class="token punctuation">,</span> id uuid<span class="token punctuation">.</span>UUID<span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token operator">*</span>model<span class="token punctuation">.</span>Subscription<span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">var</span> subscription model<span class="token punctuation">.</span>Subscription
    err <span class="token operator">:=</span> tx<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>subscription<span class="token punctuation">,</span> <span class="token string">`
        SELECT * FROM subscriptions
        WHERE id = $1
        FOR UPDATE
    `</span><span class="token punctuation">,</span> id<span class="token punctuation">)</span>
    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> err
    <span class="token punctuation">}</span>
	
    <span class="token keyword">return</span> <span class="token operator">&amp;</span>subscription<span class="token punctuation">,</span> <span class="token boolean">nil</span>
<span class="token punctuation">}</span>
</code></pre>
<p>The service code is like this::</p>
<pre class="language-go"><code class="language-go">
<span class="token keyword">func</span> <span class="token punctuation">(</span>s <span class="token operator">*</span>service<span class="token punctuation">)</span> <span class="token function">CancelSubscription</span><span class="token punctuation">(</span>ctx context<span class="token punctuation">.</span>Context<span class="token punctuation">,</span> id uuid<span class="token punctuation">.</span>UUID<span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token operator">*</span>model<span class="token punctuation">.</span>Subscription<span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    tx<span class="token punctuation">,</span> err <span class="token operator">:=</span> s<span class="token punctuation">.</span>db<span class="token punctuation">.</span><span class="token function">BeginTxx</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> <span class="token boolean">nil</span><span class="token punctuation">)</span>
    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> err
    <span class="token punctuation">}</span>
	
    <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
            tx<span class="token punctuation">.</span><span class="token function">Rollback</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    
    subscription<span class="token punctuation">,</span> err <span class="token operator">:=</span> s<span class="token punctuation">.</span>fetcher<span class="token punctuation">.</span><span class="token function">GetSubscription</span><span class="token punctuation">(</span>tx<span class="token punctuation">,</span> id<span class="token punctuation">)</span>
    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> err
    <span class="token punctuation">}</span>

    <span class="token keyword">if</span> subscription<span class="token punctuation">.</span>CancelledAt <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> subscription<span class="token punctuation">,</span> <span class="token boolean">nil</span>
    <span class="token punctuation">}</span>
	
    subscription<span class="token punctuation">.</span>CancelledAt <span class="token operator">=</span> time<span class="token punctuation">.</span><span class="token function">Now</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

    err <span class="token operator">=</span> s<span class="token punctuation">.</span>updater<span class="token punctuation">.</span><span class="token function">UpdateSubscription</span><span class="token punctuation">(</span>tx<span class="token punctuation">,</span> subscription<span class="token punctuation">)</span>
    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> err
    <span class="token punctuation">}</span>

    err <span class="token operator">=</span> tx<span class="token punctuation">.</span><span class="token function">Commit</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> err
    <span class="token punctuation">}</span>

    <span class="token keyword">return</span> subscription<span class="token punctuation">,</span> <span class="token boolean">nil</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="problem" tabindex="-1">Problem <a class="header-anchor" href="#problem"></a></h2>
<p>All client requests were timing out, and the DB connection spiked over 1.2k connections 😅</p>
<p>Not a single request was able to complete the operation. It was a stop-the-world event 🤣</p>
<figure><img src="https://media.giphy.com/media/XD4qHZpkyUFfq/giphy.gif" alt="cry"></figure>
<p><strong>Why?</strong></p>
<p>The issue happens when we try to cancel a subscription that is already cancelled. If the subscription is already cancelled
we return the subscription without doing any changes, but we are not releasing the lock on the record.</p>
<p>The reason is the <code>defer</code> function calls <code>tx.Rollback()</code> only when there is an error. This would cause the lock to be active
until the transaction commits or roll back. But since we are not doing any of the two things, the lock is held
until the transaction times out.</p>
<p>If the service is having high traffic, the transactions could not time out. This will cause the code to create
new connections to the database and exhaust the connection pool.</p>
<h2 id="fix" tabindex="-1">Fix <a class="header-anchor" href="#fix"></a></h2>
<p>There are three ways to fix this issue at the service layer.
To keep the post short, I have explained the other ways in a different post.</p>
<ol>
<li>Release the lock in every <code>if</code> condition.</li>
</ol>
<pre class="language-go"><code class="language-go"><span class="token comment">// Error handling is omitted for brevity</span>
<span class="token keyword">if</span> subscription<span class="token punctuation">.</span>CancelledAt <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
    <span class="token boolean">_</span> <span class="token operator">=</span> tx<span class="token punctuation">.</span><span class="token function">Rollback</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// release the lock</span>

    <span class="token keyword">return</span> subscription<span class="token punctuation">,</span> <span class="token boolean">nil</span>
<span class="token punctuation">}</span>
</code></pre>
<p>This is the simplest way to fix the issue. But this would need you to rollback in every <code>if</code> condition.
And if you forget to rollback in any of the <code>if</code> conditions, you would end up with the same issue.</p>
<ol start="2">
<li>Rollback the transaction in the <code>defer</code> function for every case.</li>
</ol>
<pre class="language-go"><code class="language-go"><span class="token comment">// Error handling is omitted for brevity</span>
<span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
   <span class="token boolean">_</span> <span class="token operator">=</span> tx<span class="token punctuation">.</span><span class="token function">Rollback</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</code></pre>
<p>This would release the lock in every case. For committed transactions and as per the tracing, we see some milliseconds
the code spends to roll back the transactions. In case of committed transactions the rollback does nothing.
But this is a better way to fix the issue.</p>
<ol start="3">
<li>Commit the transaction in the <code>defer</code> function for every case.</li>
</ol>
<pre class="language-go"><code class="language-go"><span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
    <span class="token boolean">_</span> <span class="token operator">=</span> tx<span class="token punctuation">.</span><span class="token function">Rollback</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
  
  commitErr <span class="token operator">:=</span> tx<span class="token punctuation">.</span><span class="token function">Commit</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token comment">// handle commitErr</span>
<span class="token punctuation">}</span></code></pre>
<p>If there are no changes the transaction will commit without any change. If there is any error only then the
rollback would happen and will release the lock.</p>
<p>But, this affects the readability of the code. Your commit is happening in the <code>defer</code> function, and that's an extra
pointer you have to keep in mind while reading the code.</p>
<h2 id="service-layer---return-error-%F0%9F%91%BE" tabindex="-1">Service Layer - Return Error 👾 <a class="header-anchor" href="#service-layer---return-error-%F0%9F%91%BE"></a></h2>
<p>The problem with the service is that for validations, it is not returning any error. The other way to fix this issue is to
return an error from the <code>if</code> condition. This would make the <code>Rollback</code> happen in the <code>defer</code> function.</p>
<p>This is a very clean way. A service should have only one responsibility. Either it completes the operation
or it returns an error. It should return error in case of validation failure. This is a good practice
and something we missed in our project. We fixed the issue later by returning an error from the <code>if</code> condition.</p>
<p>This change also helps the handler to decide what HTTP status code to return. Which is really helpful as we can return
<code>400 Bad Request</code> for validation errors.</p>
<p>This is how the code would look like after refactoring</p>
<pre class="language-go"><code class="language-go"><span class="token keyword">var</span> ErrSubscriptionAlreadyCancelled <span class="token operator">=</span> errors<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token string">"subscription already cancelled"</span><span class="token punctuation">)</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>s <span class="token operator">*</span>service<span class="token punctuation">)</span> <span class="token function">CancelSubscription</span><span class="token punctuation">(</span>ctx context<span class="token punctuation">.</span>Context<span class="token punctuation">,</span> id uuid<span class="token punctuation">.</span>UUID<span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token operator">*</span>model<span class="token punctuation">.</span>Subscription<span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    tx<span class="token punctuation">,</span> err <span class="token operator">:=</span> s<span class="token punctuation">.</span>db<span class="token punctuation">.</span><span class="token function">BeginTxx</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> <span class="token boolean">nil</span><span class="token punctuation">)</span>
    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> err
    <span class="token punctuation">}</span>
	
    <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
            tx<span class="token punctuation">.</span><span class="token function">Rollback</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    
    subscription<span class="token punctuation">,</span> err <span class="token operator">:=</span> s<span class="token punctuation">.</span>fetcher<span class="token punctuation">.</span><span class="token function">GetSubscription</span><span class="token punctuation">(</span>tx<span class="token punctuation">,</span> id<span class="token punctuation">)</span>
    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> err
    <span class="token punctuation">}</span>

    <span class="token keyword">if</span> subscription<span class="token punctuation">.</span>CancelledAt <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> subscription<span class="token punctuation">,</span> ErrSubscriptionAlreadyCancelled
    <span class="token punctuation">}</span>
	
    subscription<span class="token punctuation">.</span>CancelledAt <span class="token operator">=</span> time<span class="token punctuation">.</span><span class="token function">Now</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

    err <span class="token operator">=</span> s<span class="token punctuation">.</span>updater<span class="token punctuation">.</span><span class="token function">UpdateSubscription</span><span class="token punctuation">(</span>tx<span class="token punctuation">,</span> subscription<span class="token punctuation">)</span>
    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> err
    <span class="token punctuation">}</span>

    err <span class="token operator">=</span> tx<span class="token punctuation">.</span><span class="token function">Commit</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> err
    <span class="token punctuation">}</span>

    <span class="token keyword">return</span> subscription<span class="token punctuation">,</span> <span class="token boolean">nil</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="conclusion" tabindex="-1">Conclusion <a class="header-anchor" href="#conclusion"></a></h2>
<p>My personal preference is the second option. But you could choose any of the three options based on your preference.
I am choosing the second option because I am sure that whatever happens in the flow at the end, the transaction
revert will happen. Yes, it would cost me a few milliseconds in case of a committed transaction, but compared to the loss to
the business, it's worth.</p>
<p>Keep in mind that the service layer has only one responsibility. Either it completes the operation or it returns an error.</p>
<p>You may be thinking that a better approach is to have an abstraction that takes care of transactions. I agree,
and would also have a separate post on that. But, I also think that we can avoid the complexity of abstraction if the code is stable and not changes too often.</p>
<p>The golang official post for transactions also supports the reasoning. Check the code snippet <a href="https://go.dev/doc/database/execute-transactions#example">here</a>.
The office post also uses the second option.</p>
<pre class="language-go"><code class="language-go"><span class="token comment">// code snippet from the golang official post</span>
<span class="token keyword">func</span> <span class="token function">CreateOrder</span><span class="token punctuation">(</span>ctx context<span class="token punctuation">.</span>Context<span class="token punctuation">,</span> albumID<span class="token punctuation">,</span> quantity<span class="token punctuation">,</span> custID <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>orderID <span class="token builtin">int64</span><span class="token punctuation">,</span> err <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

  <span class="token comment">// Create a helper function for preparing failure results.</span>
  fail <span class="token operator">:=</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>err <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token builtin">int64</span><span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"CreateOrder: %v"</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// Get a Tx for making transaction requests.</span>
  tx<span class="token punctuation">,</span> err <span class="token operator">:=</span> db<span class="token punctuation">.</span><span class="token function">BeginTx</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> <span class="token boolean">nil</span><span class="token punctuation">)</span>
  <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token function">fail</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
  <span class="token comment">// Defer a rollback in case anything fails.</span>
  <span class="token keyword">defer</span> tx<span class="token punctuation">.</span><span class="token function">Rollback</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  
  <span class="token operator">...</span> <span class="token comment">// other code is omitted for brevity</span>
  
  <span class="token comment">// Commit the transaction.</span>
  <span class="token keyword">if</span> err <span class="token operator">=</span> tx<span class="token punctuation">.</span><span class="token function">Commit</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token function">fail</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
  
  <span class="token comment">// Return the order ID.</span>
  <span class="token keyword">return</span> orderID<span class="token punctuation">,</span> <span class="token boolean">nil</span>
<span class="token punctuation">}</span></code></pre>
<hr>
<p>This brings us to the end of this post. I hope you enjoyed reading this post. There is a part two to this post, where I will
talk about having another layer of protection to prevent this issue.</p>
<p>If you have any questions or suggestions, feel free to reach out to me using the AMA.</p>

                ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Docker Compose For Your Next Debezium And Postgres Project</title>
            <link href="https://iamninad.com/posts/docker-compose-for-your-next-debezium-and-postgres-project/"/>
            <updated>2023-02-04T00:00:00Z</updated>
            <id>https://iamninad.com/posts/docker-compose-for-your-next-debezium-and-postgres-project/</id>
            <content type="html">
                <![CDATA[
                <p>This is an addition to my docker-compose setup that allows me to test applications locally and quickly. I like running the services that I am building on my Mac because then it is easy to try any scenarios or replicate the reported bugs also, I think the entire CI/CD duration to deploy the change to the staging/test environment sometimes takes more time for testing small stuff <em>(I am not saying that you should never test services on staging/test env 😅)</em>.</p>
<p>I am working with Change Data Capture using Debezium recently and this docker-compose helps me to write the consumer application that will process the changes happening at the DB level.</p>
<p>In this post, I will be setting up the Debezium connector for Postgres with all the changes required to allow Debezium to capture the changes. In addition, I will also provide the details on how to make this configuration on the AWS RDS if you are going to use the Debezium Connector for your next project.</p>
<p>The following services would be needed to make the Debezium and Postgres work locally::</p>
<ul>
<li>Kafka Broker - <code>localhost:9092</code></li>
<li>Zookeeper - <code>localhost:2181</code></li>
<li>Postgres - <code>localhost:5432</code></li>
<li>Debezium Connector - <code>localhost:8083</code></li>
<li>Schema Registry - <code>localhost:8081</code></li>
<li>Debezium UI - <code>localhost:8080</code></li>
<li>Rest-Proxy - This is optional, but helps with checking cluster metadata, topics etc - <code>localhost:8082</code></li>
</ul>
<h3 id="starting-docker-compose" tabindex="-1">Starting Docker Compose <a class="header-anchor" href="#starting-docker-compose"></a></h3>
<p>Below is the docker-compose file I use to start the stack::</p>
<pre class="language-yaml"><code class="language-yaml"><span class="token key atrule">version</span><span class="token punctuation">:</span> <span class="token string">'3.9'</span>

<span class="token key atrule">services</span><span class="token punctuation">:</span>
  <span class="token key atrule">zookeeper</span><span class="token punctuation">:</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> confluentinc/cp<span class="token punctuation">-</span>zookeeper<span class="token punctuation">:</span>7.3.1
    <span class="token key atrule">hostname</span><span class="token punctuation">:</span> zookeeper
    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> zookeeper
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> <span class="token string">'2181:2181'</span>
    <span class="token key atrule">environment</span><span class="token punctuation">:</span>
      <span class="token key atrule">ZOOKEEPER_CLIENT_PORT</span><span class="token punctuation">:</span> <span class="token number">2181</span>
      <span class="token key atrule">ZOOKEEPER_TICK_TIME</span><span class="token punctuation">:</span> <span class="token number">2000</span>
    <span class="token key atrule">healthcheck</span><span class="token punctuation">:</span>
      <span class="token key atrule">test</span><span class="token punctuation">:</span> echo srvr <span class="token punctuation">|</span> nc zookeeper 2181 <span class="token punctuation">|</span><span class="token punctuation">|</span> exit 1
      <span class="token key atrule">start_period</span><span class="token punctuation">:</span> 10s
      <span class="token key atrule">retries</span><span class="token punctuation">:</span> <span class="token number">20</span>
      <span class="token key atrule">interval</span><span class="token punctuation">:</span> 10s
  <span class="token key atrule">broker</span><span class="token punctuation">:</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> confluentinc/cp<span class="token punctuation">-</span>kafka<span class="token punctuation">:</span>7.3.1
    <span class="token key atrule">hostname</span><span class="token punctuation">:</span> broker
    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> broker
    <span class="token key atrule">depends_on</span><span class="token punctuation">:</span>
      <span class="token key atrule">zookeeper</span><span class="token punctuation">:</span>
        <span class="token key atrule">condition</span><span class="token punctuation">:</span> service_healthy
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> <span class="token string">'29092:29092'</span>
      <span class="token punctuation">-</span> <span class="token string">'9092:9092'</span>
      <span class="token punctuation">-</span> <span class="token string">'9101:9101'</span>
    <span class="token key atrule">environment</span><span class="token punctuation">:</span>
      <span class="token key atrule">KAFKA_BROKER_ID</span><span class="token punctuation">:</span> <span class="token number">1</span>
      <span class="token key atrule">KAFKA_ZOOKEEPER_CONNECT</span><span class="token punctuation">:</span> <span class="token string">'zookeeper:2181'</span>
      <span class="token key atrule">KAFKA_LISTENER_SECURITY_PROTOCOL_MAP</span><span class="token punctuation">:</span> PLAINTEXT<span class="token punctuation">:</span>PLAINTEXT<span class="token punctuation">,</span>PLAINTEXT_HOST<span class="token punctuation">:</span>PLAINTEXT
      <span class="token key atrule">KAFKA_ADVERTISED_LISTENERS</span><span class="token punctuation">:</span> PLAINTEXT<span class="token punctuation">:</span>//broker<span class="token punctuation">:</span><span class="token number">29092</span><span class="token punctuation">,</span>PLAINTEXT_HOST<span class="token punctuation">:</span>//localhost<span class="token punctuation">:</span><span class="token number">9092</span>
      <span class="token key atrule">KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR</span><span class="token punctuation">:</span> <span class="token number">1</span>
      <span class="token key atrule">KAFKA_TRANSACTION_STATE_LOG_MIN_ISR</span><span class="token punctuation">:</span> <span class="token number">1</span>
      <span class="token key atrule">KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR</span><span class="token punctuation">:</span> <span class="token number">1</span>
      <span class="token key atrule">KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS</span><span class="token punctuation">:</span> <span class="token number">0</span>
      <span class="token key atrule">KAFKA_AUTO_CREATE_TOPICS_ENABLE</span><span class="token punctuation">:</span> <span class="token string">'true'</span>
      <span class="token key atrule">KAFKA_JMX_PORT</span><span class="token punctuation">:</span> <span class="token number">9101</span>
      <span class="token key atrule">KAFKA_JMX_HOSTNAME</span><span class="token punctuation">:</span> localhost
    <span class="token key atrule">healthcheck</span><span class="token punctuation">:</span>
      <span class="token key atrule">test</span><span class="token punctuation">:</span> nc <span class="token punctuation">-</span>z localhost 9092 <span class="token punctuation">|</span><span class="token punctuation">|</span> exit <span class="token punctuation">-</span><span class="token number">1</span>
      <span class="token key atrule">start_period</span><span class="token punctuation">:</span> 15s
      <span class="token key atrule">interval</span><span class="token punctuation">:</span> 5s
      <span class="token key atrule">timeout</span><span class="token punctuation">:</span> 10s
      <span class="token key atrule">retries</span><span class="token punctuation">:</span> <span class="token number">10</span>
  <span class="token key atrule">debezium</span><span class="token punctuation">:</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> debezium/connect<span class="token punctuation">:</span>latest
    <span class="token key atrule">restart</span><span class="token punctuation">:</span> always
    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> debezium
    <span class="token key atrule">hostname</span><span class="token punctuation">:</span> debezium
    <span class="token key atrule">depends_on</span><span class="token punctuation">:</span>
      <span class="token key atrule">postgres</span><span class="token punctuation">:</span>
        <span class="token key atrule">condition</span><span class="token punctuation">:</span> service_healthy
      <span class="token key atrule">broker</span><span class="token punctuation">:</span>
        <span class="token key atrule">condition</span><span class="token punctuation">:</span> service_healthy
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> <span class="token string">'8083:8083'</span>
    <span class="token key atrule">environment</span><span class="token punctuation">:</span>
      <span class="token key atrule">BOOTSTRAP_SERVERS</span><span class="token punctuation">:</span> broker<span class="token punctuation">:</span><span class="token number">29092</span>
      <span class="token key atrule">GROUP_ID</span><span class="token punctuation">:</span> <span class="token number">1</span>
      <span class="token key atrule">CONFIG_STORAGE_TOPIC</span><span class="token punctuation">:</span> connect_configs
      <span class="token key atrule">STATUS_STORAGE_TOPIC</span><span class="token punctuation">:</span> connect_statuses
      <span class="token key atrule">OFFSET_STORAGE_TOPIC</span><span class="token punctuation">:</span> connect_offsets
      <span class="token key atrule">KEY_CONVERTER</span><span class="token punctuation">:</span> org.apache.kafka.connect.json.JsonConverter
      <span class="token key atrule">VALUE_CONVERTER</span><span class="token punctuation">:</span> org.apache.kafka.connect.json.JsonConverter
      <span class="token key atrule">ENABLE_DEBEZIUM_SCRIPTING</span><span class="token punctuation">:</span> <span class="token string">'true'</span>
    <span class="token key atrule">healthcheck</span><span class="token punctuation">:</span>
      <span class="token key atrule">test</span><span class="token punctuation">:</span>
        <span class="token punctuation">[</span>
          <span class="token string">'CMD'</span><span class="token punctuation">,</span>
          <span class="token string">'curl'</span><span class="token punctuation">,</span>
          <span class="token string">'--silent'</span><span class="token punctuation">,</span>
          <span class="token string">'--fail'</span><span class="token punctuation">,</span>
          <span class="token string">'-X'</span><span class="token punctuation">,</span>
          <span class="token string">'GET'</span><span class="token punctuation">,</span>
          <span class="token string">'http://localhost:8083/connectors'</span><span class="token punctuation">,</span>
        <span class="token punctuation">]</span>
      <span class="token key atrule">start_period</span><span class="token punctuation">:</span> 10s
      <span class="token key atrule">interval</span><span class="token punctuation">:</span> 10s
      <span class="token key atrule">timeout</span><span class="token punctuation">:</span> 5s
      <span class="token key atrule">retries</span><span class="token punctuation">:</span> <span class="token number">5</span>

  <span class="token key atrule">schema-registry</span><span class="token punctuation">:</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> confluentinc/cp<span class="token punctuation">-</span>schema<span class="token punctuation">-</span>registry<span class="token punctuation">:</span>7.3.1
    <span class="token key atrule">hostname</span><span class="token punctuation">:</span> schema<span class="token punctuation">-</span>registry
    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> schema<span class="token punctuation">-</span>registry
    <span class="token key atrule">depends_on</span><span class="token punctuation">:</span>
      <span class="token key atrule">broker</span><span class="token punctuation">:</span>
        <span class="token key atrule">condition</span><span class="token punctuation">:</span> service_healthy
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> <span class="token string">'8081:8081'</span>
    <span class="token key atrule">environment</span><span class="token punctuation">:</span>
      <span class="token key atrule">SCHEMA_REGISTRY_HOST_NAME</span><span class="token punctuation">:</span> schema<span class="token punctuation">-</span>registry
      <span class="token key atrule">SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS</span><span class="token punctuation">:</span> broker<span class="token punctuation">:</span><span class="token number">29092</span>
      <span class="token key atrule">SCHEMA_REGISTRY_LISTENERS</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//0.0.0.0<span class="token punctuation">:</span><span class="token number">8081</span>

    <span class="token key atrule">healthcheck</span><span class="token punctuation">:</span>
      <span class="token key atrule">start_period</span><span class="token punctuation">:</span> 10s
      <span class="token key atrule">interval</span><span class="token punctuation">:</span> 10s
      <span class="token key atrule">retries</span><span class="token punctuation">:</span> <span class="token number">20</span>
      <span class="token key atrule">test</span><span class="token punctuation">:</span> curl <span class="token punctuation">-</span><span class="token punctuation">-</span>user superUser<span class="token punctuation">:</span>superUser <span class="token punctuation">-</span><span class="token punctuation">-</span>fail <span class="token punctuation">-</span><span class="token punctuation">-</span>silent <span class="token punctuation">-</span><span class="token punctuation">-</span>insecure http<span class="token punctuation">:</span>//localhost<span class="token punctuation">:</span>8081/subjects <span class="token punctuation">-</span><span class="token punctuation">-</span>output /dev/null <span class="token punctuation">|</span><span class="token punctuation">|</span> exit 1

  <span class="token key atrule">rest-proxy</span><span class="token punctuation">:</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> confluentinc/cp<span class="token punctuation">-</span>kafka<span class="token punctuation">-</span>rest<span class="token punctuation">:</span>7.3.1
    <span class="token key atrule">depends_on</span><span class="token punctuation">:</span>
      <span class="token key atrule">broker</span><span class="token punctuation">:</span>
        <span class="token key atrule">condition</span><span class="token punctuation">:</span> service_healthy
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> <span class="token string">'8082:8082'</span>
    <span class="token key atrule">hostname</span><span class="token punctuation">:</span> rest<span class="token punctuation">-</span>proxy
    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> rest<span class="token punctuation">-</span>proxy
    <span class="token key atrule">environment</span><span class="token punctuation">:</span>
      <span class="token key atrule">KAFKA_REST_HOST_NAME</span><span class="token punctuation">:</span> rest<span class="token punctuation">-</span>proxy
      <span class="token key atrule">KAFKA_REST_BOOTSTRAP_SERVERS</span><span class="token punctuation">:</span> <span class="token string">'broker:29092'</span>
      <span class="token key atrule">KAFKA_REST_LISTENERS</span><span class="token punctuation">:</span> <span class="token string">'http://0.0.0.0:8082'</span>

  <span class="token key atrule">debezium-ui</span><span class="token punctuation">:</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> debezium/debezium<span class="token punctuation">-</span>ui<span class="token punctuation">:</span>latest
    <span class="token key atrule">restart</span><span class="token punctuation">:</span> always
    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> debezium<span class="token punctuation">-</span>ui
    <span class="token key atrule">hostname</span><span class="token punctuation">:</span> debezium<span class="token punctuation">-</span>ui
    <span class="token key atrule">depends_on</span><span class="token punctuation">:</span>
      <span class="token key atrule">debezium</span><span class="token punctuation">:</span>
        <span class="token key atrule">condition</span><span class="token punctuation">:</span> service_healthy
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> <span class="token string">'8080:8080'</span>
    <span class="token key atrule">environment</span><span class="token punctuation">:</span>
      <span class="token key atrule">KAFKA_CONNECT_URIS</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//debezium<span class="token punctuation">:</span><span class="token number">8083</span>

  <span class="token key atrule">postgres</span><span class="token punctuation">:</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> postgres<span class="token punctuation">:</span>latest
    <span class="token key atrule">restart</span><span class="token punctuation">:</span> always
    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> postgres
    <span class="token key atrule">hostname</span><span class="token punctuation">:</span> postgres
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> <span class="token string">'5432:5432'</span>
    <span class="token key atrule">environment</span><span class="token punctuation">:</span>
      <span class="token key atrule">POSTGRES_USER</span><span class="token punctuation">:</span> postgres
      <span class="token key atrule">POSTGRES_PASSWORD</span><span class="token punctuation">:</span> postgres
      <span class="token key atrule">POSTGRES_DB</span><span class="token punctuation">:</span> movies_db
    <span class="token key atrule">command</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">'postgres'</span><span class="token punctuation">,</span> <span class="token string">'-c'</span><span class="token punctuation">,</span> <span class="token string">'wal_level=logical'</span><span class="token punctuation">]</span>
    <span class="token key atrule">healthcheck</span><span class="token punctuation">:</span>
      <span class="token key atrule">test</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">'CMD'</span><span class="token punctuation">,</span> <span class="token string">'psql'</span><span class="token punctuation">,</span> <span class="token string">'-U'</span><span class="token punctuation">,</span> <span class="token string">'postgres'</span><span class="token punctuation">,</span> <span class="token string">'-c'</span><span class="token punctuation">,</span> <span class="token string">'SELECT 1'</span><span class="token punctuation">]</span>
      <span class="token key atrule">interval</span><span class="token punctuation">:</span> 10s
      <span class="token key atrule">timeout</span><span class="token punctuation">:</span> 5s
      <span class="token key atrule">retries</span><span class="token punctuation">:</span> <span class="token number">5</span>
    <span class="token key atrule">volumes</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> ./scripts<span class="token punctuation">:</span>/docker<span class="token punctuation">-</span>entrypoint<span class="token punctuation">-</span>initdb.d</code></pre>
<p>For Debezium to work with Postgres, Postgres needs to have the <code>logical replication</code> enabled and if you observe the line <code>command: [&quot;postgres&quot;, &quot;-c&quot;, &quot;wal_level=logical&quot;]</code> we are configuring the Postgres DB to start with <code>wal_level</code> as <code>logical</code>.</p>
<p>If we don't do this step, then debezium would not be able to capture the changes happening on Postgres. The default <code>wal_level</code> is <code>replica</code>.</p>
<p>Now we have our docker-compose file ready let's start all the service</p>
<pre class="language-bash"><code class="language-bash"> <span class="token function">docker</span> compose <span class="token parameter variable">-f</span> docker-compose.yml up <span class="token parameter variable">-d</span>
<span class="token punctuation">[</span>+<span class="token punctuation">]</span> Running <span class="token number">8</span>/8
 ⠿ Network postgres_default   Created                                                                                                                                                                          <span class="token number">0</span>.1s
 ⠿ Container postgres         Healthy                                                                                                                                                                         <span class="token number">12</span>.8s
 ⠿ Container zookeeper        Healthy                                                                                                                                                                         <span class="token number">11</span>.8s
 ⠿ Container broker           Healthy                                                                                                                                                                         <span class="token number">22</span>.6s
 ⠿ Container debezium         Healthy                                                                                                                                                                         <span class="token number">44</span>.2s
 ⠿ Container rest-proxy       Started                                                                                                                                                                         <span class="token number">23</span>.1s
 ⠿ Container schema-registry  Started                                                                                                                                                                         <span class="token number">23</span>.1s
 ⠿ Container debezium-ui      Started                                                                                                                                                                         <span class="token number">44</span>.6s</code></pre>
<p>As we could see all the containers have started without any errors. If you are running this command for the first time it would take some time to download all the docker images but the later executions will be faster</p>
<h3 id="configure-postgres-connector" tabindex="-1">Configure Postgres Connector <a class="header-anchor" href="#configure-postgres-connector"></a></h3>
<p>At this point, our Debezium connector is running but it doesn't have any task to read changes happening on the Postgres DB. We need to register the Postgres connector using HTTP API so that debezium could read the transaction logs from the server.</p>
<p>It's easy to register the connector, there is a sample connector config already present in the repo. Execute the below <code>curl</code> and we would see the connector registered</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">curl</span> <span class="token parameter variable">-X</span> POST <span class="token parameter variable">--location</span> <span class="token string">"http://localhost:8083/connectors"</span> <span class="token parameter variable">-H</span> <span class="token string">"Content-Type: application/json"</span> <span class="token parameter variable">-H</span> <span class="token string">"Accept: application/json"</span> <span class="token parameter variable">-d</span> @connector.json</code></pre>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"config"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"connector.class"</span><span class="token operator">:</span> <span class="token string">"io.debezium.connector.postgresql.PostgresConnector"</span><span class="token punctuation">,</span>
    <span class="token property">"database.dbname"</span><span class="token operator">:</span> <span class="token string">"movies_db"</span><span class="token punctuation">,</span>
    <span class="token property">"database.history.kafka.bootstrap.servers"</span><span class="token operator">:</span> <span class="token string">"kafka:9092"</span><span class="token punctuation">,</span>
    <span class="token property">"database.history.kafka.topic"</span><span class="token operator">:</span> <span class="token string">"schema-changes.movies"</span><span class="token punctuation">,</span>
    <span class="token property">"database.hostname"</span><span class="token operator">:</span> <span class="token string">"postgres"</span><span class="token punctuation">,</span>
    <span class="token property">"database.password"</span><span class="token operator">:</span> <span class="token string">"postgres"</span><span class="token punctuation">,</span>
    <span class="token property">"database.port"</span><span class="token operator">:</span> <span class="token string">"5432"</span><span class="token punctuation">,</span>
    <span class="token property">"database.server.name"</span><span class="token operator">:</span> <span class="token string">"postgres"</span><span class="token punctuation">,</span>
    <span class="token property">"database.user"</span><span class="token operator">:</span> <span class="token string">"postgres"</span><span class="token punctuation">,</span>
    <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"movies-db-connector"</span><span class="token punctuation">,</span>
    <span class="token property">"plugin.name"</span><span class="token operator">:</span> <span class="token string">"pgoutput"</span><span class="token punctuation">,</span>
    <span class="token property">"table.include.list"</span><span class="token operator">:</span> <span class="token string">"public.movies"</span><span class="token punctuation">,</span>
    <span class="token property">"tasks.max"</span><span class="token operator">:</span> <span class="token string">"1"</span><span class="token punctuation">,</span>
    <span class="token property">"topic.creation.default.cleanup.policy"</span><span class="token operator">:</span> <span class="token string">"delete"</span><span class="token punctuation">,</span>
    <span class="token property">"topic.creation.default.partitions"</span><span class="token operator">:</span> <span class="token string">"1"</span><span class="token punctuation">,</span>
    <span class="token property">"topic.creation.default.replication.factor"</span><span class="token operator">:</span> <span class="token string">"1"</span><span class="token punctuation">,</span>
    <span class="token property">"topic.creation.default.retention.ms"</span><span class="token operator">:</span> <span class="token string">"604800000"</span><span class="token punctuation">,</span>
    <span class="token property">"topic.creation.enable"</span><span class="token operator">:</span> <span class="token string">"true"</span><span class="token punctuation">,</span>
    <span class="token property">"topic.prefix"</span><span class="token operator">:</span> <span class="token string">"postgres"</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"movies-db-connector"</span><span class="token punctuation">,</span>
  <span class="token property">"tasks"</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"source"</span>
<span class="token punctuation">}</span></code></pre>
<h3 id="list-kafka-topics" tabindex="-1">List Kafka Topics <a class="header-anchor" href="#list-kafka-topics"></a></h3>
<p>If there was no issue running the above steps we could confirm that our connector is working fine by checking if the topic is created for <code>movies</code> table by the connector.</p>
<pre class="language-bash"><code class="language-bash">❯ kafka-topics --bootstrap-server localhost:9092 <span class="token parameter variable">--list</span>
__consumer_offsets
_schemas
connect_configs
connect_offsets
connect_statuses
postgres.public.movies</code></pre>
<p>As you could see from the above command we have <code>postgres.public.movies</code> a topic created by debezium. The topic name pattern is of a type <code>topic_prefix_config.schema.table</code> so the prefix is what we configured and the other part is fetched by the debezium from the database schema</p>
<h3 id="reading-the-data" tabindex="-1">Reading the data <a class="header-anchor" href="#reading-the-data"></a></h3>
<p>Now we know that the topic is created next we would check the data available on the topic.</p>
<p>There would be data present in the topic because when the connector starts it takes an initial snapshot of the database table. This is a default config named <code>snapshot.mode</code> which we didn't configure but is set to <code>initial</code> which means that the connector will do a snapshot on the initial run when it doesn't find the last known offset from the transaction log available for the database server, to understand more about this configuration and others read more <a href="https://debezium.io/documentation/reference/2.1/connectors/postgresql.html#postgresql-property-snapshot-mode">here</a>.</p>
<pre class="language-bash"><code class="language-bash">kafka-console-consumer --bootstrap-server localhost:9092 <span class="token parameter variable">--topic</span> postgres.public.movies --from-beginning
<span class="token punctuation">{</span>
	<span class="token string">"schema"</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
		<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"struct"</span>,
		<span class="token string">"fields"</span><span class="token builtin class-name">:</span> <span class="token punctuation">[</span>
			<span class="token punctuation">{</span>
				<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"struct"</span>,
				<span class="token string">"fields"</span><span class="token builtin class-name">:</span> <span class="token punctuation">[</span>
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"int64"</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"id"</span>
					<span class="token punctuation">}</span>,
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"string"</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"title"</span>
					<span class="token punctuation">}</span>,
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"int32"</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"year"</span>
					<span class="token punctuation">}</span>,
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"string"</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"director"</span>
					<span class="token punctuation">}</span>,
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"struct"</span>,
						<span class="token string">"fields"</span><span class="token builtin class-name">:</span> <span class="token punctuation">[</span>
							<span class="token punctuation">{</span>
								<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"int32"</span>,
								<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
								<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"scale"</span>
							<span class="token punctuation">}</span>,
							<span class="token punctuation">{</span>
								<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"bytes"</span>,
								<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
								<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"value"</span>
							<span class="token punctuation">}</span>
						<span class="token punctuation">]</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
						<span class="token string">"name"</span><span class="token builtin class-name">:</span> <span class="token string">"io.debezium.data.VariableScaleDecimal"</span>,
						<span class="token string">"version"</span><span class="token builtin class-name">:</span> <span class="token number">1</span>,
						<span class="token string">"doc"</span><span class="token builtin class-name">:</span> <span class="token string">"Variable scaled decimal"</span>,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"rating"</span>
					<span class="token punctuation">}</span>
				<span class="token punctuation">]</span>,
				<span class="token string">"optional"</span><span class="token builtin class-name">:</span> true,
				<span class="token string">"name"</span><span class="token builtin class-name">:</span> <span class="token string">"postgres.public.movies.Value"</span>,
				<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"before"</span>
			<span class="token punctuation">}</span>,
			<span class="token punctuation">{</span>
				<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"struct"</span>,
				<span class="token string">"fields"</span><span class="token builtin class-name">:</span> <span class="token punctuation">[</span>
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"int64"</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"id"</span>
					<span class="token punctuation">}</span>,
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"string"</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"title"</span>
					<span class="token punctuation">}</span>,
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"int32"</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"year"</span>
					<span class="token punctuation">}</span>,
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"string"</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"director"</span>
					<span class="token punctuation">}</span>,
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"struct"</span>,
						<span class="token string">"fields"</span><span class="token builtin class-name">:</span> <span class="token punctuation">[</span>
							<span class="token punctuation">{</span>
								<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"int32"</span>,
								<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
								<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"scale"</span>
							<span class="token punctuation">}</span>,
							<span class="token punctuation">{</span>
								<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"bytes"</span>,
								<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
								<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"value"</span>
							<span class="token punctuation">}</span>
						<span class="token punctuation">]</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
						<span class="token string">"name"</span><span class="token builtin class-name">:</span> <span class="token string">"io.debezium.data.VariableScaleDecimal"</span>,
						<span class="token string">"version"</span><span class="token builtin class-name">:</span> <span class="token number">1</span>,
						<span class="token string">"doc"</span><span class="token builtin class-name">:</span> <span class="token string">"Variable scaled decimal"</span>,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"rating"</span>
					<span class="token punctuation">}</span>
				<span class="token punctuation">]</span>,
				<span class="token string">"optional"</span><span class="token builtin class-name">:</span> true,
				<span class="token string">"name"</span><span class="token builtin class-name">:</span> <span class="token string">"postgres.public.movies.Value"</span>,
				<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"after"</span>
			<span class="token punctuation">}</span>,
			<span class="token punctuation">{</span>
				<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"struct"</span>,
				<span class="token string">"fields"</span><span class="token builtin class-name">:</span> <span class="token punctuation">[</span>
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"string"</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"version"</span>
					<span class="token punctuation">}</span>,
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"string"</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"connector"</span>
					<span class="token punctuation">}</span>,
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"string"</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"name"</span>
					<span class="token punctuation">}</span>,
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"int64"</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"ts_ms"</span>
					<span class="token punctuation">}</span>,
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"string"</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> true,
						<span class="token string">"name"</span><span class="token builtin class-name">:</span> <span class="token string">"io.debezium.data.Enum"</span>,
						<span class="token string">"version"</span><span class="token builtin class-name">:</span> <span class="token number">1</span>,
						<span class="token string">"parameters"</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
							<span class="token string">"allowed"</span><span class="token builtin class-name">:</span> <span class="token string">"true,last,false,incremental"</span>
						<span class="token punctuation">}</span>,
						<span class="token string">"default"</span><span class="token builtin class-name">:</span> <span class="token string">"false"</span>,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"snapshot"</span>
					<span class="token punctuation">}</span>,
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"string"</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"db"</span>
					<span class="token punctuation">}</span>,
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"string"</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> true,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"sequence"</span>
					<span class="token punctuation">}</span>,
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"string"</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"schema"</span>
					<span class="token punctuation">}</span>,
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"string"</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"table"</span>
					<span class="token punctuation">}</span>,
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"int64"</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> true,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"txId"</span>
					<span class="token punctuation">}</span>,
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"int64"</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> true,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"lsn"</span>
					<span class="token punctuation">}</span>,
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"int64"</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> true,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"xmin"</span>
					<span class="token punctuation">}</span>
				<span class="token punctuation">]</span>,
				<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
				<span class="token string">"name"</span><span class="token builtin class-name">:</span> <span class="token string">"io.debezium.connector.postgresql.Source"</span>,
				<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"source"</span>
			<span class="token punctuation">}</span>,
			<span class="token punctuation">{</span>
				<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"string"</span>,
				<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
				<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"op"</span>
			<span class="token punctuation">}</span>,
			<span class="token punctuation">{</span>
				<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"int64"</span>,
				<span class="token string">"optional"</span><span class="token builtin class-name">:</span> true,
				<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"ts_ms"</span>
			<span class="token punctuation">}</span>,
			<span class="token punctuation">{</span>
				<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"struct"</span>,
				<span class="token string">"fields"</span><span class="token builtin class-name">:</span> <span class="token punctuation">[</span>
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"string"</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"id"</span>
					<span class="token punctuation">}</span>,
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"int64"</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"total_order"</span>
					<span class="token punctuation">}</span>,
					<span class="token punctuation">{</span>
						<span class="token string">"type"</span><span class="token builtin class-name">:</span> <span class="token string">"int64"</span>,
						<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
						<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"data_collection_order"</span>
					<span class="token punctuation">}</span>
				<span class="token punctuation">]</span>,
				<span class="token string">"optional"</span><span class="token builtin class-name">:</span> true,
				<span class="token string">"name"</span><span class="token builtin class-name">:</span> <span class="token string">"event.block"</span>,
				<span class="token string">"version"</span><span class="token builtin class-name">:</span> <span class="token number">1</span>,
				<span class="token string">"field"</span><span class="token builtin class-name">:</span> <span class="token string">"transaction"</span>
			<span class="token punctuation">}</span>
		<span class="token punctuation">]</span>,
		<span class="token string">"optional"</span><span class="token builtin class-name">:</span> false,
		<span class="token string">"name"</span><span class="token builtin class-name">:</span> <span class="token string">"postgres.public.movies.Envelope"</span>,
		<span class="token string">"version"</span><span class="token builtin class-name">:</span> <span class="token number">1</span>
	<span class="token punctuation">}</span>,
	<span class="token string">"payload"</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
		<span class="token string">"before"</span><span class="token builtin class-name">:</span> null,
		<span class="token string">"after"</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
			<span class="token string">"id"</span><span class="token builtin class-name">:</span> <span class="token number">1</span>,
			<span class="token string">"title"</span><span class="token builtin class-name">:</span> <span class="token string">"The Shawshank Redemption"</span>,
			<span class="token string">"year"</span><span class="token builtin class-name">:</span> <span class="token number">1994</span>,
			<span class="token string">"director"</span><span class="token builtin class-name">:</span> <span class="token string">"Frank Darabont"</span>,
			<span class="token string">"rating"</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
				<span class="token string">"scale"</span><span class="token builtin class-name">:</span> <span class="token number">1</span>,
				<span class="token string">"value"</span><span class="token builtin class-name">:</span> <span class="token string">"XQ=="</span>
			<span class="token punctuation">}</span>
		<span class="token punctuation">}</span>,
		<span class="token string">"source"</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
			<span class="token string">"version"</span><span class="token builtin class-name">:</span> <span class="token string">"2.1.1.Final"</span>,
			<span class="token string">"connector"</span><span class="token builtin class-name">:</span> <span class="token string">"postgresql"</span>,
			<span class="token string">"name"</span><span class="token builtin class-name">:</span> <span class="token string">"postgres"</span>,
			<span class="token string">"ts_ms"</span><span class="token builtin class-name">:</span> <span class="token number">1675103983563</span>,
			<span class="token string">"snapshot"</span><span class="token builtin class-name">:</span> <span class="token string">"first"</span>,
			<span class="token string">"db"</span><span class="token builtin class-name">:</span> <span class="token string">"movies_db"</span>,
			<span class="token string">"sequence"</span><span class="token builtin class-name">:</span> <span class="token string">"[null,<span class="token entity" title="\&quot;">\"</span>26612016<span class="token entity" title="\&quot;">\"</span>]"</span>,
			<span class="token string">"schema"</span><span class="token builtin class-name">:</span> <span class="token string">"public"</span>,
			<span class="token string">"table"</span><span class="token builtin class-name">:</span> <span class="token string">"movies"</span>,
			<span class="token string">"txId"</span><span class="token builtin class-name">:</span> <span class="token number">744</span>,
			<span class="token string">"lsn"</span><span class="token builtin class-name">:</span> <span class="token number">26612016</span>,
			<span class="token string">"xmin"</span><span class="token builtin class-name">:</span> null
		<span class="token punctuation">}</span>,
		<span class="token string">"op"</span><span class="token builtin class-name">:</span> <span class="token string">"r"</span>,
		<span class="token string">"ts_ms"</span><span class="token builtin class-name">:</span> <span class="token number">1675103983739</span>,
		<span class="token string">"transaction"</span><span class="token builtin class-name">:</span> null
	<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
----- <span class="token function">more</span> data ommitted <span class="token keyword">for</span> readability purpose -----</code></pre>
<h3 id="cleanup" tabindex="-1">Cleanup <a class="header-anchor" href="#cleanup"></a></h3>
<p>By running the below command all the services will be shut down and the resources would be released</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">docker</span> compose <span class="token parameter variable">-f</span> docker-compose.yml <span class="token parameter variable">-v</span> down</code></pre>
<p>Here we specify <code>-v</code> option to also remove any volumes created by the docker-compose, this will also free the disk space allocated to the containers</p>
<h3 id="debezium-ui" tabindex="-1">Debezium UI <a class="header-anchor" href="#debezium-ui"></a></h3>
<p>Debezium also provides a control dashboard. You could use it to add a new connector instead of using the REST API. The dashboard also provides the functionality to Pause or Restart the debezium task and also to delete the connector</p>
<p>Go to <code>http://localhost:8080</code> and you will be able to access the dashboard as shown below</p>
<figure><img src="/images/docker-compose-for-your-next-debezium-and-postgres-project/connectors.avif" alt="Debezium Dashboard"><figcaption>Debezium Dashboard</figcaption></figure>
<p>The Dashboard also allows you to add new connectors for other database providers</p>
<figure><img src="/images/docker-compose-for-your-next-debezium-and-postgres-project/add-new.avif" alt="Adding new connector"><figcaption>Add new Connector</figcaption></figure>
<h2 id="aws-rds" tabindex="-1">AWS RDS <a class="header-anchor" href="#aws-rds"></a></h2>
<p>Setting up docker-compose is easy because everything is local and we could use the configuration described by the Postgres documentation.</p>
<p>On AWS, it's a different story, on AWS we have to configure <code>rds.logical_replication</code> property in the parameter groups of your Postgres instance. The default value for this property is <code>0</code> which means the logical replication is disabled by default, however, setting it to <code>1</code> will enable the logical replication. An important thing that you should know is that when you change this property on AWS you would need to restart your AWS RDS Postgres instance. If your application is in production that means you would need some downtime to enable the replication. You could read more about this and the steps to do it in AWS RDS <a href="https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.Replication.Logical.html#AuroraPostgreSQL.Replication.Logical.Configure">here</a></p>
<hr>
<p>This brings us to the end of this small and quick setup of Postgres and Debezium using Docker Compose. Hope, next time you are building any CDC-related consumer this docker-compose setup will help you to run the infrastructure locally without any hassle.</p>
<p>If you like the blog, please don't forget to like the post, follow me on <a href="https://medium.com/@iamninad">Medium</a> also don't forget to subscribe on Medium.</p>
<h2 id="code" tabindex="-1">Code <a class="header-anchor" href="#code"></a></h2>
<ul>
<li><a href="https://github.com/ninadingole/docker-compose-stacks">Github</a></li>
</ul>

                ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Docker Compose For Prometheus + Grafana</title>
            <link href="https://iamninad.com/posts/docker-compose-for-prometheus-grafana/"/>
            <updated>2021-02-25T00:00:00Z</updated>
            <id>https://iamninad.com/posts/docker-compose-for-prometheus-grafana/</id>
            <content type="html">
                <![CDATA[
                <p>It becomes important that with all the tools you have in production, you can test the same flows end to end on local with very fewer efforts. The rationale behind such is the reduced feedback cycle that saves a dev from taking a long time to achieve the desired outcome.</p>
<p>I was working with sending some telemetry data from my Golang web application to Prometheus and then create a Grafana dashboard out of it. But to test the flow I needed a local setup of Prometheus + Grafana so that I can check if the metrics are right and that I am building the right PromQL query to create the dashboard.</p>
<p>I am maintaining a Github repo for all the docker-compose setup I require for my local testing and now Prometheus + Grafana is a new addition to it. If you also need a similar setup and save your setup time in future and focus more on building things refer to this post or my Github Repository.</p>
<p>Clone the repo:: <code>https://github.com/ninadingole/docker-compose-stacks</code></p>
<p>Then go to prometheus-grafana folder and run <code>docker-compose up -d</code>.</p>
<p>This will start Prometheus on <code>http://localhost:9090</code> and Grafana on <code>http://localhost:3000</code>.</p>
<figure><img src="/images/prometheus-grafana-docker-compose/scrnli_25_02_2021_18-05-25.png" alt="Prometheus running on localhost::9090"></figure>
<figure><img src="/images/prometheus-grafana-docker-compose/scrnli_25_02_2021_18-04-30.png" alt="Grafana settings to connect to local Prometheus"></figure>
<p>There is also a prometheus.yml configuration file which you can use to add the local apps that you want to scrape, a note:: if your application is running inside a docker then use host.docker.internal as your hostname with the port to scrape the target.</p>
<p>Once you have added the configs to connect Grafana to Prometheus like above image, you are ready with an end-to-end setup on your local.</p>
<hr>
<p>I hope you will find this docker-compose configuration pretty useful and saves your time. Please subscribe to the blog to get more articles delivered right to your email inbox.</p>
<p>Thanks and Happy Coding!</p>
<h2 id="reference" tabindex="-1">Reference <a class="header-anchor" href="#reference"></a></h2>
<ul>
<li><a href="https://github.com/ninadingole/docker-compose-stacks">repo</a></li>
</ul>

                ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Github Dependabot Alerts</title>
            <link href="https://iamninad.com/posts/github-dependabot-alerts/"/>
            <updated>2020-08-15T00:00:00Z</updated>
            <id>https://iamninad.com/posts/github-dependabot-alerts/</id>
            <content type="html">
                <![CDATA[
                <p>Security is a major concern for any business or product, and with the increasing number of methodologies and toolkits to easily exploits the applications it becomes a more serious issue that needs to be focused on.</p><p>I liked the definition of <strong>"Vulnerability"</strong> from the Github's documentation:</p><blockquote>A vulnerability is a problem in a project's code that could be exploited to damage the confidentiality, integrity, or availability of the project or other projects that use its code. Vulnerabilities vary in type, severity, and method of attack.<br><br>When your code depends on a package that has a security vulnerability, this vulnerable dependency can cause a range of problems for your project or the people who use it.</blockquote><p>My observation as a developer is when we are developing an internal system or application for any client and if it's not a product we will rarely upgrade the dependencies because most of the time we upgrade those dependencies only to overcome any issue or bugfix.</p><p>Other than internal application or services, If we are working on any products we will keep on upgrading the third-party dependencies frequently but not all of them, only those that we are working on most and your application majorly depend on them, or in case there was a bug with the current version which got fixed in a newer version or some additional functionality is added to the library that will benefit the application.</p><p>However, what happens when the dependency is at risk, how would we get to know about such information? Will you keep a dedicated person to keep track of it 😝? or you will do it only when you get impacted by some serious exploit to your application? or you might have a static code analysis system in place which checks for any vulnerability in the code. However, what about the dependencies even in that case?</p><p>We need some kind of automated way to deal with this issue, and this is the exact issue that Github tried to solve and came up with this cool solution "Dependabot".</p><p>Dependabot will alert you whenever there is a vulnerable dependency found in your Github repository. Dependabot will refer the <a href="https://nvd.nist.gov/">National Vulnerability Database</a>, a combination of machine learning and human review to detect vulnerabilities in public commits on GitHub, Security advisories reported on GitHub, and <a href="https://github.com/FriendsOfPHP/security-advisories">FriendsOfPHP</a>, and will use information from all these multiple sources to alert you.</p><p>As shown below, Dependabot works with a wide range of package managers &amp; support languages that are widely used in the industry. Dependabot is still in beta, however, with future releases, you will see more of the tools support added to Dependabot.</p>
<figure><img src="/images/github-dependabot-alerts/Screenshot-2020-08-08-at-2.18.14-PM.png" alt="Supported Package Ecosystem"><figcaption>Supported Package Ecosystem</figcaption></figure>
<p>In this post, will see how to enable Dependabot in Github public repo, it's simple and has easy to configure steps.</p><hr><h3 id="let-s-go-">Let's Go:</h3><ol><li>Go to the security tab of the repository, and you will see the below screen, click on the <code>Enable Dependabot alerts</code>.</li></ol>
<figure><img src="/images/github-dependabot-alerts/Screenshot-2020-07-30-at-12.53.57-PM.png" alt="Enable Dependabot alerts"><figcaption>Enable Dependabot alerts</figcaption></figure>
<p>You will be shown the below screen which has two independent configurations, enable them based on your requirement.</p><ol><li><strong>Dependabot alerts:</strong><br>It will enable the dependabot to only show an alert on the main page when there's any vulnerability found in your repo.</li><li><strong>Dependabot security update: <sup>[1]</sup></strong><br>It will raise a PR for upgrading any vulnerable dependencies to a safer version of those dependencies.</li></ol>
<figure><img src="/images/github-dependabot-alerts/Screenshot-2020-08-03-at-11.00.27-AM.png" alt="Configuration screen for dependabot alerts"><figcaption>Configuration screen for dependabot alerts</figcaption></figure>
<p>Once you enable the above options, it's all done. It's that easy to have this amazing functionality enabled for your repository.</p><p>In the below screen you can see I got an alert for security risk in one of my repository in ExpressJS project.</p>
<figure><img src="/images/github-dependabot-alerts/Screenshot-2020-07-29-at-7.43.45-PM.png" alt="Dependabot alerts for a vulnerable dependency in the repository"><figcaption>Dependabot alerts for a vulnerable dependency in the repository</figcaption></figure>
<p>On clicking <code>See Dependabot alert</code>, I found that the mongoose library that I am using is having a security issue with version <code>4.7.5</code>. The details of the alert show me that the remediation is to upgrade the library to version <code>&gt;=5.7.5</code> and as my project is a NodeJS project it shows me how to do that in my <code>package.json</code> file.</p><p>Below is the remediation you can see the details of the security vulnerability, in this case, its allowing attackers to bypass access control 😝</p>
<figure><img src="/images/github-dependabot-alerts/Screenshot-2020-07-29-at-7.44.04-PM.png" alt="Details of the Issue"><figcaption>Details of the Issue</figcaption></figure>
<p>How to fix this issue now? The details already show how to do it manually, but while enabling dependabot there's the second option that will automatically raise a PR for the version upgrade.</p><p>For this repository, I didn't enable the second option <strong><sup>[1]</sup></strong>. However, there's also another way. Click on <code>Create Dependabot security update</code> button in the above page, and it will start creating a PR for you, this is also a manual approach, and as you can see in the below image you will see a notification generated by the dependabot.</p>
<figure><img src="/images/github-dependabot-alerts/Screenshot-2020-07-29-at-7.44.26-PM.png" alt=""></figure>
<p>If you go to the <code>Pull Request</code> section of the repository you would see a Pull-Request being raised by the dependabot with tag <code>dependencies</code> I have seen similar PR's in a lot of open-source repositories. </p>
<figure><img src="/images/github-dependabot-alerts/Screenshot-2020-07-29-at-7.49.49-PM.png" alt="Dependabot Pull Request For the Issue"><figcaption>Dependabot Pull Request For the Issue</figcaption></figure>
<p>And the same PR reference/link you will see in the security alert details now.</p>
<figure><img src="/images/github-dependabot-alerts/Screenshot-2020-07-29-at-7.49.37-PM.png" alt="Pull Request Notification for Security Incident"><figcaption>Pull Request Notification for Security Incident</figcaption></figure>
<p>Further drilling down into the details of PR you could see more information about the PR, the PR upgrade the mongoose dependency to version <code>5.9.26</code> which is what was given in the remediation to upgrade to anything <code>&gt;=5.7.5</code>. It also shows that the severity of this issue is <code>moderate</code>. Dependabot categories issue in four such categories you can read more about them <a href="https://www.first.org/cvss/specification-document">here</a>.</p><ul><li>Low</li><li>Moderate</li><li>High</li><li>Critical</li></ul><p>I didn't have any CI setup for this repository. However, if you have a test suite in the repository then this will also run all your test cases to see if this version works or not.</p>
<figure><img src="/images/github-dependabot-alerts/Screenshot-2020-07-29-at-7.50.07-PM.png" alt="details of the pull-request"><figcaption>details of the pull-request</figcaption></figure>
<p>You can also see a Changelog for the recent changes to the library.</p>
<figure><img src="/images/github-dependabot-alerts/Screenshot-2020-07-30-at-12.56.29-PM.png" alt="Changelog for the mongoose library"><figcaption>Changelog for the mongoose library</figcaption></figure>
<p>And there are some dependabot action commands as shown below that you can use in your comments to trigger actions like if you want to merge this PR instead of clicking on the merge button you can just comment in the PR <code>@dependabot merge</code> and this will merge the PR. You can squash, close, ignore and do all the below-given actions using comments.</p>
<figure><img src="/images/github-dependabot-alerts/Screenshot-2020-07-30-at-12.56.52-PM.png" alt="Dependabot commands"><figcaption>Dependabot commands</figcaption></figure>
<p>This is what the diff of the PR shows, the bot just updated a single line in my <code>package.json</code> file.</p>
<figure><img src="/images/github-dependabot-alerts/Screenshot-2020-07-30-at-12.57.17-PM.png" alt="Diff for &lt;code&gt;package.json&lt;/code&gt;"><figcaption>Diff for <code>package.json</code></figcaption></figure>
<p>Once I merged the PR, this is the file content of my <code>package.json</code> 😀.</p>
<figure><img src="/images/github-dependabot-alerts/Screenshot-2020-07-29-at-7.50.51-PM.png" alt="Updated package.json"><figcaption>Updated package.json</figcaption></figure>
<hr>
<p>Wow, this will be the easiest thing to configure for the next project and comes with so many benefits. I hope this little blog post helps you to get rid of all those vulnerable dependencies in your project and keeps your business and application safe from some level of security threats. Make sure security is always a priority from the start of your project.</p><p>For any issues while following the steps or with the content do let me know down in the comments or email me using my contact page.</p><p>Don't forget to share the post with your friends &amp; colleagues. Happy Coding!</p>

                ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Github Code Scanning</title>
            <link href="https://iamninad.com/posts/github-code-scanning/"/>
            <updated>2020-07-26T00:00:00Z</updated>
            <id>https://iamninad.com/posts/github-code-scanning/</id>
            <content type="html">
                <![CDATA[
                <p>Have you ever done code scanning of your code for vulnerabilities or code error before? No? Don't worry even I wasn't aware of the same when I started my career as a developer. Many organization do follow this as a best practice and a must before moving the application to production. This helps to mitigate any security vulnerabilities or error in the application after it is deployed to production avoiding any business impact or monitory losses.</p>
<p>There are many code scanning tools available some are proprietary licensed products, and some are a free tool, and it requires some efforts to set up with your existing CI/CD setup. The one which I have seen is <a href="https://www.veracode.com/">Veracode</a>, which is a proprietary product and provides information about any security risk or code error by scanning the entire code base, even the dependencies I believe, and then there is <a href="https://www.sonarqube.org/">SonarQube</a> widely used by many organization and many of you might be aware of, it's a static code analyser and provides information regarding any security risk or code error.</p>
<p>Github, which is the most popular platform for open source development came up with a new service that allows code scanning of the repository for security vulnerabilities and any coding errors. You can use code scanning to find, triage, and prioritise fixes for existing problems in your code. Code scanning also prevents developers from introducing new problems. You can schedule scans for specific days and times, or trigger scans when a specific event occurs in the repository, such as a push.</p>
<p>If code scanning finds a potential vulnerability or error in your code, GitHub displays an alert in the repository. After you fix the code that triggered the alert, GitHub closes the alert. Code Scanning is a new service and is still in beta and lots of scanning rules are work in progress like passwords leaked in java properties file is still not available, however as the service becomes more stable will have all such cases available in CodeQL rules database.</p>
<p>By default, code scanning uses CodeQL, a semantic code analysis engine. CodeQL treats code as data, allowing you to find potential vulnerabilities in your code with greater confidence than traditional static analyzers. You can use CodeQL to find all variants of vulnerability, and remove all the variants from your code.</p>
<p>QL is the query language that powers CodeQL. QL is an object-oriented logic programming language. GitHub, language experts, and security researchers create the queries used for code scanning, and the queries are open source. The community maintains and updates the queries to improve analysis and reduce false positives. For more information, see <a href="https://securitylab.github.com/tools/codeql">CodeQL</a> on the GitHub Security Lab website.</p>
<p>In this short tutorial, will see how to configure code scanning for a Java-based project. Code scanning supports both compiled and interpreted languages and can find vulnerabilities and errors in code that's written in the supported languages.</p>
<ul>
<li>C/C++</li>
<li>C#</li>
<li>Go</li>
<li>Java</li>
<li>Javascript/Typescript</li>
<li>Python</li>
</ul>
<blockquote>
<p>Github Code Scanning is still in beta and access is limited to users on an invitation basis, follow the below steps when you have access to the service</p>
</blockquote>
<h2 id="code-scannning-vs-sonarqube" tabindex="-1">Code Scannning vs SonarQube <a class="header-anchor" href="#code-scannning-vs-sonarqube"></a></h2>
<p>I am seeing a lot of people looking for this comparison. Code scanning is a new tool which currently using CodeQL under the hood to scanning code for any security vulnerability. It's new but a lot of security researchers are sharing the findings in CodeQL repo, so you will have your code check against those latest findings. Code Scanning deals more with the Security and coding errors not the static code check analysis what SonarQube provides for every supported language.</p>
<p>SonarQube is used by many organization it has comprehensive set of checks and standards that acts as a quality gate in application development.</p>
<p>SonarQube is very mature product as compared to code scanning, code scanning is new but you never know what the future holds for it.</p>
<hr>
<h3 id="let's-start-%F0%9F%8F%83%F0%9F%8F%BB%E2%80%8D%E2%99%82%EF%B8%8F" tabindex="-1">Let's start 🏃🏻‍♂️ <a class="header-anchor" href="#let's-start-%F0%9F%8F%83%F0%9F%8F%BB%E2%80%8D%E2%99%82%EF%B8%8F"></a></h3>
<p>The first thing you need to do is navigate to the security tab of the repository</p>
<figure><img src="/images/github-code-scanning/Screenshot-2020-07-25-at-1.29.00-PM.png" alt="Security Tab In Main Section"><figcaption>Security Tab In Main Section</figcaption></figure>
<p>Then you will see a below screen, and the last option you will see &quot;Code Scanning alerts&quot;, click on the <code>Setup code scanning</code> button</p>
<figure><img src="/images/github-code-scanning/Screenshot-2020-07-22-at-1.17.57-PM.png" alt="Security Options"><figcaption>Security Options</figcaption></figure>
<figure><img src="/images/github-code-scanning/Screenshot-2020-07-22-at-1.18.14-PM.png" alt="Security Scanning Setup"><figcaption>Security Scanning Setup</figcaption></figure>
<p>Code scanning uses Github Actions, You will see the above screen for CodeQL analysis setup, along with this you will also see many different options from marketplace to setup like &quot;Anchore Container Scan&quot;, &quot;OSSAR&quot; etc. For this post will be going with the default action workflow, click on the setup this workflow button for CodeQL analysis, and you will be prompted with the below screen to configure the workflow YAML.</p>
<figure><img src="/images/github-code-scanning/Screenshot-2020-07-22-at-1.19.22-PM.png" alt="CodeQL Workflow setup screen"><figcaption>CodeQL Workflow setup screen</figcaption></figure>
<p>When you see the configuration click on the <code>Start commit</code> and create a commit with the basic configuration will do the modification afterwards.</p>
<figure><img src="/images/github-code-scanning/Screenshot-2020-07-22-at-1.19.35-PM.png" alt="Commit Dialog"><figcaption>Commit Dialog</figcaption></figure>
<figure><img src="/images/github-code-scanning/Screenshot-2020-07-22-at-1.19.50-PM.png" alt="Committed CodeQL anaylsis file"><figcaption>Committed CodeQL anaylsis file</figcaption></figure>
<p>Take a pull in your repository so that you have the workflow YAML available to modify. Open the file in <code>.github/workflow</code> directory and modify the configuration as per your requirement, below are the configuration that I have done for this post.</p>
<script src="https://gist.github.com/ninadingole/a6087db34a60cb6e0b0e221aeb389287.js"></script>
<p>Few things I modified from the given workflow like I have disabled the cron scheduled option, this makes the security scan to run on given cron expression, the option <code>push</code> enables the scan to run on every commit push to the remote, and the similar <code>pull_request</code> will happen for every pull request, however in an attempt when I ran a full pack of security rule that took 19min.</p>
<p>In such case, I would recommend setting up the Security scanning as a cron once in a day mostly a nightly build so that your team will get to see the result of the security scan as the first thing at the start of the day and can prioritise fixing the bugs first. Another change I have done is adding configuration to Initialize CodeQL step as below in file <code>.github/codeql-config.yml</code></p>
<script src="https://gist.github.com/ninadingole/b3221e3ad553521af84317957d14e618.js"></script>
<p>The CodeQL actions <code>codeql-action/init@v1</code> can find the programming language by its auto-detection feature, it is something that is embedded in the action by Github developers, however, I have explicitly added java so that the step doesn't have to do extra work and saves time, and at the same time I like to make things readable instead of the abstraction magic, this helps anyone new joining your team figure out how things are configured.</p>
<p>Then there are <code>queries</code> options, this allows to specify additional scan rules, two are inbuilt in the CodeQL tool which I have specified <code>security-extended</code> and <code>security-and-quality</code> however there are also many additional security rules on the Github's CodeQL repo, you can find it <a href="https://github.com/github/codeql">here</a> when I first added the entire repo which was more than 800 rules, it took more time and many of them were not of any use for my experiment purpose so I selected a subset of those.</p>
<p>There is a syntactic way to provide the configuration as shown below, to make the custom queries to run you need to disable the default queries by setting <code>disable-default-queries: true</code>.</p>
<pre class="language-yaml"><code class="language-yaml"><span class="token key atrule">queries</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> Use an in<span class="token punctuation">-</span>repository QL pack (run queries in the my<span class="token punctuation">-</span>queries directory)
    <span class="token key atrule">uses</span><span class="token punctuation">:</span> ./my<span class="token punctuation">-</span>queries
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> Use an external JavaScript QL pack (run queries from an external repo)
    <span class="token key atrule">uses</span><span class="token punctuation">:</span> octo<span class="token punctuation">-</span>org/javascript<span class="token punctuation">-</span>qlpack@master
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> Use an external query (run a single query from an external QL pack)
    <span class="token key atrule">uses</span><span class="token punctuation">:</span> octo<span class="token punctuation">-</span>org/python<span class="token punctuation">-</span>qlpack/show_ifs.ql@master
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> Use a query suite file (run queries from a query suite in this repo)
    <span class="token key atrule">uses</span><span class="token punctuation">:</span> ./codeql<span class="token punctuation">-</span>qlpacks/complex<span class="token punctuation">-</span>python<span class="token punctuation">-</span>qlpack/rootAndBar.qls</code></pre>
<p>In the configurations, I have provided <code>github/codeql/java/ql/src/codeql-suites/java-code-scanning.qls@v1.24.0</code> this is the path to the actual GitHub <a href="https://github.com/github/codeql/tree/master/java/ql/src/codeql-suites">link</a> and I have tagged the rules for version <code>1.24.0</code> you can also point to the <code>master</code> as shown in the above configuration guide.</p>
<p>After you have done the configuration create a new commit, and push. You will see a new scan action triggered which you can view in the Actions section of the <a href="https://github.com/ninadingole/github-codescan/actions">Github repo page</a>.</p>
<figure><img src="/images/github-code-scanning/Screenshot-2020-07-25-at-8.38.27-PM.png" alt="All Actions"><figcaption>All Actions</figcaption></figure>
<p>Clicking on the individual action run will show you additional information about the scan process, in the log which is provided for the step navigate to the <code>Perform CodeQL Analysis</code> section and you can see what all security rules that were checked against the code.</p>
<figure><img src="/images/github-code-scanning/Screenshot-2020-07-22-at-1.23.45-PM.png" alt="Log for Action Workflow"><figcaption>Log for Action Workflow</figcaption></figure>
<p>Once the workflow is completed without any error, to check any security vulnerability or error in the code navigate to the Security Tab, the badge also shows the number of security risk that is present in the code, I liked this as the information is right there available on the main page of your repo and this way team can prioritise bugs to be fixed.</p>
<figure><img src="/images/github-code-scanning/Screenshot-2020-07-22-at-4.03.15-PM.png" alt="Total number of Security risk found"><figcaption>Total number of Security risk found</figcaption></figure>
<p>If you click on it and move to the code scanning alerts you can see all the vulnerabilities that are available in the code listed</p>
<figure><img src="/images/github-code-scanning/Screenshot-2020-07-26-at-6.09.15-PM-1.png" alt="Listing of all the risks"><figcaption>Listing of all the risks</figcaption></figure>
<p>The listing shows the message of the issue found, the file in which the issue was detected with the line number (very cool) and the branch in which the issue was found. Further clicking on any issue you can drill down into the actual code, the UI will highlight the line of code which has the issue, whether its a warning or an actual error and more details like the commit that caused the issue, the rule that failed and tags the issues based on the rules category. In the below image you can see the error are tagged as <code>CWE-798</code> and <code>security</code></p>
<p>You can see the details of two errors which are a security risk to my code are listed below(deliberately added for demo purpose 😛). One is because of the password leaked into the source code and the other is directly redirecting to the user-provided URL without first validating the URL.</p>
<figure><img src="/images/github-code-scanning/Screenshot-2020-07-26-at-6.08.11-PM.png" alt="Password in source code"><figcaption>Password in source code</figcaption></figure>
<figure><img src="/images/github-code-scanning/Screenshot-2020-07-26-at-6.07.41-PM.png" alt="URL redirection without validation"><figcaption>URL redirection without validation</figcaption></figure>
<p>If you click on the small show more button you can see a good help about the issue and how to avoid it, there are also links to some reference documentation that explains the issue in depth.</p>
<figure><img src="/images/github-code-scanning/Screenshot-2020-07-26-at-6.08.28-PM.png" alt="Recommendation for the cause of the issue"><figcaption>Recommendation for the cause of the issue</figcaption></figure>
<p>Once you have fixed the issue and the code is pushed the issue will be moved to close. However, at times there will be cases of false-positive in such cases there is an option provided at the top right of the issue, to manually close the issue, and has three options showing in below image, select one that suits your use case and close the issues which are not valid.</p>
<figure><img src="/images/github-code-scanning/Screenshot-2020-07-25-at-9.58.48-PM.png" alt="Options to close issue"><figcaption>Options to close issue</figcaption></figure>
<hr>
<p><strong>EDIT::</strong>
I was reading some blogs on Github and found this exciting stats::</p>
<p>Since introducing the beta in May, we’ve seen tremendous adoption within the community::</p>
<ul>
<li>We’ve scanned over 12,000 repositories 1.4 million times, and found more than 20,000 security issues including remote code execution (RCE), SQL injection, and cross site scripting (XSS) vulnerabilities.</li>
<li>Developers and maintainers fixed 72% of reported security errors identified in their pull requests before merging in the last 30 days. We’re proud to see this impact, given industry data shows that <a href="https://www.veracode.com/state-of-software-security-report">less than 30%</a> of all flaws are fixed one month after discovery.</li>
<li>We’ve had 132 community contributions to CodeQL’s open sourced query set.</li>
<li>We’ve partnered with more than a dozen open source and commercial security vendors to allow developers to run CodeQL and industry leading solutions for SAST, container scanning, and infrastructure as code validation side-by-side in GitHub’s native code scanning experience.</li>
</ul>
<hr>
<p>I hope this post helps you, if you don't see the option to enable the security scan on your repository, don't worry the tool is still in beta and access is given on invitation basis by Github. Get an invite for the service if you want to try out and It will be accessible to everyone soon.</p>
<p>The post gives a basic idea of how the scanning will work with repository there are many open-source tools, and their workflows available in the Github marketplace that you can try, however, this post will help you to get started with basic.</p>
<p>For more advance on how different tools can be integrated, what if I work at an organization who has its own set of security rules, how to implement that in CodeQL? I will write about those advance things in another post, and as I explore more of the code scanning tool I will keep on sharing.</p>
<p>For any issue while following the steps please do let me know in the comments below I will try to correct. For anything else please comment and I will try to reply as soon as possible, and please don't forget to share the post.</p>
<p>Happy Coding!</p>
<hr>
<h2 id="references%3A%3A" tabindex="-1">References:: <a class="header-anchor" href="#references%3A%3A"></a></h2>
<ul>
<li><a href="https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/about-code-scanning">Github CodeQL</a></li>
<li><a href="https://github.com/ninadingole/github-codescan">Sample Code</a></li>
<li><a href="https://github.com/github/codeql/">Github CodeQL Additional Queries</a></li>
<li><a href="https://github.com/github/codeql-go">CodeQL for GoLang</a></li>
<li><a href="https://github.blog/2020-09-30-code-scanning-is-now-available/">https:😕/github.blog/2020-09-30-code-scanning-is-now-available/</a></li>
</ul>
<p><em>Updated on 22/05/2021 :: Add comparison of code scanning vs sonarqube</em></p>

                ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Burp Suite For Web App Testing Go Lang</title>
            <link href="https://iamninad.com/posts/burp-suite-for-web-app-testing-go-lang/"/>
            <updated>2019-12-31T00:00:00Z</updated>
            <id>https://iamninad.com/posts/burp-suite-for-web-app-testing-go-lang/</id>
            <content type="html">
                <![CDATA[
                <p>Have you ever come across a scenario where you want your code to call a dependent service however need to change the response so that you can test how different your code will behave to different data?</p>
<p>Recently, I came across the same situation where I was looking for a way to change the response of the service that I was consuming and instead of mocking the entire service using a tool like Postman or wire mock, I wanted to hit the actual service and then change a few fields to see if my error handling works as per the expectations.</p>
<p>Normally, we do write an integration test where we mock the service response using wiremock and then write the test for such edge cases. However, sometimes when we do manual testing and we want a way to mock the service response we need some mechanism to intercept the service response and modify the response. This is where Burp suites will help, Burp suites acts like a proxy that will call the actual service on behalf of you and then provides you with tools that can help to easily modify the response and send it back to your application.</p>
<p>For this post, I will be consuming <code>themoviesdb.org</code> API's to see details of &quot;Fight Club&quot; movie, and then I will write an application in golang which will connect to Burp Suite, there we modify the response using Burpsuite UI and print the modified response in the console which is received by our application.</p>
<pre class="language-go"><code class="language-go"><span class="token keyword">package</span> main
<span class="token keyword">import</span> <span class="token punctuation">(</span>
	<span class="token string">"crypto/tls"</span>
	<span class="token string">"encoding/json"</span>
	<span class="token string">"fmt"</span>
	<span class="token string">"net/http"</span>
	<span class="token string">"net/url"</span>
	<span class="token string">"os"</span>
<span class="token punctuation">)</span>

<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

	proxyURL<span class="token punctuation">,</span> e <span class="token operator">:=</span> url<span class="token punctuation">.</span><span class="token function">Parse</span><span class="token punctuation">(</span>os<span class="token punctuation">.</span><span class="token function">Getenv</span><span class="token punctuation">(</span><span class="token string">"PROXY"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
	<span class="token keyword">if</span> e <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
		<span class="token function">panic</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span>
	<span class="token punctuation">}</span>

	client <span class="token operator">:=</span> <span class="token operator">&amp;</span>amp<span class="token punctuation">;</span>http<span class="token punctuation">.</span>Client<span class="token punctuation">{</span>
		<span class="token comment">//Timeout: 20 * time.Second,</span>
		Transport<span class="token punctuation">:</span> <span class="token operator">&amp;</span>amp<span class="token punctuation">;</span>http<span class="token punctuation">.</span>Transport<span class="token punctuation">{</span>
			Proxy<span class="token punctuation">:</span> http<span class="token punctuation">.</span><span class="token function">ProxyURL</span><span class="token punctuation">(</span>proxyURL<span class="token punctuation">)</span><span class="token punctuation">,</span>
			TLSClientConfig<span class="token punctuation">:</span> <span class="token operator">&amp;</span>amp<span class="token punctuation">;</span>tls<span class="token punctuation">.</span>Config<span class="token punctuation">{</span>InsecureSkipVerify<span class="token punctuation">:</span><span class="token boolean">true</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
		<span class="token punctuation">}</span><span class="token punctuation">,</span>
	<span class="token punctuation">}</span>

	get<span class="token punctuation">,</span> err <span class="token operator">:=</span> client<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span>fmt<span class="token punctuation">.</span><span class="token function">Sprintf</span><span class="token punctuation">(</span><span class="token string">"https://api.themoviedb.org/3/movie/550?api_key=%s"</span><span class="token punctuation">,</span> os<span class="token punctuation">.</span><span class="token function">Getenv</span><span class="token punctuation">(</span><span class="token string">"KEY"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
	<span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
		<span class="token function">panic</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>
	<span class="token punctuation">}</span>

	<span class="token keyword">var</span> data <span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">string</span><span class="token punctuation">]</span><span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span>
	err <span class="token operator">=</span> json<span class="token punctuation">.</span><span class="token function">NewDecoder</span><span class="token punctuation">(</span>get<span class="token punctuation">.</span>Body<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Decode</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>amp<span class="token punctuation">;</span>data<span class="token punctuation">)</span>
	<span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
		<span class="token function">panic</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>
	<span class="token punctuation">}</span>

	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"Response: %+v"</span><span class="token punctuation">,</span>data<span class="token punctuation">)</span>
<span class="token punctuation">}</span></code></pre>
<p>As you can see in the above code, we create an HTTP client with custom Transport set to proxy URL which is configured in the environment setting of the application, for burp suite the URL is <code>http://localhost:8080</code>. The TLSClient config is configured to skip ssl certificate verification using <code>InsecureSkipVerify:true</code>. Then we do a normal <code>GET</code> request to the api which will get the details of the movie id <code>550</code>.</p>
<p>Let's now start the burp suite and configure the intercept rule to only run when the domain matches <code>themoviedb.org</code>::</p>
<figure><img src="/images/burp-suite-for-web-app-testing-go-lang/Screenshot-2019-12-30-at-2.36.21-PM.png" alt="Add themoviedb domain to intercept criteria"><figcaption>Add themoviedb domain to intercept criteria</figcaption></figure>
<p>Then start the interceptor::</p>
<figure><img src="/images/burp-suite-for-web-app-testing-go-lang/Screenshot-2019-12-30-at-2.36.34-PM.png" alt="Enable Intercept"><figcaption>Enable Intercept</figcaption></figure>
<p>Now, run the go application and you will see that the request is captured by the burp suite as follows::</p>
<figure><img src="/images/burp-suite-for-web-app-testing-go-lang/Screenshot-2019-12-30-at-2.36.43-PM-1.png" alt="When the request is captured"><figcaption>When the request is captured</figcaption></figure>
<p>After you see the above screen click on the <code>Action</code> button and click <code>Do intercept</code> with <code>Response to this request</code>::</p>
<figure><img src="/images/burp-suite-for-web-app-testing-go-lang/Screenshot-2019-12-30-at-2.37.00-PM-1.png" alt="Select intercept response"><figcaption>Select intercept response</figcaption></figure>
<p>After clicking the <code>Forward</code> button, burp suite will call the actual service and will open the editor where you can edit the response, this movie is &quot;Flight Club&quot; movie and I have changed the movie name to <code>Fight Pub</code> and rating from 8.4 to 9.4. Then click the forward button again to forward the response to the golang app.</p>
<figure><img src="/images/burp-suite-for-web-app-testing-go-lang/Screenshot-2019-12-30-at-2.37.43-PM-1-.jpg" alt=""></figure>
<p>Once the application receives this response we just print it to the console and you could see that the name of the movie is now <code>Fight Pub</code> and the rating is <code>9.4</code> which is what we modified in the response.</p>
<pre class="language-log"><code class="language-log"><span class="token property">Response:</span> map<span class="token punctuation">[</span>adult<span class="token operator">:</span><span class="token boolean">false</span>
backdrop_path<span class="token operator">:</span><span class="token file-path string">/mMZRKb3NVo5ZeSPEIaNW9buLWQ0.jpg</span> belongs_to_collection<span class="token operator">:</span><span class="token operator">&amp;</span>lt<span class="token operator">;</span>nil<span class="token operator">&amp;</span>gt<span class="token operator">;</span>
budget<span class="token operator">:</span><span class="token number">6.3e+07</span>
genres<span class="token operator">:</span><span class="token punctuation">[</span>map<span class="token punctuation">[</span>id<span class="token operator">:</span><span class="token number">18</span> name<span class="token operator">:</span>Drama<span class="token punctuation">]</span><span class="token punctuation">]</span>
homepage<span class="token operator">:</span><span class="token url">http://www.foxmovies.com/movies/fight-club</span> id<span class="token operator">:</span><span class="token number">550</span> imdb_id<span class="token operator">:</span>tt0137523
original_language<span class="token operator">:</span>en
original_title<span class="token operator">:</span>Fight Pub
overview<span class="token operator">:</span>A ticking<span class="token operator">-</span>time<span class="token operator">-</span>bomb insomniac and a slippery soap salesman channel primal male aggression into a shocking new form of therapy<span class="token punctuation">.</span> Their concept catches on<span class="token punctuation">,</span> with underground <span class="token string">"fight clubs"</span> forming in every town<span class="token punctuation">,</span> until an eccentric gets in the way and ignites an out<span class="token operator">-</span>of<span class="token operator">-</span>control spiral toward oblivion<span class="token punctuation">.</span>
popularity<span class="token operator">:</span><span class="token number">58.844</span>
poster_path<span class="token operator">:</span><span class="token file-path string">/adw6Lq9FiC9zjYEpOqfq03ituwp.jpg</span>
production_companies<span class="token operator">:</span><span class="token punctuation">[</span>map<span class="token punctuation">[</span>id<span class="token operator">:</span><span class="token number">508</span> logo_path<span class="token operator">:</span><span class="token file-path string">/7PzJdsLGlR7oW4J0J5Xcd0pHGRg.png</span> name<span class="token operator">:</span>Regency Enterprises origin_country<span class="token operator">:</span>US<span class="token punctuation">]</span> map<span class="token punctuation">[</span>id<span class="token operator">:</span><span class="token number">711</span> logo_path<span class="token operator">:</span><span class="token file-path string">/tEiIH5QesdheJmDAqQwvtN60727.png</span> name<span class="token operator">:</span>Fox <span class="token number">2000</span> Pictures origin_country<span class="token operator">:</span>US<span class="token punctuation">]</span> map<span class="token punctuation">[</span>id<span class="token operator">:</span><span class="token number">20555</span> logo_path<span class="token operator">:</span><span class="token file-path string">/hD8yEGUBlHOcfHYbujp71vD8gZp.png</span> name<span class="token operator">:</span>Taurus Film origin_country<span class="token operator">:</span>DE<span class="token punctuation">]</span> map<span class="token punctuation">[</span>id<span class="token operator">:</span><span class="token number">54051</span> logo_path<span class="token operator">:</span><span class="token operator">&amp;</span>lt<span class="token operator">;</span>nil<span class="token operator">&amp;</span>gt<span class="token operator">;</span> name<span class="token operator">:</span>Atman Entertainment origin_country<span class="token operator">:</span><span class="token punctuation">]</span> map<span class="token punctuation">[</span>id<span class="token operator">:</span><span class="token number">54052</span> logo_path<span class="token operator">:</span><span class="token operator">&amp;</span>lt<span class="token operator">;</span>nil<span class="token operator">&amp;</span>gt<span class="token operator">;</span> name<span class="token operator">:</span>Knickerbocker Films origin_country<span class="token operator">:</span>US<span class="token punctuation">]</span> map<span class="token punctuation">[</span>id<span class="token operator">:</span><span class="token number">25</span> logo_path<span class="token operator">:</span><span class="token file-path string">/qZCc1lty5FzX30aOCVRBLzaVmcp.png</span> name<span class="token operator">:</span><span class="token number">20th</span> Century Fox origin_country<span class="token operator">:</span>US<span class="token punctuation">]</span> map<span class="token punctuation">[</span>id<span class="token operator">:</span><span class="token number">4700</span> logo_path<span class="token operator">:</span><span class="token file-path string">/A32wmjrs9Psf4zw0uaixF0GXfxq.png</span> name<span class="token operator">:</span>The Linson Company origin_country<span class="token operator">:</span><span class="token punctuation">]</span><span class="token punctuation">]</span>
production_countries<span class="token operator">:</span><span class="token punctuation">[</span>map<span class="token punctuation">[</span>iso_3166_1<span class="token operator">:</span>DE name<span class="token operator">:</span>Germany<span class="token punctuation">]</span> map<span class="token punctuation">[</span>iso_3166_1<span class="token operator">:</span>US name<span class="token operator">:</span>United States of America<span class="token punctuation">]</span><span class="token punctuation">]</span>
release_date<span class="token operator">:</span><span class="token date number">1999-10-15</span>
revenue<span class="token operator">:</span><span class="token number">1.00853753e+08</span>
runtime<span class="token operator">:</span><span class="token number">139</span>
spoken_languages<span class="token operator">:</span><span class="token punctuation">[</span>map<span class="token punctuation">[</span>iso_639_1<span class="token operator">:</span>en name<span class="token operator">:</span>English<span class="token punctuation">]</span><span class="token punctuation">]</span>
status<span class="token operator">:</span>Released
tagline<span class="token operator">:</span>Mischief<span class="token punctuation">.</span> Mayhem<span class="token punctuation">.</span> Soap<span class="token punctuation">.</span>
title<span class="token operator">:</span>Fight Pub
video<span class="token operator">:</span><span class="token boolean">false</span>
vote_average<span class="token operator">:</span><span class="token number">9.4</span>
vote_count<span class="token operator">:</span><span class="token number">17753</span><span class="token punctuation">]</span></code></pre>
<p>So, thats how you can connect your application to the burp suite and can intercept the response of the services to manually test the application for different cases.</p>
<p>I hope this post helps you to understand how to configure an HTTP client in your code to connect to Burp suite, I have used golang for this post because I am currently working on it. However, if you are working on any other programming language the HTTP Api's will have some way to configure the proxy as like I have done in my golang code.</p>
<p>Happy Coding!</p>

                ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Organizing Scala Tests For Faster Feedback</title>
            <link href="https://iamninad.com/posts/organizing-scala-tests-for-faster-feedback/"/>
            <updated>2019-03-18T00:00:00Z</updated>
            <id>https://iamninad.com/posts/organizing-scala-tests-for-faster-feedback/</id>
            <content type="html">
                <![CDATA[
                <p>Writing tests is a developer's mundane task, and when you follow practices like TDD or BDD, hardly you find any code without any test cases. We all might have seen the testing pyramid in agile and if not then you can read this <a href="https://martinfowler.com/articles/practical-test-pyramid.html">blog</a> by Martin Fowler on the testing pyramid.</p>
<figure><img src="/images/organizing-scala-tests-for-faster-feedback/test-pyramid.png" alt="testing pyramid by 360logica"><figcaption>testing pyramid by 360logica</figcaption></figure>
<p>In short and crisp, tests gets divided into three categories:: <em>unit test, integration/service test, and e2e/UI tests</em>. The unit test validates the functionality of each class and written on per class basis, integration test checks for the functionality of module with external systems like database, web service, and UI/e2e test the entire business flow or UI flow.</p>
<p>As you can see from the test pyramid, we should have more integration test than e2e test and more unit test than the integration test. The reason for having less integration and e2e tests is &quot;time&quot;; Integration test and e2e test interacts typically with other systems which are external or internal like in-memory DB or clusters. These tests take time to execute and are often slower.</p>
<p>And not to mention we have our CD/CI pipelines which run these tests and generate our code artifact. We also want our CI to provide us faster feedback by running these test individually, so we don't have to wait longer if there is an issue at the unit level.</p>
<p>Currently, I am working on a Big Data project which includes frameworks like Spark, HBase, Kafka, HDFS, etc. Some of our unit tests are independent of any spark code, and some unit test does require spark context, but they do not interact with external systems like HDFS and HBase. Moreover, integration test, runs an in-memory HBase cluster, in-memory mini dfs cluster and spark of course :😛. Now, these integration test shares the single running clusters amongst them and executes sequentially.</p>
<p>We have SBT as the build tool and, we have disabled the parallel execution of tests which makes the entire test suite including the unit test to run slower. I am struggling with that sometimes have to wait for 10-15mins to get the feedback about my code changes, running unit tests also runs integration test which takes time for cluster initialization of HBase and HDFS, and I was seriously looking for some alternative to this issue. Seldom I do comment out my integration suite code only to run the unit test which is again a wrong way. We need some mechanism to organize our tests such that we can execute them separately as a suite of unit, integration and e2e tests and, we only have parallel execution disabled for integration and e2e tests. It would provide developers with quick feedback by just running the unit tests.</p>
<p>In this post, I am going to share my findings on how to organize the tests and configure sbt (<strong>v1.2.8</strong>) such that it enables us to run these different scala test independently without any code hacks or commenting your test cases which is a more of an ugly way.</p>
<h2 id="integration-test" tabindex="-1">Integration Test <a class="header-anchor" href="#integration-test"></a></h2>
<p>Integration Test setting comes default in SBT. It's just a matter of configuring the modules with these settings in the build.sbt</p>
<pre class="language-scala"><code class="language-scala"><span class="token keyword">lazy</span> <span class="token keyword">val</span> module1 <span class="token operator">=</span> <span class="token punctuation">(</span>project in file<span class="token punctuation">(</span><span class="token string">"module1"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span>configs<span class="token punctuation">(</span>IntegrationTest<span class="token punctuation">)</span>
<span class="token punctuation">.</span>settings<span class="token punctuation">(</span>
Defaults<span class="token punctuation">.</span>itSettings<span class="token punctuation">,</span>
  libraryDependencies <span class="token operator">+=</span> scalatest <span class="token operator">%</span> <span class="token string">"it,test"</span>
<span class="token punctuation">)</span></code></pre>
<p>Adding &quot;it, test&quot; at the end of dependencies enables that lib to be available to both standard unit test &amp; integration test packages. After this, you have a new location to write an integration test.</p>
<pre class="language-vim"><code class="language-vim">src<span class="token operator">/</span>it<span class="token operator">/</span>scala
src<span class="token operator">/</span>it<span class="token operator">/</span>java
src<span class="token operator">/</span>it<span class="token operator">/</span>resources</code></pre>
<p>I have created an integration test per module and placed in the above location now to execute the integration test use <code>IntegrationTest / testOnly</code> or <code>it:test</code> in SBT console, and the output as::</p>
<pre class="language-log"><code class="language-log"><span class="token punctuation">[</span>info<span class="token punctuation">]</span> Compiling <span class="token number">1</span> Scala source to <span class="token file-path string">/Users/neenad/codes/tutorials/scala/sbt-learnings/module1/target/scala-2.11/it-classes</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> Run completed in <span class="token number">9</span> milliseconds<span class="token punctuation">.</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Total number of tests run:</span> <span class="token number">0</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Suites:</span> completed <span class="token number">0</span><span class="token punctuation">,</span> aborted <span class="token number">0</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Tests:</span> succeeded <span class="token number">0</span><span class="token punctuation">,</span> failed <span class="token number">0</span><span class="token punctuation">,</span> canceled <span class="token number">0</span><span class="token punctuation">,</span> ignored <span class="token number">0</span><span class="token punctuation">,</span> pending <span class="token number">0</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> No tests were executed<span class="token punctuation">.</span>
this is a integration test
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Module2IntegrationTest1:</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token operator">-</span> integration test
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> Run completed in <span class="token number">194</span> milliseconds<span class="token punctuation">.</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Total number of tests run:</span> <span class="token number">1</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Suites:</span> completed <span class="token number">1</span><span class="token punctuation">,</span> aborted <span class="token number">0</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Tests:</span> succeeded <span class="token number">1</span><span class="token punctuation">,</span> failed <span class="token number">0</span><span class="token punctuation">,</span> canceled <span class="token number">0</span><span class="token punctuation">,</span> ignored <span class="token number">0</span><span class="token punctuation">,</span> pending <span class="token number">0</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> All tests passed<span class="token punctuation">.</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> Done compiling<span class="token punctuation">.</span>
module1 integration test
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Module1IntegrationTest:</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token operator">-</span> integration test
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> Run completed in <span class="token number">134</span> milliseconds<span class="token punctuation">.</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Total number of tests run:</span> <span class="token number">1</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Suites:</span> completed <span class="token number">1</span><span class="token punctuation">,</span> aborted <span class="token number">0</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Tests:</span> succeeded <span class="token number">1</span><span class="token punctuation">,</span> failed <span class="token number">0</span><span class="token punctuation">,</span> canceled <span class="token number">0</span><span class="token punctuation">,</span> ignored <span class="token number">0</span><span class="token punctuation">,</span> pending <span class="token number">0</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> All tests passed<span class="token punctuation">.</span>
<span class="token punctuation">[</span>success<span class="token punctuation">]</span> <span class="token property">Total time:</span> <span class="token number">2</span> s<span class="token punctuation">,</span> completed <span class="token number">17</span> Mar<span class="token punctuation">,</span> <span class="token number">2019</span> <span class="token time number">5:52:42</span> PM</code></pre>
<h2 id="end-to-end-tests" tabindex="-1">End-To-End Tests <a class="header-anchor" href="#end-to-end-tests"></a></h2>
<p>Like integration test end-to-end configuration is not provided by SBT. We would need to create them and apply to the module. I have created an E2E object in the <code>project</code> folder and, the contents are as below::</p>
<pre class="language-scala"><code class="language-scala"><span class="token keyword">import</span> <span class="token namespace">sbt<span class="token punctuation">.</span></span><span class="token punctuation">{</span>Configuration<span class="token punctuation">,</span> Defaults<span class="token punctuation">,</span> Test<span class="token punctuation">,</span> inConfig<span class="token punctuation">}</span>
<span class="token keyword">import</span> <span class="token namespace">sbt<span class="token punctuation">.</span></span>_
<span class="token keyword">import</span> <span class="token namespace">sbt<span class="token punctuation">.</span></span>Keys<span class="token punctuation">.</span>_

<span class="token keyword">object</span> E2E <span class="token punctuation">{</span>
  <span class="token keyword">final</span> <span class="token keyword">val</span> E2ETest <span class="token operator">=</span> Configuration<span class="token punctuation">.</span>of<span class="token punctuation">(</span><span class="token string">"EndToEndTest"</span><span class="token punctuation">,</span> <span class="token string">"e2e"</span><span class="token punctuation">)</span> extend <span class="token punctuation">(</span>Test<span class="token punctuation">)</span>
  <span class="token keyword">final</span> <span class="token keyword">val</span> e2eSettings <span class="token operator">=</span>
    inConfig<span class="token punctuation">(</span>E2ETest<span class="token punctuation">)</span><span class="token punctuation">(</span>e2eConfig<span class="token punctuation">)</span>
  <span class="token keyword">lazy</span> <span class="token keyword">val</span> e2eConfig <span class="token operator">=</span>
      Defaults<span class="token punctuation">.</span>configSettings <span class="token operator">++</span> Defaults<span class="token punctuation">.</span>testTasks <span class="token operator">++</span> Seq<span class="token punctuation">(</span>
    scalaSource in E2ETest <span class="token operator">:</span><span class="token operator">=</span> baseDirectory<span class="token punctuation">.</span>value <span class="token operator">/</span> <span class="token string">"src"</span> <span class="token operator">/</span> <span class="token string">"e2e"</span> <span class="token operator">/</span> <span class="token string">"scala"</span><span class="token punctuation">,</span>
    javaSource in E2ETest <span class="token operator">:</span><span class="token operator">=</span> baseDirectory<span class="token punctuation">.</span>value <span class="token operator">/</span> <span class="token string">"src"</span> <span class="token operator">/</span> <span class="token string">"e2e"</span> <span class="token operator">/</span> <span class="token string">"java"</span><span class="token punctuation">,</span>
    resourceDirectory in E2ETest <span class="token operator">:</span><span class="token operator">=</span> baseDirectory<span class="token punctuation">.</span>value <span class="token operator">/</span> <span class="token string">"src"</span> <span class="token operator">/</span> <span class="token string">"e2e"</span> <span class="token operator">/</span> <span class="token string">"resources"</span><span class="token punctuation">,</span>
  <span class="token punctuation">)</span>
<span class="token punctuation">}</span></code></pre>
<p>Now apply these settings to your modules and add <code>e2e</code> to the library dependencies as we did with the integration test</p>
<pre class="language-scala"><code class="language-scala"><span class="token keyword">lazy</span> <span class="token keyword">val</span> module1 <span class="token operator">=</span> <span class="token punctuation">(</span>project in file<span class="token punctuation">(</span><span class="token string">"module1"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span>configs<span class="token punctuation">(</span>IntegrationTest<span class="token punctuation">)</span>
  <span class="token punctuation">.</span>configs<span class="token punctuation">(</span>E2ETest<span class="token punctuation">)</span>
<span class="token punctuation">.</span>settings<span class="token punctuation">(</span>
  E2E<span class="token punctuation">.</span>e2eSettings<span class="token punctuation">,</span>
  Defaults<span class="token punctuation">.</span>itSettings<span class="token punctuation">,</span>
  libraryDependencies <span class="token operator">+=</span> scalatest <span class="token operator">%</span> <span class="token string">"it,test,e2e"</span><span class="token punctuation">,</span>
    name <span class="token operator">:</span><span class="token operator">=</span> <span class="token string">"module1"</span><span class="token punctuation">,</span>
  version <span class="token operator">:</span><span class="token operator">=</span> <span class="token string">"0.1"</span>
<span class="token punctuation">)</span>

<span class="token keyword">lazy</span> <span class="token keyword">val</span> module2 <span class="token operator">=</span> <span class="token punctuation">(</span>project in file<span class="token punctuation">(</span><span class="token string">"module2"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span>configs<span class="token punctuation">(</span>IntegrationTest<span class="token punctuation">)</span>
  <span class="token punctuation">.</span>configs<span class="token punctuation">(</span>E2ETest<span class="token punctuation">)</span>
  <span class="token punctuation">.</span>settings<span class="token punctuation">(</span>
    Defaults<span class="token punctuation">.</span>itSettings<span class="token punctuation">,</span>
    libraryDependencies <span class="token operator">+=</span> scalatest <span class="token operator">%</span> <span class="token string">"it,test,e2e"</span><span class="token punctuation">,</span>
      E2E<span class="token punctuation">.</span>e2eSettings<span class="token punctuation">,</span>
    name <span class="token operator">:</span><span class="token operator">=</span> <span class="token string">"module2"</span><span class="token punctuation">,</span>
    version <span class="token operator">:</span><span class="token operator">=</span> <span class="token string">"0.1"</span>
  <span class="token punctuation">)</span>

<span class="token keyword">lazy</span> <span class="token keyword">val</span> root <span class="token operator">=</span> <span class="token punctuation">(</span>project in file<span class="token punctuation">(</span><span class="token string">"."</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span>configs<span class="token punctuation">(</span>IntegrationTest<span class="token punctuation">)</span>
  <span class="token punctuation">.</span>configs<span class="token punctuation">(</span>E2ETest<span class="token punctuation">)</span>
  <span class="token punctuation">.</span>aggregate<span class="token punctuation">(</span>module1<span class="token punctuation">,</span> module2<span class="token punctuation">)</span>
  <span class="token punctuation">.</span>enablePlugins<span class="token punctuation">(</span>Common<span class="token punctuation">)</span>
  <span class="token punctuation">.</span>settings<span class="token punctuation">(</span>
    E2E<span class="token punctuation">.</span>e2eSettings<span class="token punctuation">,</span>
    Defaults<span class="token punctuation">.</span>itSettings<span class="token punctuation">,</span>
    libraryDependencies <span class="token operator">+=</span> scalatest <span class="token operator">%</span> <span class="token string">"it,test,e2e"</span>
  <span class="token punctuation">)</span></code></pre>
<p>we can now create our e2e tests inside the following folders</p>
<pre class="language-vim"><code class="language-vim">src<span class="token operator">/</span>e2e<span class="token operator">/</span>scala
src<span class="token operator">/</span>e2e<span class="token operator">/</span>java
src<span class="token operator">/</span>e2e<span class="token operator">/</span>resources</code></pre>
<p>To run the e2e test use <code>EndToEndTest / test</code> or <code>e2e:test</code> in sbt. This command runs only the integration test as shown below::</p>
<pre class="language-log"><code class="language-log"><span class="token punctuation">[</span>info<span class="token punctuation">]</span> Run completed in <span class="token number">10</span> milliseconds<span class="token punctuation">.</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Total number of tests run:</span> <span class="token number">0</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Suites:</span> completed <span class="token number">0</span><span class="token punctuation">,</span> aborted <span class="token number">0</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Tests:</span> succeeded <span class="token number">0</span><span class="token punctuation">,</span> failed <span class="token number">0</span><span class="token punctuation">,</span> canceled <span class="token number">0</span><span class="token punctuation">,</span> ignored <span class="token number">0</span><span class="token punctuation">,</span> pending <span class="token number">0</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> No tests were executed<span class="token punctuation">.</span>
this is e2e test
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Module1E2ETest:</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token operator">-</span> module1 e2e test
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> Run completed in <span class="token number">172</span> milliseconds<span class="token punctuation">.</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Total number of tests run:</span> <span class="token number">1</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Suites:</span> completed <span class="token number">1</span><span class="token punctuation">,</span> aborted <span class="token number">0</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Tests:</span> succeeded <span class="token number">1</span><span class="token punctuation">,</span> failed <span class="token number">0</span><span class="token punctuation">,</span> canceled <span class="token number">0</span><span class="token punctuation">,</span> ignored <span class="token number">0</span><span class="token punctuation">,</span> pending <span class="token number">0</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> All tests passed<span class="token punctuation">.</span>
module2 e2e test
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Module2E2ETest:</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token operator">-</span> module2 e2e test
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> Run completed in <span class="token number">250</span> milliseconds<span class="token punctuation">.</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Total number of tests run:</span> <span class="token number">1</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Suites:</span> completed <span class="token number">1</span><span class="token punctuation">,</span> aborted <span class="token number">0</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Tests:</span> succeeded <span class="token number">1</span><span class="token punctuation">,</span> failed <span class="token number">0</span><span class="token punctuation">,</span> canceled <span class="token number">0</span><span class="token punctuation">,</span> ignored <span class="token number">0</span><span class="token punctuation">,</span> pending <span class="token number">0</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> All tests passed<span class="token punctuation">.</span>
<span class="token punctuation">[</span>success<span class="token punctuation">]</span> <span class="token property">Total time:</span> <span class="token number">1</span> s<span class="token punctuation">,</span> completed <span class="token number">17</span> Mar<span class="token punctuation">,</span> <span class="token number">2019</span> <span class="token time number">5:53:46</span> PM</code></pre>
<h2 id="unit-test%3F" tabindex="-1">Unit Test? <a class="header-anchor" href="#unit-test%3F"></a></h2>
<p>Now, what remains are the unit tests and configuring the unit tests is relatively straightforward. You don't have to do anything at all. 😄 Any test under package <code>src/test/scala</code> gets considered as a unit test and to execute it you have to use your standard <code>test</code> task in sbt, this runs all the unit test in your module::</p>
<pre class="language-log"><code class="language-log"><span class="token punctuation">[</span>info<span class="token punctuation">]</span> Compiling <span class="token number">1</span> Scala source to <span class="token file-path string">/Users/neenad/codes/tutorials/scala/sbt-learnings/module1/target/scala-2.11/test-classes</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> Run completed in <span class="token number">9</span> milliseconds<span class="token punctuation">.</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Total number of tests run:</span> <span class="token number">0</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Suites:</span> completed <span class="token number">0</span><span class="token punctuation">,</span> aborted <span class="token number">0</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Tests:</span> succeeded <span class="token number">0</span><span class="token punctuation">,</span> failed <span class="token number">0</span><span class="token punctuation">,</span> canceled <span class="token number">0</span><span class="token punctuation">,</span> ignored <span class="token number">0</span><span class="token punctuation">,</span> pending <span class="token number">0</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> No tests were executed<span class="token punctuation">.</span>
module2 sample unit test
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Module2UnitTest:</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token operator">-</span> sample test
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> Run completed in <span class="token number">202</span> milliseconds<span class="token punctuation">.</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Total number of tests run:</span> <span class="token number">1</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Suites:</span> completed <span class="token number">1</span><span class="token punctuation">,</span> aborted <span class="token number">0</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Tests:</span> succeeded <span class="token number">1</span><span class="token punctuation">,</span> failed <span class="token number">0</span><span class="token punctuation">,</span> canceled <span class="token number">0</span><span class="token punctuation">,</span> ignored <span class="token number">0</span><span class="token punctuation">,</span> pending <span class="token number">0</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> All tests passed<span class="token punctuation">.</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> Done compiling<span class="token punctuation">.</span>
module1 sample unit test
Hello World
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Module1UnitTest:</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token operator">-</span> sample test
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> Run completed in <span class="token number">142</span> milliseconds<span class="token punctuation">.</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Total number of tests run:</span> <span class="token number">1</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Suites:</span> completed <span class="token number">1</span><span class="token punctuation">,</span> aborted <span class="token number">0</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> <span class="token property">Tests:</span> succeeded <span class="token number">1</span><span class="token punctuation">,</span> failed <span class="token number">0</span><span class="token punctuation">,</span> canceled <span class="token number">0</span><span class="token punctuation">,</span> ignored <span class="token number">0</span><span class="token punctuation">,</span> pending <span class="token number">0</span>
<span class="token punctuation">[</span>info<span class="token punctuation">]</span> All tests passed<span class="token punctuation">.</span>
<span class="token punctuation">[</span>success<span class="token punctuation">]</span> <span class="token property">Total time:</span> <span class="token number">2</span> s<span class="token punctuation">,</span> completed <span class="token number">17</span> Mar<span class="token punctuation">,</span> <span class="token number">2019</span> <span class="token time number">6:06:45</span> PM</code></pre>
<h2 id="disabling-parallel-execution%3A%3A" tabindex="-1">Disabling Parallel Execution:: <a class="header-anchor" href="#disabling-parallel-execution%3A%3A"></a></h2>
<p>To disable parallel execution of the e2e test in our code add below line in our E2E settings</p>
<pre class="language-scala"><code class="language-scala">E2ETest <span class="token operator">/</span> parallelExecution <span class="token operator">:</span><span class="token operator">=</span> <span class="token boolean">false</span></code></pre>
<p>##Code::</p>
<script src="https://gist.github.com/ninadingole/b5bab2423a507d4b38376c51954b4aed.js"></script>
<hr>
<h2 id="resources" tabindex="-1">Resources <a class="header-anchor" href="#resources"></a></h2>
<ul>
<li><a href="https://www.scala-sbt.org/1.x/docs/">SBT Reference</a></li>
</ul>
<p>I hope this post helps you to organize your tests such that you get faster feedback by running tests independently and don't have to survive the pain I went through in your project. If you have any doubt, please comment and don't forget to share it.</p>

                ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>The Ultimate Guide To Setup Golden Gate On Vagrant Box</title>
            <link href="https://iamninad.com/posts/the-ultimate-guide-to-setup-golden-gate-on-vagrant-box/"/>
            <updated>2018-07-22T00:00:00Z</updated>
            <id>https://iamninad.com/posts/the-ultimate-guide-to-setup-golden-gate-on-vagrant-box/</id>
            <content type="html">
                <![CDATA[
                <p>If you have read my previous post on <a href="https://iamninad.com/how-debezium-kafka-stream-can-help-you-write-cdc/">Debezium</a>, I have mentioned that currently, I am working on a platform which includes capturing CDC events from Oracle and publishing those to our new database. For this to work Oracle provides Golden Gate which is similar to what Debezium does, publishing all database changes to Kafka topics. However, If you are a developer like me who is working on Mac OS and do not have Oracle DB setup for Mac and which is sad 😞 then this post will help you to have your own Oracle Vagrant environment.</p>
<p>While I was working on this new platform development one of my colleagues told me about Oracle having vagrant images which could provide Oracle 12c to developers working on mac. Then I checked and found that Oracle has created a GitHub repo with the vagrant files both for Linux and Oracle 11 and 12c. After that, I basically took this vagrant files as a base for my work and installed golden gate setup along with confluent package on the Linux box. But you know it was a very tedious task to manually do the installation and all. And if I do a big blog with all the steps you guys would be like?</p>
<figure><img src="https://media.giphy.com/media/oOTTyHRHj0HYY/giphy.gif" alt=""></figure>
<p>So, I enhanced the scripts to do the hard work and install Golden Gate + Confluent + enable some configuration for the Oracle database during vagrant box provisioning. And you know what one command does all the setup and configuration for you. Follow the exact given steps in the post and you will be gifted with the magical power of Oracle database, golden gate and confluent. 😂</p>
<figure><img src="https://media.giphy.com/media/144waw4kQiQVgY/giphy.gif" alt="happy"></figure>
<h2 id="1.-clone-vagrant-box-images" tabindex="-1">1. Clone Vagrant Box Images <a class="header-anchor" href="#1.-clone-vagrant-box-images"></a></h2>
<p>Clone my oracle vagrant fork from <a href="https://github.com/ninadingole/vagrant-boxes.git">here</a>. Let's wish my pull request get accepted by the oracle contributors team and this work becomes officially a part of Oracle GitHub repository ( finger crossed 🤞🏼).</p>
<h2 id="2.-download-oracle-database-zip" tabindex="-1">2. Download Oracle Database Zip <a class="header-anchor" href="#2.-download-oracle-database-zip"></a></h2>
<p>Download the Oracle database 12c zip file from oracle tech network <a href="http://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.html">here</a> or <a href="http://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.html">here</a>. Use the Oracle Database 12c Release 2 - Linux x86-64 version and download the single file zip which is around 3.2GB.</p>
<h2 id="3.-download-oracle-gg-and-oracle-gg-bd" tabindex="-1">3. Download Oracle GG and Oracle GG BD <a class="header-anchor" href="#3.-download-oracle-gg-and-oracle-gg-bd"></a></h2>
<p>Now, we need the Oracle Golden Gate and Golden Gate for Big Data zip files. These files can be downloaded from <a href="http://www.oracle.com/technetwork/middleware/goldengate/downloads/index.html">here</a>. Download Oracle GoldenGate for Big Data 12.3.1.1.1 on Linux x86-64 &amp; Oracle GoldenGate 12.3.0.1.4 for Oracle on Linux x86-64.</p>
<blockquote>
<p>Keep all the downloaded files in the same vagrant git checkout directory.</p>
</blockquote>
<h2 id="4.-start-vagrant" tabindex="-1">4. Start Vagrant <a class="header-anchor" href="#4.-start-vagrant"></a></h2>
<p>At this point, all the pre-requisites are done. Now run <code>vagrant up</code> and this will start installing Oracle database 12c, oracle golden gate, oracle golden gate for big data and confluent oss package on the Linux box.</p>
<figure><img src="https://media.giphy.com/media/WZ4M8M2VbauEo/giphy.gif" alt="start"></figure>
<p>Wait till everything finishes. At the very end, the setup will print the password for Oracle database make sure you copy that as this will help you to progress with the next steps. Now, you have your CDC dev environment ready on Mac or on any machine having vagrant. 😎</p>
<figure><img src="https://media.giphy.com/media/8UF0EXzsc0Ckg/giphy.gif" alt="done"></figure>
<hr>
<p>If you are new to Oracle golden gate and want to know about configuring the golden gate for Oracle database follow the below steps in the post.</p>
<h2 id="configure-golden-gate-on-vagrant-box" tabindex="-1">Configure Golden Gate On Vagrant Box <a class="header-anchor" href="#configure-golden-gate-on-vagrant-box"></a></h2>
<p>There are two things we need to configure, the first is oracle golden gate and then oracle golden gate for big data. Let's begin by first configuring the golden gate for Oracle database. Please follow the exact step to get it running. You can find more information about the following command on oracle golden gate <a href="https://www.oracle.com/technetwork/middleware/goldengate/documentation/index.html">documentation</a>.</p>
<h3 id="1.-load-sample-schema-to-oracle-database." tabindex="-1">1. Load Sample Schema To Oracle Database. <a class="header-anchor" href="#1.-load-sample-schema-to-oracle-database."></a></h3>
<p>We need a schema present in the installed oracle database so that we can configure the golden gate to listen to the changes happening on this schema. Well, Oracle setup comes with HR schema SQL files present in the installation. We will load the same into our database.</p>
<blockquote>
<p>use <code>vagrant ssh</code> command to ssh into the virtual machine</p>
</blockquote>
<p>Log in to the database using SQL shell as a sysdba::</p>
<p><code>sqlplus / as sysdba</code></p>
<p>Alter the session to allow Oracle scripts to execute::</p>
<p><code>alter session set &quot;_ORACLE_SCRIPT&quot;=true;</code></p>
<p>Alter the session to use the PDB database (inside SQL shell)::</p>
<p><code>alter session set container=ORCLPDB1;</code></p>
<p>Load the schema and for all the input asked by the below command provide proper responses::</p>
<p><code>@?/demo/schema/human_resources/hr_main.sql</code></p>
<p>Execute the below commands as an oracle user, switch the vagrant user to Oracle using</p>
<p><code>sudo su - oracle</code></p>
<h3 id="2.-configure-oracle-golden-gate" tabindex="-1">2. Configure Oracle Golden Gate <a class="header-anchor" href="#2.-configure-oracle-golden-gate"></a></h3>
<ol>
<li>Go to Oracle golden gate installation directory.
<code>cd /u01/ogg</code></li>
<li>Open golden gate console.
<code>./ggsci</code></li>
<li>Start manager.
<code>&gt; start mgr</code></li>
<li>Log in to the database.
<code>&gt; DBLOGIN USERID SYSTEM@localhost:1521/ORCLCDB PASSWORD [password copied while installation]</code></li>
<li>Register Extract.
<code>&gt; REGISTER EXTRACT EXT1 DATABASE CONTAINER (ORCLPDB1)</code></li>
<li>Enable schema-level supplemental logging for a table.
<code>&gt; ADD SCHEMATRANDATA ORCLPDB1.HR ALLCOLS</code></li>
<li>Create an Extract group.
<code>&gt; ADD EXTRACT EXT1, INTEGRATED TRANLOG, BEGIN NOW</code></li>
<li>Create a trail for online processing on the local system and Associate it with an Extract group.
<code>&gt; ADD EXTTRAIL ./dirdat/lt EXTRACT EXT1</code></li>
<li>Create EXT1 parameter file and paste the content in the file.
<code>&gt; EDIT PARAM EXT1</code></li>
</ol>
<pre class="language-log"><code class="language-log">EXTRACT EXT1
USERID SYSTEM<span class="token operator">@</span>ORCLCDB<span class="token punctuation">,</span> PASSWORD <span class="token punctuation">[</span>password copied during installation<span class="token punctuation">]</span>
EXTTRAIL <span class="token file-path string">./dirdat/lt</span>
SOURCECATALOG ORCLPDB1
TABLE HR<span class="token punctuation">.</span><span class="token operator">*</span><span class="token operator">;</span></code></pre>
<ol start="10">
<li>Start Extract EXT1.
<code>&gt; start ext1</code></li>
<li>View status of manager and ext1.
<code>&gt; info all</code></li>
</ol>
<pre class="language-log"><code class="language-log">Program     Status      Group       Lag at Chkpt  Time Since Chkpt
MANAGER     RUNNING
EXTRACT     RUNNING     EXT1        <span class="token time number">00:00:00</span>      <span class="token time number">00:00:00</span></code></pre>
<p>The Oracle golden gate for Oracle 12c is configured. Now, its time to configure Oracle golden gate for big data which will push all the changes/ CDC events to confluent Kafka.</p>
<h3 id="3.-configure-oracle-golden-gate-for-big-data" tabindex="-1">3. Configure Oracle Golden Gate For Big Data <a class="header-anchor" href="#3.-configure-oracle-golden-gate-for-big-data"></a></h3>
<p>Before following the below steps make sure you add java path to <code>$LD_LIBRARY_PATH</code> environment variable in your <code>.bashrc</code> file. The location of the java is <code>/usr/lib/jvm/java-1.8.0-openjdk-XXXXX/jre/lib/amd64/server</code>. Replace XXXXX with your current version installed on during the installation.</p>
<ol>
<li>
<p>Change directory to oggbd
<code>cd /u01/oggbd</code></p>
</li>
<li>
<p>Open golden gate for bd console.
<code>./ggsci</code></p>
</li>
<li>
<p>Create default directories.
<code>&gt; CREATE SUBDIRS</code>
After doing this exit the console using <code>exit</code> command, and create the following files in <code>dirprm</code> directory.</p>
</li>
</ol>
<ul>
<li>kafkaconnect.properties</li>
<li>rkafka_handler.props</li>
<li>rkafka.prm</li>
</ul>
<ol start="4">
<li>
<p>Login to GG console again using step <code>2</code> then execute the below command and add the contents to the param file
<code>&gt; edit param mgr</code></p>
<pre class="language-log"><code class="language-log">PORT <span class="token number">7801</span></code></pre>
</li>
<li>
<p>Start the manager.
<code>&gt; start mgr</code></p>
</li>
<li>
<p>Create replicat group <code>rkafka</code>.
<code>&gt; add replicat rkafka, exttrail /u01/ogg/dirdat/lt</code></p>
</li>
<li>
<p>Start the replicat.
<code>&gt; start rkafka</code></p>
</li>
<li>
<p>View status of all if everything is properly configured.
<code>&gt; info all</code></p>
<pre class="language-log"><code class="language-log">Program     Status      Group       Lag at Chkpt  Time Since Chkpt
MANAGER     RUNNING
REPLICAT    RUNNING     RKAFKA      <span class="token time number">00:00:00</span>      <span class="token time number">00:00:09</span></code></pre>
</li>
</ol>
<h3 id="4.-verify-setup" tabindex="-1">4. Verify Setup <a class="header-anchor" href="#4.-verify-setup"></a></h3>
<ol>
<li>
<p>Login to the database and add row to any table like::</p>
<pre class="language-sql"><code class="language-sql"><span class="token operator">></span> sqlplus <span class="token operator">/</span> <span class="token keyword">as</span> sysdba
<span class="token keyword">SQL</span><span class="token operator">></span> <span class="token keyword">alter</span> <span class="token keyword">session</span> <span class="token keyword">set</span> container<span class="token operator">=</span>ORCLPDB1<span class="token punctuation">;</span>
<span class="token keyword">SQL</span><span class="token operator">></span> <span class="token keyword">INSERT</span> <span class="token keyword">INTO</span> HR<span class="token punctuation">.</span>REGIONS<span class="token punctuation">(</span>REGION_ID<span class="token punctuation">,</span> REGION_NAME<span class="token punctuation">)</span> <span class="token keyword">VALUES</span><span class="token punctuation">(</span><span class="token number">47</span><span class="token punctuation">,</span> <span class="token string">'FOO'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">SQL</span><span class="token operator">></span> <span class="token keyword">COMMIT</span><span class="token punctuation">;</span></code></pre>
</li>
<li>
<p>Check if the kafka topics are created for the data inserted tables
<code>&gt; kafka-topics --zookeeper localhost:2181 --list</code></p>
<pre class="language-log"><code class="language-log">__confluent<span class="token punctuation">.</span>support<span class="token punctuation">.</span>metrics
__consumer_offsets
_confluent<span class="token operator">-</span>ksql<span class="token operator">-</span>default__command_topic
_schemas
connect<span class="token operator">-</span>configs
connect<span class="token operator">-</span>offsets
connect<span class="token operator">-</span>statuses
ora<span class="token operator">-</span>ogg<span class="token operator">-</span>HR<span class="token operator">-</span>REGIONS<span class="token operator">-</span>avro</code></pre>
</li>
<li>
<p>To check the data in the kafka topics run -
<code>&gt; kafka-avro-console-consumer --bootstrap-server localhost:9092 --topic ora-ogg-HR-REGIONS-avro --from-beginning</code></p>
</li>
</ol>
<p>You can run both <code>kafka-topics</code> and <code>kafka-avro-console-consumer</code> from the host machine where you are running vagrant. This will help you while coding to connect to Kafka instance present in the vagrant vm. Also, The Oracle database is running on port 1521 to which you can connect from your java code or from your IDE.</p>
<figure><img src="https://media.giphy.com/media/MTclfCr4tVgis/giphy.gif" alt="done"></figure>
<p>This vagrant images is really helpful to me and hope it will also help you guys while developing your CDC related applications. For any issues, during setup or configuring please do comment on the post.</p>
<h4 id="other-information%3A%3A" tabindex="-1">Other Information:: <a class="header-anchor" href="#other-information%3A%3A"></a></h4>
<ul>
<li>Zookeeper Port:: 2181</li>
<li>Kafka Broker:: 9092</li>
<li>Confluent Schema Registry:: 8081</li>
<li>Oracle DB Port:: 1521</li>
</ul>
<p>Don't forget to share the post with your friends and colleagues.</p>
<hr>
<h2 id="references%3A%3A" tabindex="-1">References:: <a class="header-anchor" href="#references%3A%3A"></a></h2>
<ol>
<li><a href="https://github.com/oracle/vagrant-boxes">Oracle Repository</a></li>
<li><a href="https://github.com/ninadingole/vagrant-boxes.git">Own Personal Project Repository</a></li>
</ol>

                ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>How Debezium Kafka Streams Can Help You Write Cdc Solution</title>
            <link href="https://iamninad.com/posts/how-debezium-kafka-streams-can-help-you-write-cdc-solution/"/>
            <updated>2018-05-23T00:00:00Z</updated>
            <id>https://iamninad.com/posts/how-debezium-kafka-streams-can-help-you-write-cdc-solution/</id>
            <content type="html">
                <![CDATA[
                <p>I had worked on multiple applications for enterprises where legacy applications have been migrated on modern technology stack. Starting this year I am working on one such application.</p>
<p>The way to design such application is hard because one cannot simply take the entire big complex application and migrated to a new one, it's always better to do it part by part (baby steps). The new application is divided into two parts- read-side and write-side. Considering a part to migrate, the read side of the application is being migrated at first. The consumers will read the data from the new application however, all the write-side operations will still be performed using the legacy application. However, once we have received the certainty that the new application is working as anticipated, the other side of the legacy application will migrate to the new technology stack.</p>
<p>With such decisions in mind, it becomes extremely important for the new application to sync the data from the old one and provide the exact results back to the consumer. For this innovative platform, technology shift in regards to the database is being made though, the older application works with Oracle Database. Now having a <a href="https://en.wikipedia.org/wiki/Change_data_capture">CDC</a> (change data capture) solution that puts all the changes happening inside the old database to this new database platform becomes crucial. What could be a better way than to use Kafka as a messaging platform and process it using Kafka Streams?</p>
<p>To explore this idea and getting more understanding of how to manage the data flow I found Debezium which does exactly what I was looking for, a CDC solution to migrate data from source to destination using Kafka and I considered using MySQL and MongoDB for keeping the tutorial simple.</p>
<p>So, this post is all about setting MySQL, MongoDB, Confluent Kafka, Avro Schema Registry and Configuring Debezium. Once everything is setup we will write a simple application using Scala that could capture real-time changes in MySQL and publish those as Document in MongoDB.</p>
<h2 id="1.-installation" tabindex="-1">1. Installation <a class="header-anchor" href="#1.-installation"></a></h2>
<h3 id="mysql-and-mongodb" tabindex="-1">MySQL And MongoDB <a class="header-anchor" href="#mysql-and-mongodb"></a></h3>
<p>For this tutorial, both MySQL and MongoDB are needed. Download and install the binaries based on OS version from below given links::</p>
<ul>
<li>MySQL <a href="https://www.mysql.com/downloads/">download</a></li>
<li>MongoDB <a href="https://www.mongodb.com/download-center?jmp=nav#community">download</a></li>
</ul>
<h3 id="confluent-kafka" tabindex="-1">Confluent Kafka <a class="header-anchor" href="#confluent-kafka"></a></h3>
<p>Kafka binaries are needed so that debezium can listen to MySQL changes and push them to Kafka topics. Download the confluent Kafka package from <a href="https://www.confluent.io/download/">here</a> and extract it. Also, don't forget to set environment variable <code>PATH</code> to point to the binaries.</p>
<h3 id="debezium" tabindex="-1">Debezium <a class="header-anchor" href="#debezium"></a></h3>
<p>The Confluent Kafka package will come with some default connectors available. However, we will need the debezium MySQL connector for this tutorial, download it from <a href="https://repo1.maven.org/maven2/io/debezium/debezium-connector-mysql/0.7.5/debezium-connector-mysql-0.7.5-plugin.tar.gz">here</a> then extract the jars in a folder and copy the folder at <code>share/java/</code> inside confluent Kafka directory.</p>
<h2 id="2.-start-confluent-platform" tabindex="-1">2. Start Confluent Platform <a class="header-anchor" href="#2.-start-confluent-platform"></a></h2>
<p>Once you will extract out the confluent binaries and place the debezium jars at the right place you have to execute the following command to start confluent</p>
<pre class="language-shell-session"><code class="language-shell-session"><span class="token output">> confluent up
Using CONFLUENT_CURRENT: /var/folders/y7/j6zgy2w13g1fjljkgb8mdc4r0000gn/T/confluent.2GgyNcVE
Starting zookeeper
zookeeper is [UP]
Starting Kafka
kafka is [UP]
Starting schema-registry
schema-registry is [UP]
Starting Kafka-rest
kafka-rest is [UP]
Starting connect
connect is [UP]
Starting ksql-server
ksql-server is [UP]
</span></code></pre>
<p>As you can see the command start zookeeper, Kafka, schema-registry and Kafka-connect. You can read more about schema-registry, kafka-connect on confuent docs <a href="https://docs.confluent.io/current/?_ga=2.178768998.354855723.1527094165-1244062922.1523460392">here</a>. Once you see that everything is started properly without any error head to <a href="http://localhost:8083/connector-plugins">http:😕/localhost::8083/connector-plugins</a> to see if the debezium MySQL plugin is showing in the list as</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"class"</span><span class="token operator">:</span> <span class="token string">"io.debezium.connector.mysql.MySqlConnector"</span><span class="token punctuation">,</span>
  <span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"source"</span><span class="token punctuation">,</span>
  <span class="token property">"version"</span><span class="token operator">:</span> <span class="token string">"0.7.5"</span>
<span class="token punctuation">}</span></code></pre>
<p>If the output in the browser is not, as shown above, it means you have missed something or the debezium jars folder is not placed on the right path.</p>
<h2 id="3.-configure-mysql-%26-mysql-connector" tabindex="-1">3. Configure MySQL &amp; MySQL Connector <a class="header-anchor" href="#3.-configure-mysql-%26-mysql-connector"></a></h2>
<p>Before the Debezium MySQL connector starts monitoring the changes committed to MySQL database, the server must be set up to use row-level binary logging and have a database user with appropriate privileges. If MySQL is configured to use global transaction identifiers (GTIDs), then the Debezium connector can more easily reestablish connection should one of the MySQL servers fail.</p>
<h3 id="enabling-the-binlog" tabindex="-1">Enabling the binlog <a class="header-anchor" href="#enabling-the-binlog"></a></h3>
<p>The MySQL server must be configured to use a row-level binary log, which is described in more detail in the MySQL documentation. This is most often done in the MySQL server configuration file, and will look similar to the following fragment::</p>
<pre class="language-ini"><code class="language-ini"><span class="token section"><span class="token punctuation">[</span><span class="token section-name selector">mysqld</span><span class="token punctuation">]</span></span>
<span class="token key attr-name">server-id</span>         <span class="token punctuation">=</span> <span class="token value attr-value">223344   # any random number</span>
<span class="token key attr-name">log_bin</span>           <span class="token punctuation">=</span> <span class="token value attr-value">mysql-bin</span>
<span class="token key attr-name">binlog_format</span>     <span class="token punctuation">=</span> <span class="token value attr-value">row      # use row or ROW</span>
<span class="token key attr-name">binlog_row_image</span>  <span class="token punctuation">=</span> <span class="token value attr-value">full     # use full or FULL</span>
<span class="token key attr-name">expire_logs_days</span>  <span class="token punctuation">=</span> <span class="token value attr-value">10</span>
<span class="token key attr-name">gtid_mode</span>                 <span class="token punctuation">=</span> <span class="token value attr-value">on   # (optional)</span>
<span class="token key attr-name">enforce_gtid_consistency</span>  <span class="token punctuation">=</span> <span class="token value attr-value">on   # (optional)</span></code></pre>
<h3 id="create-user-for-mysql-connector" tabindex="-1">Create User For MySQL Connector <a class="header-anchor" href="#create-user-for-mysql-connector"></a></h3>
<p>For the connector to listen to the database changes and monitor the logs it requires USER with <code>SELECT, RELOAD, SHOW DATABASES, REPLICATION SLAVE, RELICATION CLIENT</code> access privileges. Login to your MySQL console using <code>$ mysql -u root -p</code> with the password you have given at the time of installation and run the below command to create a user named <code>debezium</code> with password <code>dbz</code></p>
<pre class="language-sql"><code class="language-sql">mysql<span class="token operator">></span> <span class="token keyword">GRANT</span> <span class="token keyword">SELECT</span><span class="token punctuation">,</span> RELOAD<span class="token punctuation">,</span> <span class="token keyword">SHOW</span> <span class="token keyword">DATABASES</span><span class="token punctuation">,</span> <span class="token keyword">REPLICATION</span> SLAVE<span class="token punctuation">,</span> <span class="token keyword">REPLICATION</span> CLIENT <span class="token keyword">ON</span> <span class="token operator">*</span><span class="token punctuation">.</span><span class="token operator">*</span> <span class="token keyword">TO</span> <span class="token string">'debezium'</span> IDENTIFIED <span class="token keyword">BY</span> <span class="token string">'dbz'</span><span class="token punctuation">;</span></code></pre>
<h3 id="configure-mysql-connector-for-the-database" tabindex="-1">Configure MySQL Connector For The Database <a class="header-anchor" href="#configure-mysql-connector-for-the-database"></a></h3>
<p>I have created a <code>moviesdemo</code> database with two tables <code>movies</code> and <code>sales</code>. The <code>movies</code> tables consist of all the movies and the <code>sales</code> consist of the total number of movie ticket sold. The idea behind using these two tables is to make the tutorial simple and easy and also to show how two related tables get processed in stream processing.</p>
<p>When the movie row is being inserted in the movies table within the same transaction <code>sales</code> table row also gets inserted with a starting value of <code>0</code>.</p>
<p>To make the debezium Kafka connector to listen to the changes happening on the <code>moviesdemo</code> project we will need to provide configuration settings to the connector. A <code>POST</code> request in the following format to the URL <code>http://localhost:8083/connectors</code> will register the connection settings to the debezium utility. Make sure to provide the same username and password that you used while configuring the mySQL.</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>
  <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"moviesdemo-connector"</span><span class="token punctuation">,</span>
  <span class="token property">"config"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">"connector.class"</span><span class="token operator">:</span> <span class="token string">"io.debezium.connector.mysql.MySqlConnector"</span><span class="token punctuation">,</span>
    <span class="token property">"tasks.max"</span><span class="token operator">:</span> <span class="token string">"1"</span><span class="token punctuation">,</span>
    <span class="token property">"database.hostname"</span><span class="token operator">:</span> <span class="token string">"localhost"</span><span class="token punctuation">,</span>
    <span class="token property">"database.port"</span><span class="token operator">:</span> <span class="token string">"3306"</span><span class="token punctuation">,</span>
    <span class="token property">"database.user"</span><span class="token operator">:</span> <span class="token string">"debezium"</span><span class="token punctuation">,</span>
    <span class="token property">"database.password"</span><span class="token operator">:</span> <span class="token string">"dbz"</span><span class="token punctuation">,</span>
    <span class="token property">"database.server.id"</span><span class="token operator">:</span> <span class="token string">"184054"</span><span class="token punctuation">,</span>
    <span class="token property">"database.server.name"</span><span class="token operator">:</span> <span class="token string">"dbserver1"</span><span class="token punctuation">,</span>
    <span class="token property">"database.history.kafka.bootstrap.servers"</span><span class="token operator">:</span> <span class="token string">"localhost:9092"</span><span class="token punctuation">,</span>
    <span class="token property">"database.history.kafka.topic"</span><span class="token operator">:</span> <span class="token string">"dbhistory.moviesdemo"</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Head to <code>http://localhost:8083/connectors/moviesdemo-connector</code> using web browser to see configurations been done properly and if so, your Debezium connector is now ready to listen to any changes happening to MySQL moviedemo database.</p>
<h2 id="4.-kafka-topics" tabindex="-1">4. Kafka Topics <a class="header-anchor" href="#4.-kafka-topics"></a></h2>
<p>Open MySQL console using <code>$&gt; mysql -u debezium -p</code>, and try to insert one row in both <code>movies</code> and <code>sales</code> table. Make sure auto-commit is being turned off and commit explicitly using <code>mysql&gt; commit;</code> 😊</p>
<blockquote>
<p>Note:: Make sure you have created a database named <code>moviesdemo</code> in MySQL along with two tables <code>movies</code> and <code>sales</code> the DDL scripts for both of the tables are <a href="https://gist.github.com/ninadingole/cfd3683c5d65dec9a232c8604963f2ed">here</a></p>
</blockquote>
<p>If you have seen your kafka topic list you will find that there are two topics created as below</p>
<pre class="language-shell-session"><code class="language-shell-session"><span class="token command"><span class="token shell-symbol important">$</span> <span class="token bash language-bash">./bin/kafka-topics <span class="token parameter variable">--zookeeper</span> localhost:2181 <span class="token parameter variable">--list</span></span></span>
<span class="token output">__confluent.support.metrics
__consumer_offsets
_confluent-ksql-default__command_topic
_schemas
connect-configs
connect-offsets
connect-status
connect-statuses
dbhistory.inventory
dbserver1
dbserver1.moviesdemo.movies
dbserver1.moviesdemo.sales
</span></code></pre>
<h2 id="5.-generating-business-event-using-kafka-streams" tabindex="-1">5. Generating Business Event Using Kafka Streams <a class="header-anchor" href="#5.-generating-business-event-using-kafka-streams"></a></h2>
<p>I wrote a simple Kafka stream program in Scala that reads from both the two Kafka topics <code>movies</code> and <code>sales</code>, joins the two messages based on <code>movie_id</code> and then create a business event which is published to <code>events</code> Kafka topic.</p>
<p>The program is easy to understand. It works on two business cases <code>Insertion</code> &amp; <code>Updates</code> to both the table. However, I left deletion logic implementation for the readers.</p>
<pre class="language-scala"><code class="language-scala"><span class="token keyword">private</span> <span class="token keyword">def</span> buildMovieStream<span class="token operator">:</span> KStreamS<span class="token punctuation">[</span><span class="token builtin">String</span><span class="token punctuation">,</span> movie<span class="token punctuation">.</span>Envelope<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token keyword">import</span> AppSerdes<span class="token punctuation">.</span>movieSerde<span class="token punctuation">.</span>consumed
    builder<span class="token punctuation">.</span>stream<span class="token punctuation">[</span><span class="token builtin">String</span><span class="token punctuation">,</span> movie<span class="token punctuation">.</span>Envelope<span class="token punctuation">]</span><span class="token punctuation">(</span>Utils<span class="token punctuation">.</span>getTopic<span class="token punctuation">(</span><span class="token string">"movies"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">private</span> <span class="token keyword">def</span> buildMovieSalesStream <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token keyword">import</span> AppSerdes<span class="token punctuation">.</span>movieSalesSerde<span class="token punctuation">.</span>consumed
    builder<span class="token punctuation">.</span>stream<span class="token punctuation">[</span><span class="token builtin">String</span><span class="token punctuation">,</span> Envelope<span class="token punctuation">]</span><span class="token punctuation">(</span>Utils<span class="token punctuation">.</span>getTopic<span class="token punctuation">(</span><span class="token string">"sales"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">val</span> movieStream <span class="token operator">=</span> buildMovieStream
  <span class="token keyword">val</span> saleStream  <span class="token operator">=</span> buildMovieSalesStream

  <span class="token keyword">private</span> <span class="token keyword">def</span> filterSalesStreamForCreations <span class="token operator">=</span> <span class="token punctuation">{</span>
    saleStream
      <span class="token punctuation">.</span>filter<span class="token punctuation">(</span><span class="token punctuation">(</span>id<span class="token punctuation">,</span> value<span class="token punctuation">)</span> <span class="token keyword">=></span> <span class="token punctuation">{</span>
        println<span class="token punctuation">(</span><span class="token string">"filtering sales creation message"</span><span class="token punctuation">)</span>
        value<span class="token punctuation">.</span>op<span class="token punctuation">.</span>equalsIgnoreCase<span class="token punctuation">(</span><span class="token string">"c"</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">def</span> createMovieBusinessEvent <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token keyword">import</span> AppSerdes<span class="token punctuation">.</span>movieBEventSerde<span class="token punctuation">.</span><span class="token punctuation">{</span>joined<span class="token punctuation">,</span> salesSerialized<span class="token punctuation">}</span>
    <span class="token keyword">val</span> movieFilteredStream <span class="token operator">=</span> <span class="token keyword">new</span> MovieCreatedFilter<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>filter<span class="token punctuation">(</span>movieStream<span class="token punctuation">)</span>
    <span class="token keyword">val</span> salesFilteredStream <span class="token operator">=</span> filterSalesStreamForCreations

    <span class="token keyword">val</span> envelopExtractedMovie<span class="token operator">:</span> KStreamS<span class="token punctuation">[</span><span class="token builtin">Int</span><span class="token punctuation">,</span> Movie<span class="token punctuation">]</span> <span class="token operator">=</span>
      movieFilteredStream<span class="token punctuation">.</span>map<span class="token punctuation">(</span><span class="token punctuation">(</span>id<span class="token punctuation">,</span> value<span class="token punctuation">)</span> <span class="token keyword">=></span> <span class="token punctuation">(</span>value<span class="token punctuation">.</span>after<span class="token punctuation">.</span>get<span class="token punctuation">.</span>movie_id<span class="token punctuation">.</span>get<span class="token punctuation">,</span> value<span class="token punctuation">.</span>after<span class="token punctuation">.</span>get<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">val</span> envelopeExtractedSale <span class="token operator">=</span> salesFilteredStream<span class="token punctuation">.</span>map<span class="token punctuation">(</span><span class="token punctuation">(</span>id<span class="token punctuation">,</span> value<span class="token punctuation">)</span> <span class="token keyword">=></span> <span class="token punctuation">(</span>value<span class="token punctuation">.</span>after<span class="token punctuation">.</span>get<span class="token punctuation">.</span>movie_id<span class="token punctuation">.</span>get<span class="token punctuation">,</span> value<span class="token punctuation">.</span>after<span class="token punctuation">.</span>get<span class="token punctuation">)</span><span class="token punctuation">)</span>

    envelopExtractedMovie<span class="token punctuation">.</span>join<span class="token punctuation">(</span>envelopeExtractedSale<span class="token punctuation">,</span> <span class="token punctuation">(</span>movie<span class="token operator">:</span> Movie<span class="token punctuation">,</span> movieSale<span class="token operator">:</span> MovieSales<span class="token punctuation">)</span> <span class="token keyword">=></span> <span class="token punctuation">{</span>
      println<span class="token punctuation">(</span><span class="token string">"Created Business Event"</span><span class="token punctuation">)</span>
      <span class="token keyword">val</span> serializer <span class="token operator">=</span> <span class="token keyword">new</span> KafkaAvroSerializer<span class="token punctuation">(</span><span class="token punctuation">)</span>
      serializer<span class="token punctuation">.</span>configure<span class="token punctuation">(</span>schemaConfig<span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span>
      <span class="token keyword">val</span> movieSerialized <span class="token operator">=</span> serializer<span class="token punctuation">.</span>serialize<span class="token punctuation">(</span>Utils<span class="token punctuation">.</span>getTopic<span class="token punctuation">(</span><span class="token string">"movie"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> AppSerdes<span class="token punctuation">.</span>movieBEventSerde<span class="token punctuation">.</span>movieFormat<span class="token punctuation">.</span>to<span class="token punctuation">(</span>movie<span class="token punctuation">)</span><span class="token punctuation">)</span>
      <span class="token keyword">val</span> salesSerialized <span class="token operator">=</span>
        serializer<span class="token punctuation">.</span>serialize<span class="token punctuation">(</span>Utils<span class="token punctuation">.</span>getTopic<span class="token punctuation">(</span><span class="token string">"movie_sales"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> AppSerdes<span class="token punctuation">.</span>movieBEventSerde<span class="token punctuation">.</span>saleFormat<span class="token punctuation">.</span>to<span class="token punctuation">(</span>movieSale<span class="token punctuation">)</span><span class="token punctuation">)</span>

      <span class="token keyword">val</span> map <span class="token operator">=</span> Map<span class="token punctuation">(</span><span class="token string">"movie"</span> <span class="token operator">-></span> movieSerialized<span class="token punctuation">,</span> <span class="token string">"sale"</span> <span class="token operator">-></span> salesSerialized<span class="token punctuation">)</span>
      BusinessEvent<span class="token punctuation">(</span>EventTypes<span class="token punctuation">.</span>`MOVIECREATEEVENT`<span class="token punctuation">,</span> map<span class="token punctuation">)</span>

    <span class="token punctuation">}</span><span class="token punctuation">,</span> JoinWindows<span class="token punctuation">.</span>of<span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">def</span> emitMovieBussinessEventToTopic <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token keyword">import</span> AppSerdes<span class="token punctuation">.</span>movieBEventSerde<span class="token punctuation">.</span>eventProduced
    createMovieBusinessEvent<span class="token punctuation">.</span>to<span class="token punctuation">(</span><span class="token string">"events"</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  emitMovieBussinessEventToTopic

  <span class="token keyword">def</span> createMovieUpdateEvent <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token keyword">val</span> updateStream <span class="token operator">=</span> <span class="token keyword">new</span> MovieUpdateFilter<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>filter<span class="token punctuation">(</span>movieStream<span class="token punctuation">)</span>
    updateStream<span class="token punctuation">.</span>map<span class="token punctuation">(</span><span class="token punctuation">(</span>id<span class="token punctuation">,</span> envelop<span class="token punctuation">)</span> <span class="token keyword">=></span> <span class="token punctuation">{</span>
      <span class="token keyword">val</span> before <span class="token operator">=</span> envelop<span class="token punctuation">.</span>before<span class="token punctuation">.</span>get
      <span class="token keyword">val</span> after  <span class="token operator">=</span> envelop<span class="token punctuation">.</span>after<span class="token punctuation">.</span>get

      <span class="token keyword">val</span> serializer <span class="token operator">=</span> <span class="token keyword">new</span> KafkaAvroSerializer<span class="token punctuation">(</span><span class="token punctuation">)</span>
      serializer<span class="token punctuation">.</span>configure<span class="token punctuation">(</span>schemaConfig<span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span>

      <span class="token keyword">val</span> beforeMovieSerialized <span class="token operator">=</span> serializer<span class="token punctuation">.</span>serialize<span class="token punctuation">(</span><span class="token string">"events"</span><span class="token punctuation">,</span> AppSerdes<span class="token punctuation">.</span>movieBEventSerde<span class="token punctuation">.</span>movieFormat<span class="token punctuation">.</span>to<span class="token punctuation">(</span>before<span class="token punctuation">)</span><span class="token punctuation">)</span>
      <span class="token keyword">val</span> afterMovieSerialized  <span class="token operator">=</span> serializer<span class="token punctuation">.</span>serialize<span class="token punctuation">(</span><span class="token string">"events"</span><span class="token punctuation">,</span> AppSerdes<span class="token punctuation">.</span>movieBEventSerde<span class="token punctuation">.</span>movieFormat<span class="token punctuation">.</span>to<span class="token punctuation">(</span>after<span class="token punctuation">)</span><span class="token punctuation">)</span>

      <span class="token punctuation">(</span>after<span class="token punctuation">.</span>movie_id<span class="token punctuation">.</span>get<span class="token punctuation">,</span>
       BusinessEvent<span class="token punctuation">(</span>EventTypes<span class="token punctuation">.</span>`MOVIEUPDATEEVENT`<span class="token punctuation">,</span> Map<span class="token punctuation">(</span><span class="token string">"before"</span> <span class="token operator">-></span> beforeMovieSerialized<span class="token punctuation">,</span> <span class="token string">"after"</span> <span class="token operator">-></span> afterMovieSerialized<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">def</span> emitMovieUpdateEvent <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token keyword">import</span> AppSerdes<span class="token punctuation">.</span>movieBEventSerde<span class="token punctuation">.</span>eventProduced
    createMovieUpdateEvent<span class="token punctuation">.</span>to<span class="token punctuation">(</span><span class="token string">"events"</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  emitMovieUpdateEvent</code></pre>
<p>When you run the above program it will start listening to the movies &amp; sales topic and will create event objects for any insert or update operation at MySQL side.</p>
<h2 id="6.-updating-mongodb-based-on-business-events" tabindex="-1">6. Updating MongoDB Based On Business Events <a class="header-anchor" href="#6.-updating-mongodb-based-on-business-events"></a></h2>
<p>This code that you see below reads the business events from the <code>events</code> topic and inserts or updates MongoDB collection. This code is also written using Kafka Streams in Scala and is pretty straightforward to understand.</p>
<p>It reads the topic, deserialize the message and checks which type of business event is present. Based on the event type it will change the records in the MongoDB movies collection.</p>
<pre class="language-scala"><code class="language-scala"><span class="token keyword">def</span> buildEventStream <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token keyword">import</span> AppSerdes<span class="token punctuation">.</span>movieBEventSerde<span class="token punctuation">.</span>eventConsumed
    builder<span class="token punctuation">.</span>stream<span class="token punctuation">[</span><span class="token builtin">Int</span><span class="token punctuation">,</span> BusinessEvent<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token string">"events"</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">private</span> <span class="token keyword">val</span> eventStreams<span class="token operator">:</span> KStreamS<span class="token punctuation">[</span><span class="token builtin">Int</span><span class="token punctuation">,</span> BusinessEvent<span class="token punctuation">]</span> <span class="token operator">=</span> buildEventStream

  <span class="token keyword">def</span> filterEventsByType<span class="token punctuation">(</span>eventType<span class="token operator">:</span> <span class="token builtin">String</span><span class="token punctuation">)</span><span class="token operator">:</span> KStreamS<span class="token punctuation">[</span><span class="token builtin">Int</span><span class="token punctuation">,</span> BusinessEvent<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
    eventStreams<span class="token punctuation">.</span>filter<span class="token punctuation">(</span><span class="token punctuation">(</span>_<span class="token operator">:</span> <span class="token builtin">Int</span><span class="token punctuation">,</span> event<span class="token operator">:</span> BusinessEvent<span class="token punctuation">)</span> <span class="token keyword">=></span> event<span class="token punctuation">.</span>eventType<span class="token punctuation">.</span>equalsIgnoreCase<span class="token punctuation">(</span>eventType<span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  filterEventsByType<span class="token punctuation">(</span>EventTypes<span class="token punctuation">.</span>`MOVIECREATEEVENT`<span class="token punctuation">)</span><span class="token punctuation">.</span>foreach<span class="token punctuation">(</span><span class="token punctuation">(</span>id<span class="token punctuation">,</span> event<span class="token punctuation">)</span> <span class="token keyword">=></span> <span class="token punctuation">{</span>

    <span class="token keyword">val</span> value <span class="token operator">=</span> <span class="token keyword">new</span> MovieCreatedEventDeserializer<span class="token punctuation">(</span>event<span class="token punctuation">)</span><span class="token punctuation">.</span>get
    <span class="token keyword">if</span> <span class="token punctuation">(</span>value<span class="token punctuation">.</span>isDefined<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">val</span> doc <span class="token operator">=</span> value<span class="token punctuation">.</span>get
      movies<span class="token punctuation">.</span>insertOne<span class="token punctuation">(</span>document <span class="token operator">=</span> doc<span class="token punctuation">)</span><span class="token punctuation">.</span>toFuture<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>onComplete<span class="token punctuation">(</span>_ <span class="token keyword">=></span> println<span class="token punctuation">(</span><span class="token string-interpolation"><span class="token id function">s</span><span class="token string">"Inserted </span><span class="token interpolation"><span class="token punctuation">${</span><span class="token expression">doc</span><span class="token punctuation">}</span></span><span class="token string">"</span></span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>

  <span class="token punctuation">}</span><span class="token punctuation">)</span>

  filterEventsByType<span class="token punctuation">(</span>EventTypes<span class="token punctuation">.</span>`MOVIEUPDATEEVENT`<span class="token punctuation">)</span><span class="token punctuation">.</span>foreach<span class="token punctuation">(</span><span class="token punctuation">(</span>id<span class="token punctuation">,</span> event<span class="token punctuation">)</span> <span class="token keyword">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">val</span> movie<span class="token operator">:</span> Option<span class="token punctuation">[</span>Document<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">new</span> MovieUpdateEventDeserializer<span class="token punctuation">(</span>event<span class="token punctuation">)</span><span class="token punctuation">.</span>get
    <span class="token keyword">val</span> movieDocument           <span class="token operator">=</span> movies<span class="token punctuation">.</span>find<span class="token punctuation">(</span>Filters<span class="token punctuation">.</span>eq<span class="token punctuation">(</span><span class="token string">"movie_id"</span><span class="token punctuation">,</span> movie<span class="token punctuation">.</span>get<span class="token punctuation">.</span>getInteger<span class="token punctuation">(</span><span class="token string">"movie_id"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    movieDocument<span class="token punctuation">.</span>toFuture<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>map<span class="token punctuation">(</span>_<span class="token punctuation">.</span>head<span class="token punctuation">)</span><span class="token punctuation">.</span>onSuccess <span class="token punctuation">{</span>
      <span class="token keyword">case</span> data <span class="token keyword">=></span> <span class="token punctuation">{</span>
        <span class="token keyword">val</span> document <span class="token operator">=</span> movie<span class="token punctuation">.</span>get<span class="token punctuation">.</span>toBsonDocument
        println<span class="token punctuation">(</span><span class="token string-interpolation"><span class="token id function">s</span><span class="token string">"Relpacing Movie Information </span><span class="token interpolation"><span class="token punctuation">${</span><span class="token expression">movie<span class="token punctuation">.</span>get<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token string">"movie_id"</span><span class="token punctuation">)</span><span class="token punctuation">.</span>get<span class="token punctuation">.</span>asString<span class="token punctuation">(</span><span class="token punctuation">)</span></span><span class="token punctuation">}</span></span><span class="token string">"</span></span><span class="token punctuation">)</span>
        document<span class="token punctuation">.</span>put<span class="token punctuation">(</span><span class="token string">"sales"</span><span class="token punctuation">,</span> data<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token string">"sales"</span><span class="token punctuation">)</span><span class="token punctuation">.</span>get<span class="token punctuation">)</span>
        movies
          <span class="token punctuation">.</span>replaceOne<span class="token punctuation">(</span>Filters<span class="token punctuation">.</span>eq<span class="token punctuation">(</span><span class="token string">"_id"</span><span class="token punctuation">,</span> data<span class="token punctuation">.</span>getObjectId<span class="token punctuation">(</span><span class="token string">"_id"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span> document<span class="token punctuation">)</span>
          <span class="token punctuation">.</span>toFuture<span class="token punctuation">(</span><span class="token punctuation">)</span>
          <span class="token punctuation">.</span>onSuccess <span class="token punctuation">{</span>
            <span class="token keyword">case</span> data <span class="token keyword">=></span> println<span class="token punctuation">(</span><span class="token string">"Movie Information Updated"</span><span class="token punctuation">)</span>
          <span class="token punctuation">}</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

  <span class="token punctuation">}</span><span class="token punctuation">)</span></code></pre>
<p>This completes the tutorial on how debezium can help you design change data capture solutions. Hope you guys like it and for any questions or doubt please do comment on this post I will surely get back.</p>
<p>Also, Please don't forget to share the post using the share link and do subscribe to the blog by which you will get the next blog post right into your mailbox. This also helps me to track the users following the blog 😀.</p>
<p>Stay tuned &amp; Happy Coding!</p>
<hr>
<h2 id="reference-links%3A%3A" tabindex="-1">Reference Links:: <a class="header-anchor" href="#reference-links%3A%3A"></a></h2>
<ul>
<li><a href="http://debezium.io/docs/">Debezium Docs</a></li>
<li><a href="https://github.com/ninadingole/kafka-streams">Code @Github</a></li>
<li><a href="https://docs.confluent.io/current/?_ga=2.178768998.354855723.1527094165-1244062922.1523460392">Confluent Docs</a></li>
</ul>

                ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Running Spark Job On Minikube Kubernetes Cluster</title>
            <link href="https://iamninad.com/posts/running-spark-job-on-minikube-kubernetes-cluster/"/>
            <updated>2018-03-10T00:00:00Z</updated>
            <id>https://iamninad.com/posts/running-spark-job-on-minikube-kubernetes-cluster/</id>
            <content type="html">
                <![CDATA[
                <p>Kubernetes is another industry buzz words these days and I am trying few different things with Kubernetes. On Feb 28th, 2018 Apache spark released v2.3.0, I am already working on Apache Spark and the new released has added a  new Kubernetes scheduler backend that supports native submission of spark jobs to a cluster managed by kubernetes. The feature is still currently experimental but I wanted to try it out.</p>
<p>I am writing this post because I have to search a lot of things to get it working and there is no single place to get the exact information on how to run spark job on a local kubernetes cluster. I thought writing a post on my findings will enable others not to go through the same pain as I did.</p>
<p>In this post we will take a look on how to setup Kubernetes cluster using minikube on local machine and how to run apache spark job on top of it. We are not going to write any code for this, few examples are already available within Apache Spark distribution and we are going to use the same example jar and run <code>SparkPi</code> program from it onto our kubernetes cluster.</p>
<h3 id="prerequisites" tabindex="-1">Prerequisites <a class="header-anchor" href="#prerequisites"></a></h3>
<p>Before we start please make sure you have the following pre-requisites installed on your local machine.</p>
<blockquote>
<p>I am running the tools on Mac High Sierra.</p>
</blockquote>
<ul>
<li>Apache Spark (v2.3.0)</li>
<li>Kubernetes (v.1.9.3)</li>
<li>Docker</li>
<li>Minikube</li>
<li>VirtualBox</li>
</ul>
<h3 id="1.-start-minikube" tabindex="-1">1. Start Minikube <a class="header-anchor" href="#1.-start-minikube"></a></h3>
<p>We can start minikube locally by simply running below command.</p>
<script src="https://gist.github.com/ninadingole/9f387324b9a4aff3458f51a2814f1279.js"></script>
<p>Minikube is a tool that makes it easy to run Kubernetes locally. Minikube runs a single-node Kubernetes cluster inside a VM on a local machine. It enables us to try out Kubernetes or develop with it day-to-day.</p>
<p>When minikube starts it starts with a single node configuration and takes <code>1Gb</code> of Memory and <code>2</code> cores of CPU by default, however, for running spark this requirement will not suffice and the jobs will fail (and they do as I have tried multiple times) so we have to increase both Memory and CPU cores for our minikube cluster.</p>
<p>There are <strong>three</strong> different ways to do this. However, for me not all worked and that’s how I came to know about the different ways to change the minikube configuration. You can use any one of the below ways to change the configuration.</p>
<h3 id="pass-configuration-to-minikube-start-command" tabindex="-1">Pass Configuration To Minikube Start Command <a class="header-anchor" href="#pass-configuration-to-minikube-start-command"></a></h3>
<p>You can directly pass the memory and CPU options to the minikube start command like::</p>
<script src="https://gist.github.com/ninadingole/d63f43a9b297d93029c67cadcccd37e3.js"></script>
<p>This will start a minikube cluster with 8Gb of memory and 4 cores of CPU. (somehow for me this didn't work)</p>
<h2 id="modify-minikube-config" tabindex="-1">Modify minikube config <a class="header-anchor" href="#modify-minikube-config"></a></h2>
<p>We can change the minikube config with <code>config</code> command in minikube cli. The <code>config</code> command allows setting different config options for minikube like memory, CPUs, vm-driver, disk-size etc. To see all the available options use <code>&gt; minikube config</code> command it will list all the available options that can be modified.</p>
<script src="https://gist.github.com/ninadingole/5e62d4ce5cadc7d9e988c260210a3556.js"></script>
<script src="https://gist.github.com/ninadingole/d91e0c7ad3dee6a2f20cf0197d1f75e7.js"></script>
<p>After setting configuration using <code>config</code> command we need to delete our previous running cluster and start a new one. To delete minikube cluster run <code>&gt; minikube delete</code> and rerun the start minikube command.</p>
<h2 id="change-configuration-using-virtualbox" tabindex="-1">Change Configuration Using VirtualBox <a class="header-anchor" href="#change-configuration-using-virtualbox"></a></h2>
<p>For me, the above two options didn't work and if you are like me you can use this last option which worked for me and hope it works for you. Open VirtualBox app on your machine and select your VM like the one shown in below image. <code>RightClick -&gt; Settings</code> on your VM, this will open the configuration page for the Minikube VM.</p>
<blockquote>
<p>note:: To change configuration using VirtualBox first you need to shutdown the VM if it is already running.</p>
</blockquote>
<figure><img src="/images/running-spark-job-on-minikube-kubernetes-cluster/okF4NxZ.png" alt=""></figure>
<p>Inside option <code>System -&gt; Motherboard</code>, you can change the memory of the VM using the slider, in my case I have given it <code>8192MB</code> of memory.</p>
<figure><img src="/images/running-spark-job-on-minikube-kubernetes-cluster/0RhSdV6.png" alt=""></figure>
<p>To change the CPU config, go to <code>Processor</code> tab and change it to <code>4</code>. You can try other options also for me 4 works just fine. Don’t change it to less than 2 otherwise things won’t work. ::p</p>
<figure><img src="/images/running-spark-job-on-minikube-kubernetes-cluster/eG6OhDs.png" alt=""></figure>
<p>After the configuration changes are done, start the VM using VirtualBox app or using the above given <code>minikube start</code> command.</p>
<p>Your cluster is running and now you need to have a docker image for spark. Let's see how to build the image next.</p>
<h2 id="creating-docker-image-for-spark" tabindex="-1">Creating Docker Image For Spark <a class="header-anchor" href="#creating-docker-image-for-spark"></a></h2>
<p>Make sure you have Docker installed on your machine and the spark distribution is extracted.</p>
<p>Go inside your extracted spark folder and run the below command to create a spark docker image</p>
<blockquote>
<p>some of the output logs are excluded.</p>
</blockquote>
<script src="https://gist.github.com/ninadingole/3a6727ec8abf7fa6b6cb3e83dc21c9d1.js"></script>
<p>Now if you run <code>&gt; docker image ls</code> you will see the docker build available in your local machine. Make a note of this image name we need to provide the image name to <code>spark-submit</code> command.</p>
<p>There is a <code>push</code> option available to the above command which enables you to push the docker image to your own repository this, in turn, will enable your production kubernetes to pull the docker image from the configured Docker repository. Run the same command without any options to see its usage.</p>
<p>It might happen that the command will not work and will give error like::</p>
<script src="https://gist.github.com/ninadingole/67bbe2f8761a61abd28a49399ab13c77.js"></script>
<p>This is because of an issue with the <code>docker-image-tool.sh</code> file. I have raised a bug for this in Apache Spark JIRA you can see it <a href="https://issues.apache.org/jira/browse/SPARK-23618">here</a>.</p>
<p>The issue is under fix but for you to continue with this post what you can do is open the <code>docker-image-tool.sh</code> file present inside the <code>bin</code> folder and after line no <code>59</code> add <code>BUILD_ARGS=()</code>, save the file and run the command once again and it will work.</p>
<p>For those who the above command worked without the workaround the issue might have been fixed at the time you are reading this post and you don't have to do anything hurrah!!!</p>
<h2 id="submit-spark-job" tabindex="-1">Submit Spark Job <a class="header-anchor" href="#submit-spark-job"></a></h2>
<p>Now lets submit our <code>SparkPi</code> job to the cluster. Our cluster is ready and we have the docker image. Run the below command to submit the spark job on a kubernetes cluster. The <code>spark-submit</code> script takes care of setting up the classpath with Spark and its dependencies, and can support different cluster managers and deploy modes that Spark supports</p>
<script src="https://gist.github.com/ninadingole/8b677dc8c5130fa5cc46d436b97e0c00.js"></script>
<p>options used to run on kubernetes are::</p>
<ul>
<li><code>--class</code>:: The entry point for your application (e.g. org.apache.spark.examples.SparkPi)</li>
<li><code>--master</code>:: The master URL for the Kubernetes cluster (e.g. k8s:😕/<a href="https://192.168.99.100:8443">https://192.168.99.100:8443</a>)</li>
<li><code>--deploy-mode</code>:: Whether to deploy your driver on the worker nodes (cluster) or locally as an external client (client) (default:: client)</li>
<li><code>--conf spark.executor.instances=3</code>:: configuration property to specify how many executor instances to use while running the spark job.</li>
<li><code>--conf spark.kubernetes.container.image=spark-docker</code>:: Configuration property to specify which docker image to use, here provide the same docker name from <code>docker image ls</code> command.</li>
<li><code>local:///opt/spark/examples/jars/spark-examples_2.11-2.3.0.jar</code>:: Path to a bundled jar including your application and all dependencies. The URL must be globally visible inside of your cluster, for instance, an hdfs:😕/ path or a local:😕/ path that is present on all nodes</li>
</ul>
<p>The package jar should be available cluster-wide either through HDFS, HTTP or should be available within every packaged docker image so that it will be available to all the executor nodes in our spark program. The <code>local://</code> address means that the jar is available as a local file on every initialized pod by the spark driver and no IO has to be made to pull the jar from anywhere, this works well when application jar is large which is pushed to every worker node or shared using any shared filesystem.</p>
<p>Luckily, our spark docker image file packages the example jar in the docker container so we can use it. However, how to package our own application code and push it either on HDFS or as a separate docker image I will write it as a separate post.</p>
<p>To check if the pods are started and the spark job is running, open kubernetes dashboard available within minikube.</p>
<h2 id="view-minikube-dashboard-%26-kubernetes-logs" tabindex="-1">View Minikube Dashboard &amp; Kubernetes Logs <a class="header-anchor" href="#view-minikube-dashboard-%26-kubernetes-logs"></a></h2>
<p>To check the status of our submitted job we can use either kubernetes dashboard or view kubernetes logs. Minikube comes with the dashboard available as an addon and can be started using the following command.</p>
<script src="https://gist.github.com/ninadingole/fcfc462ba149504129c2dc5d8b40afb6.js"></script>
<figure><img src="/images/running-spark-job-on-minikube-kubernetes-cluster/r3y5p9p.png" alt="Kubernetes Dashboard"><figcaption>Kubernetes Dashboard</figcaption></figure>
<p>Navigate to the URL given by above command to view the dashboard. The dashboard provides lots of information about cluster memory usage, CPU usage, pods, services, replica set etc. We can also view service logs directly through the dashboard. However, if you don't want to go to the dashboard you can view the Spark Driver log using <code>&gt; kubectl logs &lt;pod name&gt;</code> command::</p>
<script src="https://gist.github.com/ninadingole/f5e3617d59f4fee7bff9e34363a3c954.js"></script>
<p>If you see in the logs the program has calculated the Pi value and the container are stopped in the end.</p>
<h2 id="shutdown-cluster" tabindex="-1">Shutdown Cluster <a class="header-anchor" href="#shutdown-cluster"></a></h2>
<p>Shutting down cluster is very easy, use <code>&gt; minikube stop</code> and it will stop the cluster.</p>
<hr>
<p>Hope this helps you try running apache spark on local kubernetes cluster. Please do comment if you didn’t understand any step or getting any errors while following the steps and I will try to add more details to the post. Also, please do let me know if you liked it and help others by sharing.</p>
<p>Happy Coding...</p>
<h2 id="references" tabindex="-1">References <a class="header-anchor" href="#references"></a></h2>
<ol>
<li><a href="https://spark.apache.org/docs/latest/running-on-kubernetes.html">Apache Spark Documentation</a></li>
<li><a href="https://github.com/kubernetes/minikube">Minikube Github</a></li>
</ol>

                ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Apache Kafka Using Java</title>
            <link href="https://iamninad.com/posts/apache-kafka-using-java/"/>
            <updated>2018-03-09T00:00:00Z</updated>
            <id>https://iamninad.com/posts/apache-kafka-using-java/</id>
            <content type="html">
                <![CDATA[
                <p>Apache Kafka is a buzz word these days. Originally developed by LinkedIn in 2011 the project has been donated to Apache, many companies have successfully adopted the technology. But what is this buzz word all about, what does it do? Why does everyone these days talk about it? What was the existing solution it replaced? And does it really justifies the change?</p>
<p>In this post, we'll try to answer all these questions. We'll start with the basic introduction of Kafka, then will see its use-cases, after that will dive into some demonstration and coding of how you can get started with Kafka using Java.</p>
<h2 id="what-is-kafka%3F" tabindex="-1">What is Kafka? <a class="header-anchor" href="#what-is-kafka%3F"></a></h2>
<p>Kafka is distributed publish-subscriber message delivery system that is designed to be fast, durable, scalable in very simple terms. But as you go deeper into the design and technicality of the architecture it's a large system. We are not going to discuss the entire design in this post however, you can get more insight about the design of Kafka by reading Kafka Documentation.</p>
<p>Kafka has following 4 core API's::</p>
<p><strong>Producer API</strong> - Allows to push messages to one or more topics.
<strong>Consumer API</strong> - Allows to consume messages from one or more topics.
<strong>Streams API</strong> - Allows to consume input stream from one or more topics producing an output stream to one or more topics, effectively converting input streams to output streams.
<strong>Connector API</strong> - Allows building a reusable producers and consumers that connects to Kafka topics to existing applications or data system.</p>
<h2 id="apache-kafka-architecture" tabindex="-1">Apache Kafka Architecture <a class="header-anchor" href="#apache-kafka-architecture"></a></h2>
<figure><img src="/images/apache-kafka-using-java/kafka-apis.png" alt="Apache Kafka Architecture"><figcaption>Apache Kafka Architecture</figcaption></figure>
<p>Like other publish-subscribe messaging systems, Kafka maintains feeds of messages in topics. One or more Producers writes to the topic whereas consumers consume from the topic. As Kafka is distributed platform topics are partitioned and replicated across multiple nodes.</p>
<p>Message to the topics are simple byte array and developers can store messages in any form of String, Json etc. Each message is associated with a key and producer guarantees that messages with the same key will arrive at the same partition. Consumers can be organized into consumer groups in which case Kafka makes sure that each consumer within the consumer group will receive exactly one message to the partitioned within the topic it subscribes too i.e each consumer in a consumer group reads from a unique partitioned of topic to which no other consumer within the consumer group will have access, thus all the messages that arrive at the unique partitioned which is identified by a unique key will be delivered to the same consumer always.</p>
<p>Kafka treats each topic as a log(ordered sequence of messages) like a pipeline where messages come from one end and are consumed from another end, each message in a partitioned is assigned a unique offset. Kafka does not maintain any detail of which message is read by each consumer and only retains unread messages rather, Kafka retains messages for a certain amount of time and consumer are responsible to track their location in each log. Kafka can maintain a large amount of data without any issue.</p>
<figure><img src="/images/apache-kafka-using-java/log_consumer.png" alt="logs"><figcaption>logs</figcaption></figure>
<p><strong>Use Cases::</strong></p>
<p><em>Website activity tracking::</em> Web Apps can send events to Kafka such as page clicks, page search for real-time processing and analytics.</p>
<p><em>Log aggregation</em>:: Logs can be aggregated from multiple servers which can be analyzed in real time or will be available to tools like Hadoop or Apache Solr.</p>
<p><em>Stream Processing::</em> Framework like Apache Spark can stream data from a topic, process it and writes the processed data to the new topic. This processed data then can be made available to the customer or another application for further processing.</p>
<p><em>Operational Metrix::</em> Alert monitoring and notification can be done by analysing the metadata or logs. Other way application can send stats or counts to the topic which will be then compared and visualized as a dashboard.</p>
<p>Others system may serve the purpose but none of them does all. Like ActiveMQ and RabbitMQ are a very popular messaging system. Google PubSub is also one of the great messaging platforms but does not provide on premises solutions. I have also heard about the performance and throughput of Kafka as oppose to others.</p>
<p>Now, let's get into the coding stuff will see how you can install Kafka on your local machine and perform operations like creating, deleting, listing topics, sending and receiving messages to the topic.</p>
<h2 id="installing-kafka" tabindex="-1">Installing Kafka <a class="header-anchor" href="#installing-kafka"></a></h2>
<p>For this I am using a windows machine so I will be explaining installing Kafka on windows, however, Unix and Mac's setup is also same. Kafka binaries are packaged into zip folder which needs to be extracted. Download the binaries extract it somewhere on your machine. Execute the following commands to start Kafka on your local machine. For windows machine the bat files are located inside <code>bin\windows</code>.</p>
<pre class="language-shell"><code class="language-shell"><span class="token operator">></span> bin/zookeeper-server-start.sh config/zookeeper.properties
<span class="token punctuation">[</span><span class="token number">2017</span>-09-03 <span class="token number">19</span>:00:38,859<span class="token punctuation">]</span> INFO Reading configuration from: <span class="token punctuation">..</span><span class="token punctuation">\</span>config<span class="token punctuation">\</span>zookeeper.properties <span class="token punctuation">(</span>org.apache.zookeeper.server.quorum.QuorumPeerConfig<span class="token punctuation">)</span><span class="token punctuation">..</span>.
<span class="token punctuation">..</span>.</code></pre>
<p>You need to first start the Zookeeper instance. There are scripts packaged into the Kafka binaries the above command starts the zookeeper instance.</p>
<pre class="language-shell"><code class="language-shell"><span class="token operator">></span> bin/kafka-server-start.sh config/server.properties
<span class="token punctuation">[</span><span class="token number">2017</span>-09-03 <span class="token number">19</span>:03:59,553<span class="token punctuation">]</span> INFO starting <span class="token punctuation">(</span>kafka.server.KafkaServer<span class="token punctuation">)</span>
<span class="token punctuation">[</span><span class="token number">2017</span>-09-03 <span class="token number">19</span>:03:59,590<span class="token punctuation">]</span> INFO Connecting to zookeeper on localhost:2181 <span class="token punctuation">(</span>kafka.server.KafkaServer<span class="token punctuation">)</span>
<span class="token punctuation">..</span>.</code></pre>
<p>The above command will start Kafka server and the the broker address will be <code>localhost:9092</code>.</p>
<h2 id="creating-a-topic" tabindex="-1">Creating a Topic <a class="header-anchor" href="#creating-a-topic"></a></h2>
<p>Creating a topic using cmd is fairly simple. Run the following command to create a &quot;test&quot; topic.</p>
<pre class="language-shell"><code class="language-shell"><span class="token operator">></span> bin/kafka-topics.sh <span class="token parameter variable">--create</span> <span class="token parameter variable">--zookeeper</span> localhost:2181 --replication-factor <span class="token number">1</span> <span class="token parameter variable">--partitions</span> <span class="token number">1</span> <span class="token parameter variable">--topic</span> <span class="token builtin class-name">test</span></code></pre>
<p>To list all the topics::</p>
<pre class="language-shell"><code class="language-shell"><span class="token operator">></span> bin/kafka-topics.sh <span class="token parameter variable">--list</span> <span class="token parameter variable">--zookeeper</span> localhost:2181 <span class="token builtin class-name">test</span></code></pre>
<p>To delete a Topic::</p>
<pre class="language-shell"><code class="language-shell"><span class="token operator">></span> bin/kafka-topics.sh <span class="token parameter variable">--zookeeper</span> localhost:2181 <span class="token parameter variable">--delete</span> <span class="token builtin class-name">test</span></code></pre>
<p>Every command given above will work with your console. Let's move to the programming part and see how to use API in java. Will try to do the above operations using Kafka Admin Client API and then will write a simple producer and consumer that sends and messages to the Topic we create.</p>
<h2 id="project-setup" tabindex="-1">Project Setup <a class="header-anchor" href="#project-setup"></a></h2>
<p>I will be using maven for the project and the Maven configuration for the project is as follows::</p>
<pre class="language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>project</span> <span class="token attr-name">xmlns</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://maven.apache.org/POM/4.0.0<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xmlns:</span>xsi</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://www.w3.org/2001/XMLSchema-instance<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">xsi:</span>schemaLocation</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>modelVersion</span><span class="token punctuation">></span></span>4.0.0<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>modelVersion</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">></span></span>com.kafka.samples<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">></span></span>kafka-learning<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">></span></span>0.0.1-SNAPSHOT<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">></span></span>

    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependencies</span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">></span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">></span></span>org.apache.kafka<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">></span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">></span></span>kafka-clients<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">></span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">></span></span>0.11.0.0<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">></span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">></span></span>org.apache.kafka<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">></span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">></span></span>kafka_2.11<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">></span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">></span></span>0.11.0.0<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">></span></span>
	    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">></span></span>com.esotericsoftware<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">></span></span>
	    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">></span></span>kryo<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">></span></span>
	    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">></span></span>4.0.1<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">></span></span>
	<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">></span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">></span></span>junit<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">></span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">></span></span>junit<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">></span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">></span></span>&lt;4.11<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">></span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>scope</span><span class="token punctuation">></span></span>test<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>scope</span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependencies</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>project</span><span class="token punctuation">></span></span></code></pre>
<p>The Kryo library in our <code>pom.xml</code> is used to write custom Serializer and Deserializer for Kafka which is explained furture in the post.</p>
<h2 id="creating-a-topic%3A%3A" tabindex="-1">Creating a Topic:: <a class="header-anchor" href="#creating-a-topic%3A%3A"></a></h2>
<p>You will require properties like <code>bootstrap.server</code> and <code>client.id</code> to configure the admin client. You can read about all the configuration options in Kafka Documentation but for now, as we are not dealing with configurations like secure SSL, <code>bootstrap.server</code> will be enough to connect to the Kafka Server.</p>
<pre class="language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">CreateTopic</span> <span class="token punctuation">{</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
        <span class="token class-name">Properties</span> properties <span class="token operator">=</span> <span class="token class-name">ConfigUtils</span><span class="token punctuation">.</span><span class="token function">getConfiguration</span><span class="token punctuation">(</span><span class="token string">"admin-config"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">AdminClient</span> adminClient <span class="token operator">=</span> <span class="token class-name">AdminClient</span><span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span>properties<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">CreateTopicsResult</span> result <span class="token operator">=</span> adminClient<span class="token punctuation">.</span><span class="token function">createTopics</span><span class="token punctuation">(</span><span class="token class-name">Arrays</span><span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">NewTopic</span><span class="token punctuation">(</span><span class="token string">"test1"</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token keyword">short</span><span class="token punctuation">)</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Topic Created: "</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

<span class="token punctuation">}</span></code></pre>
<p>The arguments to NewTopic is the new topic name, number of partitioned and replication factor.</p>
<h2 id="listing-all-topics%3A%3A" tabindex="-1">Listing All Topics:: <a class="header-anchor" href="#listing-all-topics%3A%3A"></a></h2>
<pre class="language-java"><code class="language-java"><span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>kafka<span class="token punctuation">.</span>clients<span class="token punctuation">.</span>admin<span class="token punctuation">.</span></span><span class="token class-name">AdminClient</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>kafka<span class="token punctuation">.</span>clients<span class="token punctuation">.</span>admin<span class="token punctuation">.</span></span><span class="token class-name">ListTopicsResult</span></span><span class="token punctuation">;</span>


<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ListTopics</span> <span class="token punctuation">{</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span><span class="token punctuation">,</span> <span class="token class-name">InterruptedException</span><span class="token punctuation">,</span> <span class="token class-name">ExecutionException</span> <span class="token punctuation">{</span>
        <span class="token class-name">Properties</span> prop <span class="token operator">=</span> <span class="token class-name">ConfigUtils</span><span class="token punctuation">.</span><span class="token function">getConfiguration</span><span class="token punctuation">(</span><span class="token string">"admin-config"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">AdminClient</span> admin <span class="token operator">=</span> <span class="token class-name">AdminClient</span><span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span>prop<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">ListTopicsResult</span> topics <span class="token operator">=</span> admin<span class="token punctuation">.</span><span class="token function">listTopics</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">Set</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">></span></span> topicNames <span class="token operator">=</span> topics<span class="token punctuation">.</span><span class="token function">names</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token class-name">String</span> topic<span class="token operator">:</span> topicNames<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>topic<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

<span class="token punctuation">}</span></code></pre>
<h2 id="delete-topic%3A%3A" tabindex="-1">Delete Topic:: <a class="header-anchor" href="#delete-topic%3A%3A"></a></h2>
<pre class="language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">DeleteTopic</span> <span class="token punctuation">{</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span><span class="token punctuation">,</span> <span class="token class-name">InterruptedException</span><span class="token punctuation">,</span> <span class="token class-name">ExecutionException</span> <span class="token punctuation">{</span>
        <span class="token class-name">Properties</span> prop <span class="token operator">=</span> <span class="token class-name">ConfigUtils</span><span class="token punctuation">.</span><span class="token function">getConfiguration</span><span class="token punctuation">(</span><span class="token string">"admin-config"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">ZkClient</span> zkClient <span class="token operator">=</span> <span class="token class-name">ZkUtils</span><span class="token punctuation">.</span><span class="token function">createZkClient</span><span class="token punctuation">(</span>prop<span class="token punctuation">.</span><span class="token function">getProperty</span><span class="token punctuation">(</span><span class="token string">"bootstrap.server"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">10000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        zkClient<span class="token punctuation">.</span><span class="token function">deleteRecursive</span><span class="token punctuation">(</span><span class="token class-name">ZkUtils</span><span class="token punctuation">.</span><span class="token function">getTopicPath</span><span class="token punctuation">(</span><span class="token string">"test2"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="producer-to-send-messages%3A%3A" tabindex="-1">Producer To Send Messages:: <a class="header-anchor" href="#producer-to-send-messages%3A%3A"></a></h2>
<p>Here is our simple Kafka producer that sends Hello World message to test topic.</p>
<pre class="language-java"><code class="language-java"><span class="token keyword">package</span> <span class="token namespace">com<span class="token punctuation">.</span>kafka<span class="token punctuation">.</span>sample</span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">IOException</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">Properties</span></span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>kafka<span class="token punctuation">.</span>clients<span class="token punctuation">.</span>producer<span class="token punctuation">.</span></span><span class="token class-name">KafkaProducer</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>kafka<span class="token punctuation">.</span>clients<span class="token punctuation">.</span>producer<span class="token punctuation">.</span></span><span class="token class-name">Producer</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>kafka<span class="token punctuation">.</span>clients<span class="token punctuation">.</span>producer<span class="token punctuation">.</span></span><span class="token class-name">ProducerRecord</span></span><span class="token punctuation">;</span>

<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">SimpleProducer</span> <span class="token punctuation">{</span>

	<span class="token keyword">private</span> <span class="token class-name">Producer</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Long</span><span class="token punctuation">,</span> <span class="token class-name">Employee</span><span class="token punctuation">></span></span> producer<span class="token punctuation">;</span>
	<span class="token keyword">long</span> count <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>

	<span class="token keyword">public</span> <span class="token class-name">SimpleProducer</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>producer <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
			<span class="token function">createProducer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">}</span>

	<span class="token keyword">public</span> <span class="token class-name">SimpleProducer</span><span class="token punctuation">(</span><span class="token class-name">Producer</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Long</span><span class="token punctuation">,</span> <span class="token class-name">Employee</span><span class="token punctuation">></span></span> producer<span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token keyword">this</span><span class="token punctuation">.</span>producer <span class="token operator">=</span> producer<span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">createProducer</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
		<span class="token class-name">Properties</span> configuration <span class="token operator">=</span> <span class="token class-name">ConfigUtils</span><span class="token punctuation">.</span><span class="token function">getConfiguration</span><span class="token punctuation">(</span><span class="token string">"producer-config"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		producer <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">KafkaProducer</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token punctuation">></span></span><span class="token punctuation">(</span>configuration<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">sendMessage</span><span class="token punctuation">(</span><span class="token class-name">String</span> topic<span class="token punctuation">,</span> <span class="token class-name">Employee</span> message<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
		producer<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">ProducerRecord</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Long</span><span class="token punctuation">,</span> <span class="token class-name">Employee</span><span class="token punctuation">></span></span><span class="token punctuation">(</span>topic<span class="token punctuation">,</span> count<span class="token operator">++</span><span class="token punctuation">,</span> message<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		producer<span class="token punctuation">.</span><span class="token function">flush</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		producer<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Done"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		producer<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
		<span class="token class-name">SimpleProducer</span> producer <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SimpleProducer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token class-name">Employee</span> emp <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Employee</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		emp<span class="token punctuation">.</span><span class="token function">setEmpId</span><span class="token punctuation">(</span><span class="token number">101</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		emp<span class="token punctuation">.</span><span class="token function">setFirstName</span><span class="token punctuation">(</span><span class="token string">"Ninad"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		emp<span class="token punctuation">.</span><span class="token function">setLastName</span><span class="token punctuation">(</span><span class="token string">"Ingole"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		emp<span class="token punctuation">.</span><span class="token function">setJoiningDate</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		producer<span class="token punctuation">.</span><span class="token function">sendMessage</span><span class="token punctuation">(</span><span class="token string">"test"</span><span class="token punctuation">,</span> emp<span class="token punctuation">)</span><span class="token punctuation">;</span>
		producer<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Configuration is fairly simple for this example::</p>
<pre class="language-properties"><code class="language-properties"><span class="token key attr-name">bootstrap.servers</span><span class="token punctuation">=</span><span class="token value attr-value">localhost:9092</span>
<span class="token key attr-name">key.serializer</span><span class="token punctuation">=</span><span class="token value attr-value">org.apache.kafka.common.serialization.LongSerializer</span>
<span class="token key attr-name">value.serializer</span><span class="token punctuation">=</span><span class="token value attr-value">org.apache.kafka.common.serialization.StringSerializer</span>
<span class="token key attr-name">client.id</span><span class="token punctuation">=</span><span class="token value attr-value">kafka-client-1</span></code></pre>
<p><code>bootstrap.servers</code> is a list of comma separated values of all the Kafka servers, you will have three or more depending on your cluster configurations. The <code>key.serializer</code> and <code>value.serializer</code> is required for serializing messages at producer end. Few Serializer and Deserializer are available for wrapper types in Kafka. However, if you are sending your own message type you need to implement <code>org.apache.kafka.common.serialization.Serializer</code> and provide your own implementation. <code>client.id</code> is needed to uniquely identify the producer in Kafka and Kafka logs.</p>
<h2 id="consumer-to-pull-the-messages%3A%3A" tabindex="-1">Consumer to Pull the messages:: <a class="header-anchor" href="#consumer-to-pull-the-messages%3A%3A"></a></h2>
<pre class="language-java"><code class="language-java"><span class="token keyword">package</span> <span class="token namespace">com<span class="token punctuation">.</span>kafka<span class="token punctuation">.</span>sample</span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">IOException</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">Collections</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">Properties</span></span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>kafka<span class="token punctuation">.</span>clients<span class="token punctuation">.</span>consumer<span class="token punctuation">.</span></span><span class="token class-name">ConsumerRecord</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>kafka<span class="token punctuation">.</span>clients<span class="token punctuation">.</span>consumer<span class="token punctuation">.</span></span><span class="token class-name">ConsumerRecords</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>kafka<span class="token punctuation">.</span>clients<span class="token punctuation">.</span>consumer<span class="token punctuation">.</span></span><span class="token class-name">KafkaConsumer</span></span><span class="token punctuation">;</span>

<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">SimpleConsumer</span> <span class="token punctuation">{</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
        <span class="token class-name">SimpleConsumer</span> consumer <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SimpleConsumer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        consumer<span class="token punctuation">.</span><span class="token function">recieveAndPrintMessage</span><span class="token punctuation">(</span><span class="token string">"test"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">recieveAndPrintMessage</span><span class="token punctuation">(</span><span class="token class-name">String</span> topic<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
        <span class="token class-name">Properties</span> prop <span class="token operator">=</span> <span class="token class-name">ConfigUtils</span><span class="token punctuation">.</span><span class="token function">getConfiguration</span><span class="token punctuation">(</span><span class="token string">"consumer-config"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token class-name">KafkaConsumer</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Long</span><span class="token punctuation">,</span> <span class="token class-name">String</span><span class="token punctuation">></span></span> consumer <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">KafkaConsumer</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token punctuation">></span></span><span class="token punctuation">(</span>prop<span class="token punctuation">)</span><span class="token punctuation">;</span>
        consumer<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span><span class="token class-name">Collections</span><span class="token punctuation">.</span><span class="token function">singletonList</span><span class="token punctuation">(</span>topic<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token class-name">ConsumerRecords</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Long</span><span class="token punctuation">,</span> <span class="token class-name">String</span><span class="token punctuation">></span></span> consumerRecords <span class="token operator">=</span> consumer<span class="token punctuation">.</span><span class="token function">poll</span><span class="token punctuation">(</span><span class="token number">1000L</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token class-name">ConsumerRecord</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Long</span><span class="token punctuation">,</span> <span class="token class-name">String</span><span class="token punctuation">></span></span> record <span class="token operator">:</span> consumerRecords<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token class-name">String</span> message <span class="token operator">=</span> record<span class="token punctuation">.</span><span class="token function">value</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">try</span> <span class="token punctuation">{</span>
            <span class="token class-name">Thread</span><span class="token punctuation">.</span><span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">InterruptedException</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        consumer<span class="token punctuation">.</span><span class="token function">commitAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        consumer<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>The example given above will create a KafkaConsumer using consumer properties and will subscribe to the test topic. It will poll the topic for 1sec and return all the messages in the topic as ConsumerRecords which is a collection of ConsumerRecord i.e a message on the topic. The type is same as that of the producer <code>&lt;Long, String&gt;</code>. You can retrieve the value of a ConsumerRecord by calling <code>value()</code> method on it. Other information can also be inferred from ConsumerRecord like checksum, headers, topic, key etc.</p>
<p>In the example, We just poll the topic once for 1sec and it will get some messages but not all. However, in a real scenario, you will poll the topic multiple times in a loop. Once the messages are read by poll method we need to commit the offset for the last returned poll offset, there are two ways to commit one is commitSync which will block until the commit succeeds or some error occurs and the other is commitAsync which will not block and will return immediately, you can also pass a call back to <code>commitAsync</code> which will get called with commit results.</p>
<p>Like Producer the properties for the consumer are::</p>
<pre class="language-properties"><code class="language-properties"><span class="token key attr-name">bootstrap.servers</span><span class="token punctuation">=</span><span class="token value attr-value">localhost:9092</span>
<span class="token key attr-name">key.deserializer</span><span class="token punctuation">=</span><span class="token value attr-value">org.apache.kafka.common.serialization.LongDeserializer</span>
<span class="token key attr-name">value.deserializer</span><span class="token punctuation">=</span><span class="token value attr-value">org.apache.kafka.common.serialization.StringDeserializer</span>
<span class="token key attr-name">group.id</span><span class="token punctuation">=</span><span class="token value attr-value">kafka-consumer-1</span></code></pre>
<p><code>bootstrap.servers</code> is same as producer. Consumer requires deserialization and properties <code>key.deserializer</code>, <code>value.deserializer</code> provides that information. You need to provide your own implementation in case if you sending your own message type. Other configurations are also there like SSL which you can read on Kafka Documentation site. As our examples are pretty simple we are not dealing with other configuration options.</p>
<h2 id="serialization-and-deserialization" tabindex="-1">Serialization And Deserialization <a class="header-anchor" href="#serialization-and-deserialization"></a></h2>
<p>If you have a custom message schema and if you want to send it to a Topic in Kafka you will need to implement <code>org.apache.kafka.common.serialization.Serializer</code> and <code>org.apache.kafka.common.serialization.Deserializer</code>. There are various Serializer available in the market like Jackson (for JSON), XStream (for XML), Smile, Kryo (a fast, compact binary serialization format) or you can use Java Object Serialization. For this example, I am using Kryo.</p>
<pre class="language-java"><code class="language-java"><span class="token keyword">package</span> <span class="token namespace">com<span class="token punctuation">.</span>kafka<span class="token punctuation">.</span>sample</span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">Date</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">Map</span></span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>kafka<span class="token punctuation">.</span>common<span class="token punctuation">.</span>serialization<span class="token punctuation">.</span></span><span class="token class-name">Deserializer</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>apache<span class="token punctuation">.</span>kafka<span class="token punctuation">.</span>common<span class="token punctuation">.</span>serialization<span class="token punctuation">.</span></span><span class="token class-name">Serializer</span></span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">com<span class="token punctuation">.</span>esotericsoftware<span class="token punctuation">.</span>kryo<span class="token punctuation">.</span></span><span class="token class-name">Kryo</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">com<span class="token punctuation">.</span>esotericsoftware<span class="token punctuation">.</span>kryo<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">ByteBufferInput</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">com<span class="token punctuation">.</span>esotericsoftware<span class="token punctuation">.</span>kryo<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">ByteBufferOutput</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">com<span class="token punctuation">.</span>esotericsoftware<span class="token punctuation">.</span>kryo<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">Input</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">com<span class="token punctuation">.</span>esotericsoftware<span class="token punctuation">.</span>kryo<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span><span class="token class-name">Output</span></span><span class="token punctuation">;</span>

<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">KryoSerialization</span> <span class="token keyword">implements</span> <span class="token class-name">Serializer</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Employee</span><span class="token punctuation">></span></span><span class="token punctuation">,</span><span class="token class-name">Deserializer</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Employee</span><span class="token punctuation">></span></span> <span class="token punctuation">{</span>

	<span class="token keyword">private</span> <span class="token class-name">ThreadLocal</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Kryo</span><span class="token punctuation">></span></span> kryos <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ThreadLocal</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Kryo</span><span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token keyword">protected</span> <span class="token class-name">Kryo</span> <span class="token function">initialValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
			<span class="token class-name">Kryo</span> kryo <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Kryo</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			kryo<span class="token punctuation">.</span><span class="token function">addDefaultSerializer</span><span class="token punctuation">(</span><span class="token class-name">Employee</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">KryoSerializer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token keyword">return</span> kryo<span class="token punctuation">;</span>
		<span class="token punctuation">}</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span><span class="token punctuation">;</span>

	<span class="token annotation punctuation">@Override</span>
	<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">configure</span><span class="token punctuation">(</span><span class="token class-name">Map</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token operator">?</span><span class="token punctuation">></span></span> configs<span class="token punctuation">,</span> <span class="token keyword">boolean</span> isKey<span class="token punctuation">)</span> <span class="token punctuation">{</span>

	<span class="token punctuation">}</span>

	<span class="token annotation punctuation">@Override</span>
	<span class="token keyword">public</span> <span class="token class-name">Employee</span> <span class="token function">deserialize</span><span class="token punctuation">(</span><span class="token class-name">String</span> topic<span class="token punctuation">,</span> <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> data<span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token class-name">Employee</span> employee <span class="token operator">=</span> kryos<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">readObject</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">ByteBufferInput</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">Employee</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">return</span> employee<span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token annotation punctuation">@Override</span>
	<span class="token keyword">public</span> <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token function">serialize</span><span class="token punctuation">(</span><span class="token class-name">String</span> topic<span class="token punctuation">,</span> <span class="token class-name">Employee</span> data<span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token class-name">ByteBufferOutput</span> output <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ByteBufferOutput</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		kryos<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">writeObject</span><span class="token punctuation">(</span>output<span class="token punctuation">,</span> data<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">return</span> output<span class="token punctuation">.</span><span class="token function">toBytes</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token annotation punctuation">@Override</span>
	<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
			kryos<span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">KryoSerializer</span> <span class="token keyword">extends</span> <span class="token class-name"><span class="token namespace">com<span class="token punctuation">.</span>esotericsoftware<span class="token punctuation">.</span>kryo<span class="token punctuation">.</span></span>Serializer</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Employee</span><span class="token punctuation">></span></span> <span class="token punctuation">{</span>

		<span class="token annotation punctuation">@Override</span>
		<span class="token keyword">public</span> <span class="token class-name">Employee</span> <span class="token function">read</span><span class="token punctuation">(</span><span class="token class-name">Kryo</span> kryo<span class="token punctuation">,</span> <span class="token class-name">Input</span> input<span class="token punctuation">,</span> <span class="token class-name">Class</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Employee</span><span class="token punctuation">></span></span> clazz<span class="token punctuation">)</span> <span class="token punctuation">{</span>
			<span class="token class-name">Employee</span> emp <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Employee</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			emp<span class="token punctuation">.</span><span class="token function">setEmpId</span><span class="token punctuation">(</span>input<span class="token punctuation">.</span><span class="token function">readLong</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			emp<span class="token punctuation">.</span><span class="token function">setFirstName</span><span class="token punctuation">(</span>input<span class="token punctuation">.</span><span class="token function">readString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			emp<span class="token punctuation">.</span><span class="token function">setLastName</span><span class="token punctuation">(</span>input<span class="token punctuation">.</span><span class="token function">readString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			emp<span class="token punctuation">.</span><span class="token function">setJoiningDate</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span>input<span class="token punctuation">.</span><span class="token function">readLong</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token keyword">return</span> emp<span class="token punctuation">;</span>
		<span class="token punctuation">}</span>

		<span class="token annotation punctuation">@Override</span>
		<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">write</span><span class="token punctuation">(</span><span class="token class-name">Kryo</span> kryo<span class="token punctuation">,</span> <span class="token class-name">Output</span> output<span class="token punctuation">,</span> <span class="token class-name">Employee</span> message<span class="token punctuation">)</span> <span class="token punctuation">{</span>
			output<span class="token punctuation">.</span><span class="token function">writeLong</span><span class="token punctuation">(</span>message<span class="token punctuation">.</span><span class="token function">getEmpId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			output<span class="token punctuation">.</span><span class="token function">writeString</span><span class="token punctuation">(</span>message<span class="token punctuation">.</span><span class="token function">getFirstName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			output<span class="token punctuation">.</span><span class="token function">writeString</span><span class="token punctuation">(</span>message<span class="token punctuation">.</span><span class="token function">getLastName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			output<span class="token punctuation">.</span><span class="token function">writeLong</span><span class="token punctuation">(</span>message<span class="token punctuation">.</span><span class="token function">getJoiningDate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>

	<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Serializer and Deserializer have two methods serialize and deserialize and what we are doing in this two method is handing over the task to Kryo. The write and read sequence of data in KryoSerializer will be same as you can see in the read and write method. We'll require changing our properties file to use this new serializer in producer and consumer.</p>
<p>Thus we have seen the basics of Apache Kafka, its use cases, installation and working with Apache Kafka API's in Java. Many projects like real time based and streaming based uses Apache Kafka and I hope this post helps you get started with Apache Kafka. If you want to experiment with the examples you can find the source here.</p>
<h2 id="references" tabindex="-1">References <a class="header-anchor" href="#references"></a></h2>
<ul>
<li><a href="https://kafka.apache.org/documentation/">Kafka Documentation</a></a><br></li>
<li><a href="https://github.com/EsotericSoftware/kryo">Kryo</a></a><br></li>
<li><a href="%22https://github.com/ninadingole/kafka-learnings%22">Source Code</a></li>
</ul>

                ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Rest Web Service Using Express Js</title>
            <link href="https://iamninad.com/posts/rest-web-service-using-express-js/"/>
            <updated>2018-03-07T00:00:00Z</updated>
            <id>https://iamninad.com/posts/rest-web-service-using-express-js/</id>
            <content type="html">
                <![CDATA[
                <p>In this post, we will be using expressjs to create REST web services. We will also learn about what is ExpressJS, its features, and as we progress in the post we will build a rest based library app that will allow us to perform CRUD functionality using ExpressJS.</p>
<p><strong>RESTful</strong> web services are everywhere. Many of you might have heard of this name in your current project and if not it might happen your next project will need you to build some Rest based web services. From Banking and Financial applications to social networking sites, IOT devices, gaming, the mobile development you name it REST is everywhere. And it's because of the vast popularity of REST older application based on the SOAP is also getting converted to REST. But what is REST and why do we require it?.</p>
<p>REST is <strong>&quot;Representational State Transfer&quot;</strong>, big name but let me break it down for you in simple terms. Over internet when two systems need to interface with each other they need some form/language to communicate, REST is that medium which enables transferring of data between two remote systems. REST is based on HTTP protocol and hence supports all the HTTP verbs like GET, POST, PUT, DELETE, PATH etc. We also have SOAP &amp; WSDL web services which are still used in many places but they are old and creepy. SOAP is based on XML format and is slow whereas with REST get the freedom to use formats like text, XML or JSON. REST takes the advantage of HTTP protocol because of which it is more faster and with json format which is faster to parse and compact as compared to XML.</p>
<p>Express JS is a javascript web framework that allows to easily build web apps and rest web services. It is built on top of nodejs HTTP server and with nodejs event loop architecture it gets its benefits. It is most widely used framework in the javascript community and many other web frameworks are built using ExpressJS.</p>
<h2 id="setup" tabindex="-1">Setup <a class="header-anchor" href="#setup"></a></h2>
<p>To setup express project you need to install nodejs &amp; npm first. You can download the installers(I work on a windows machine) from nodejs <a href="https://nodejs.org/en/download/">site</a>. Create a new folder and execute the commands in your command line.</p>
<pre class="language-bash"><code class="language-bash"><span class="token operator">></span> <span class="token function">npm</span> init
<span class="token operator">></span> <span class="token function">npm</span> <span class="token function">install</span> <span class="token parameter variable">--save</span> express body-parser mongoose</code></pre>
<p><code>npm init</code> will ask you some question, use Enter key to skip the questions if you want. It will create <code>package.json</code> file in your folder this file is required by npm. The second command will add express, body parser and mongoose packages. We need body parser to parse and format json data for request-response messages and we are going to use MongoDB for this project so we need mongoose package to connect to MongoDB. Please also install MongoDB database on your local machine.</p>
<h2 id="hello-world" tabindex="-1">Hello World <a class="header-anchor" href="#hello-world"></a></h2>
<p>Let's create our first basic setup for expressjs. We will write a program that will print <code>Hello World</code> when accessed from the browser. Create <code>app.js</code> file inside your folder with below code.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">var</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> app <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Hello World!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'App listening on port 3000!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Now open a terminal in your current project directory and run <code>node app.js</code> this will start the express app on port 3000. Open your browser and go to <a href="http://localhost:3000/">http:😕/localhost::3000/</a> you will see <code>Hello World</code>. It's a very basic code what we've written, it just returns the same static message for all request. If you see the message on your browser and there is no error shown in terminal it means you are good to proceed.</p>
<h2 id="handling-post-request" tabindex="-1">Handling Post Request <a class="header-anchor" href="#handling-post-request"></a></h2>
<p>What we've seen in the previous example is a basic GET request. We want to handle data that is sent from the client in form of json, a GET request can also send data to application, however, there is limitation to the amount of data so in such cases a POST request is used which sends data from the client in the body of POST request.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">var</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> bodyParser <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'body-parser'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">var</span> app <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>bodyParser<span class="token punctuation">.</span><span class="token function">urlencoded</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
<span class="token literal-property property">extended</span><span class="token operator">:</span> <span class="token boolean">true</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>bodyParser<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">"/hello"</span><span class="token punctuation">,</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token string-property property">"message"</span><span class="token operator">:</span> <span class="token string">"Hello "</span><span class="token operator">+</span>req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>name<span class="token operator">+</span><span class="token string">" welcome to Express Tutorial"</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token operator">...</span></code></pre>
<p>You can create a post route by using<code>app.post()</code> method, from the above example any <code>POST</code> request that made has been made by the client at <code>/</code> with name parameter in the body will return the welcome message along with the name. The arguments to the <code>get()</code> and <code>post()</code> methods if you have noticed is a path and a function, the path denotes that whenever any request is made for the given path the action should be handled by the function which is passed. The function is a callback with two arguments <code>Request</code> and <code>Response</code>. You can read more about the object methods and parameters at Express documentation.</p>
<p>We have registered a middleware <code>app.use(bodyParser.json())</code> of body-parser that converts the request and response into json. For accessing data of any post request you need to use <code>req.body</code> json object and to access any parameters of a GET URL you need to use <code>req.params</code> json object we will see how to use it further sections of the post.</p>
<h3 id="defining-mongo-schema" tabindex="-1">Defining Mongo Schema <a class="header-anchor" href="#defining-mongo-schema"></a></h3>
<p>For this tutorial, we are using MongoDB to store library data. Mongoose plugin helps us to work with MongoDB in nodejs. Mongoose is a straightforward schema-based approach to model the application. It includes features like query building, typecasting, validation, business logic hooks. To work with MongoDB collections you need to define a schema, as in our case it will be a Book which we will store in the collection. Let's create a Book Schema and store it in a separate folder <code>models</code> in our project structure.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">var</span> mongoose <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'mongoose'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  Schema <span class="token operator">=</span> mongoose<span class="token punctuation">.</span>Schema<span class="token punctuation">;</span>

<span class="token keyword">var</span> bookModel <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Schema</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">title</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">type</span><span class="token operator">:</span> String<span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token literal-property property">author</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">type</span><span class="token operator">:</span> String<span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token literal-property property">genre</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">type</span><span class="token operator">:</span> String<span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token literal-property property">read</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">type</span><span class="token operator">:</span> Boolean<span class="token punctuation">,</span>
    <span class="token keyword">default</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

module<span class="token punctuation">.</span>exports <span class="token operator">=</span> mongoose<span class="token punctuation">.</span><span class="token function">model</span><span class="token punctuation">(</span><span class="token string">'Book'</span><span class="token punctuation">,</span> bookModel<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>The schema definition is very simple for this tutorial. We are going to store information regarding a book like a title, author, genre and a property which will indicate if the book is read. We are not going to include any mongoose validation in this as we want to keep the things simple. Will dive deeper into mongoose in some other separate post.</p>
<p>As our schema is ready now we need some way to insert books into the collection and for this, we will add a new route that saves book information to the DB.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token operator">...</span> previous code here
<span class="token keyword">var</span> mongoose <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'mongoose'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> db<span class="token punctuation">;</span>

<span class="token keyword">var</span> db <span class="token operator">=</span> mongoose<span class="token punctuation">.</span><span class="token function">connect</span><span class="token punctuation">(</span><span class="token string">"mongodb://localhost:27017/libraryApp"</span><span class="token punctuation">,</span><span class="token punctuation">{</span>
<span class="token literal-property property">useMongoClient</span><span class="token operator">:</span> <span class="token boolean">true</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token operator">...</span> previous code here
<span class="token keyword">var</span> Book <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./models/bookModel'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">"/addbook"</span><span class="token punctuation">,</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
<span class="token keyword">var</span> book <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Book</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>body<span class="token punctuation">)</span><span class="token punctuation">;</span>
book<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">201</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span>book<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>As you would see from above code for connecting to MongoDB we need to import <code>mongoose</code> package to our code and we do it using <code>require</code>. To connect to the DB mongoose has the <code>.connect()</code> method that takes in connection URL and configuration json options as parameters. As our DB is locally deployed we use the local URL and port. The <code>useMongoClient</code> is new, it tells the initialization logic that the connection mode is a client. Older mongoose version prior to 4.11.0 didn't have this option. So, if you are upgrading your mongoose library to a newer version then you will get an error if you try to connect to mongo without this option.</p>
<p>The new post route <code>/addbook</code> handles post requests, inside the callback function we create a new Book instance passing <code>req.body</code> to the constructor, as we have registered body-parser middleware the request body get's automatically converted to json object this new instance is called a Document which then can be saved or retrieved from the DB. However, for Book Schema to be available in our program we need to import our <code>Book</code> schema from the <code>model</code> package. Once we create a Book instance there are various static helper methods available for a Model like <code>save</code>, <code>update</code>, <code>remove</code>, <code>find</code> you can find more about those in Mongoose Documentation. After we have the instance available we call the <code>save</code> method which will store the book information to DB.</p>
<p>The helper method is of pattern <code>callback(error, results)</code>. Results depend upon the operation like <code>find</code>, <code>findOne</code>, <code>count</code> which returns value from the DB. For our above route, we are saving the data, we are not going to have any return value so it's just a callback which will return error object in case of any error that might happen while storing the document to mongo. We check if there is an error and return <code>500</code> status code and if everything works perfectly we will return back the same Book object as a response. Storing data to MongoDB will have some more properties added to the json object like <code>_id</code><em>(unique key)</em> and <code>ver</code>.</p>
<p>If we run the program now and do a post request we will be able to save the book information to the DB. You need to have some REST client utility for testing. I use Restless Client extension of my chrome browser, you can also download it from chrome web store or you can use any other client utility for testing.</p>
<h2 id="handling-get-request" tabindex="-1">Handling GET Request <a class="header-anchor" href="#handling-get-request"></a></h2>
<p>Our POST route handles the insertion of data to our MongoDB. We need two more routes, one which will show all the books as an array and another to show individual book by its id. It might happen in a real-world application that you will not display all the details right on a single page. Take for an example of my blog, on the home page you won't see the entire blog contents, you would see some excerpt and the title but when you click on the title you are taking to a new page where you would see the entire contents, comments section etc.</p>
<pre class="language-javascript"><code class="language-javascript">app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/books'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  Book<span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> books</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
      res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span>books<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/book/:id'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  Book<span class="token punctuation">.</span><span class="token function">findById</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>params<span class="token punctuation">.</span>id<span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> book</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>book<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span>book<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
      res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">404</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Book Not Found.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Our route <code>/books</code> finds all the books from <code>Book</code> model using <code>find({condition},{callback})</code> method that takes condition object like a where clause. In our case, we want to retrieve all the books so we are passing an empty object and it will return all the books to our callback. If there is an issue while getting the data the route will return status code <code>500</code> with an error message or else it will return the books object as json.</p>
<p>Another route <code>/book/:id</code> finds the book with the given id. For a single record from MongoDB, we use <code>findById</code> which returns the single object matching the condition.</p>
<h2 id="handling-put-request" tabindex="-1">Handling PUT Request <a class="header-anchor" href="#handling-put-request"></a></h2>
<p>Our POST and GET routes handle insertion and retrieval of book information. We now need a new route that will handle requests for updating book details. For this we will use the same route URL <code>/book/:id</code> however the update will be handled using HTTP PUT verb. The flow very is simple, first, we will find the book by its <code>id</code> which will arrive as a part of <code>req.params</code> in our request URL. Mongoose <code>findById</code> method returns document by <code>id</code> as we have seen in the previous code sample, once we get the book from DB will update the information with contents of the body. And at last a call to <code>save</code> method will update the details back to our MongoDB.</p>
<pre class="language-javascript"><code class="language-javascript">app<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">'/book/:id'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  Book<span class="token punctuation">.</span><span class="token function">findById</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>params<span class="token punctuation">.</span>id<span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> book</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>book<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      book<span class="token punctuation">.</span>title <span class="token operator">=</span> req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>title<span class="token punctuation">;</span>
      book<span class="token punctuation">.</span>genre <span class="token operator">=</span> req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>genre<span class="token punctuation">;</span>
      book<span class="token punctuation">.</span>author <span class="token operator">=</span> req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>author<span class="token punctuation">;</span>
      book<span class="token punctuation">.</span>read <span class="token operator">=</span> req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>read<span class="token punctuation">;</span>

      book<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
          res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
          res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
          res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span>book<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
      res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">404</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Book Not Found.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2 id="handling-delete-request" tabindex="-1">Handling DELETE Request <a class="header-anchor" href="#handling-delete-request"></a></h2>
<p>At last, we are left with delete functionality in our library App. We want to delete the book from our MongoDB so based on <code>id</code> which is the unique key for our document we find it as we have done previously using <code>findById</code> method and then mongoose model has a <code>remove({callback})</code> method that removes the document. We will utilize the same route address <code>/book/:id</code> with DELETE verb. So whenever a delete request is made by the client on this URL our delete functionality will get invoked.</p>
<pre class="language-javascript"><code class="language-javascript">app<span class="token punctuation">.</span><span class="token function">delete</span><span class="token punctuation">(</span><span class="token string">'/book/:id'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  Book<span class="token punctuation">.</span><span class="token function">findById</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>params<span class="token punctuation">.</span>id<span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> book</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>book<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      book<span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token string">'Book Removed.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
      res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">404</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'No Book Found.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2 id="chaining-verbs" tabindex="-1">Chaining Verbs <a class="header-anchor" href="#chaining-verbs"></a></h2>
<p>The last three routes get, update and delete are bound to same route URL however the different HTTP methods handle the updating and deleting logic. Express allows us to chain such common routes. Let's change our code for DELETE, PUT and GET to chained to a common route <code>/book/:id</code>.</p>
<pre class="language-javascript"><code class="language-javascript">app
  <span class="token punctuation">.</span><span class="token function">route</span><span class="token punctuation">(</span><span class="token string">'/books/:id'</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    Book<span class="token punctuation">.</span><span class="token function">findById</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>params<span class="token punctuation">.</span>id<span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> book</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>book<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span>book<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">404</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Book Not Found.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    Book<span class="token punctuation">.</span><span class="token function">findById</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>params<span class="token punctuation">.</span>id<span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> book</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>book<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        book<span class="token punctuation">.</span>title <span class="token operator">=</span> req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>title<span class="token punctuation">;</span>
        book<span class="token punctuation">.</span>genre <span class="token operator">=</span> req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>genre<span class="token punctuation">;</span>
        book<span class="token punctuation">.</span>author <span class="token operator">=</span> req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>author<span class="token punctuation">;</span>
        book<span class="token punctuation">.</span>read <span class="token operator">=</span> req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>read<span class="token punctuation">;</span>

        book<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
          <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
          <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
            res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span>book<span class="token punctuation">)</span><span class="token punctuation">;</span>
          <span class="token punctuation">}</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">404</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Book Not Found.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">delete</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    Book<span class="token punctuation">.</span><span class="token function">findById</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>params<span class="token punctuation">.</span>id<span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> book</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>book<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        book<span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
          <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
          <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
            res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Removed'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
          <span class="token punctuation">}</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">404</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Book Not Found.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Have you observed in our above code that whenever we need to get, update or delete the book we first need to find the book object from our mongo collection? Its kind of code repetition we are doing which finds the book and if there's an error returns 500 error or if we don't find the book it returns 404. This is where Express middleware functions come into the picture.</p>
<h2 id="middleware-functions" tabindex="-1">Middleware Functions <a class="header-anchor" href="#middleware-functions"></a></h2>
<p>Express Middleware functions are the functions that have access to the request object, response object and the next middleware function in application's request-response cycle. Middleware functions allow you to run the code, modify the request-response object, end the request-response cycle or call the next middleware function in the chain. The next function when called passes the control to the next middleware function in the chain. If the current middleware function does not end the request-response cycle then it must call the <code>next()</code> otherwise the request will be left hanging.</p>
<p>There are different types of middleware function that an Express App can have::</p>
<ul>
<li>Application-level middleware-Router-level middleware</li>
<li>Error-level middleware</li>
<li>Built-in middleware</li>
<li>Third-party middleware</li>
</ul>
<p>The <code>body-parser</code> which we used in our application is a type of third-party middleware. If you want to log all the request-response of an application you can write your own application-level middleware.</p>
<p>Let's write an application-level middleware that will handle our code repetition.</p>
<pre class="language-javascript"><code class="language-javascript">app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token string">'/book/:id'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  Book<span class="token punctuation">.</span><span class="token function">findById</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>params<span class="token punctuation">.</span>id<span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> book</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>book<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      req<span class="token punctuation">.</span>book <span class="token operator">=</span> book<span class="token punctuation">;</span>
      <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
      res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">404</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Book Not Found'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>This middleware is an application level easiest way to identify is to look for <code>app.use(...)</code> it indicates the middleware is registered at the app level. We no longer have to find the book in every method of our routes, we should change our code as below.</p>
<pre class="language-javascript"><code class="language-javascript">app
  <span class="token punctuation">.</span><span class="token function">route</span><span class="token punctuation">(</span><span class="token string">'/books/:id'</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span>book<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    req<span class="token punctuation">.</span>book<span class="token punctuation">.</span>title <span class="token operator">=</span> req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>title<span class="token punctuation">;</span>
    req<span class="token punctuation">.</span>book<span class="token punctuation">.</span>genre <span class="token operator">=</span> req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>genre<span class="token punctuation">;</span>
    req<span class="token punctuation">.</span>book<span class="token punctuation">.</span>author <span class="token operator">=</span> req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>author<span class="token punctuation">;</span>
    req<span class="token punctuation">.</span>book<span class="token punctuation">.</span>read <span class="token operator">=</span> req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>read<span class="token punctuation">;</span>

    book<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span>book<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">delete</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    book<span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Removed'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2 id="code-cleanup" tabindex="-1">Code Cleanup <a class="header-anchor" href="#code-cleanup"></a></h2>
<p>All the functionality we have written up till now is within one file. For a small application like this it would be no issue but as we add more and more functionality to our application it becomes a bit cumbersome to manage everything in one file.</p>
<p>We need to modularize our code by separating things into different files and packages. We have done it for model's but our routing logic and everything else is still contained within our <code>app.js</code> file. In this section will try to divide our code into two parts all the database related functionality which is needed for the routes will go into controller's and all the routing logic like creating get, post, put request routes will go into routers.</p>
<h3 id="controllers" tabindex="-1">Controllers <a class="header-anchor" href="#controllers"></a></h3>
<p>We will put all our DB related code into a new javascript file into controller package. Create a new folder in your project and name it <code>controllers</code> also create a new file <code>bookController.js</code> and use the below code.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">var</span> <span class="token function-variable function">bookController</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">Book</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">var</span> <span class="token function-variable function">filterBook</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    Book<span class="token punctuation">.</span><span class="token function">findById</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>params<span class="token punctuation">.</span>id<span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> book</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>book<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        req<span class="token punctuation">.</span>book <span class="token operator">=</span> book<span class="token punctuation">;</span>
        <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">404</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'No Book Found.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
  <span class="token keyword">var</span> <span class="token function-variable function">bookById</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>book<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>

  <span class="token keyword">var</span> <span class="token function-variable function">post</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">var</span> book <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Book</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>body<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>book<span class="token punctuation">.</span>title<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">400</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Title is Required.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
      book<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">201</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span>book<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>

  <span class="token keyword">var</span> <span class="token function-variable function">get</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    Book<span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> books</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>books<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span>books<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'No Books Found.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>

  <span class="token keyword">var</span> <span class="token function-variable function">update</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    req<span class="token punctuation">.</span>book<span class="token punctuation">.</span>title <span class="token operator">=</span> res<span class="token punctuation">.</span>body<span class="token punctuation">.</span>title<span class="token punctuation">;</span>
    req<span class="token punctuation">.</span>book<span class="token punctuation">.</span>genre <span class="token operator">=</span> res<span class="token punctuation">.</span>body<span class="token punctuation">.</span>genre<span class="token punctuation">;</span>
    req<span class="token punctuation">.</span>book<span class="token punctuation">.</span>author <span class="token operator">=</span> res<span class="token punctuation">.</span>body<span class="token punctuation">.</span>author<span class="token punctuation">;</span>
    req<span class="token punctuation">.</span>book<span class="token punctuation">.</span>read <span class="token operator">=</span> res<span class="token punctuation">.</span>body<span class="token punctuation">.</span>read<span class="token punctuation">;</span>

    req<span class="token punctuation">.</span>book<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>book<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>

  <span class="token keyword">var</span> <span class="token function-variable function">remove</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    req<span class="token punctuation">.</span>book<span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Book deleted.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">post</span><span class="token operator">:</span> post<span class="token punctuation">,</span>
    <span class="token literal-property property">get</span><span class="token operator">:</span> get<span class="token punctuation">,</span>
    <span class="token literal-property property">bookById</span><span class="token operator">:</span> bookById<span class="token punctuation">,</span>
    <span class="token literal-property property">remove</span><span class="token operator">:</span> remove<span class="token punctuation">,</span>
    <span class="token literal-property property">update</span><span class="token operator">:</span> update<span class="token punctuation">,</span>
    <span class="token literal-property property">filterBook</span><span class="token operator">:</span> filterBook<span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

module<span class="token punctuation">.</span>exports <span class="token operator">=</span> bookController<span class="token punctuation">;</span></code></pre>
<p>Our controller is basically an object that exposes methods like get, post, update. It takes <code>Book</code> schema as an argument which is passed from the router.</p>
<h3 id="routers" tabindex="-1">Routers <a class="header-anchor" href="#routers"></a></h3>
<p>Routing in Express refers to the endpoint of the application and how they respond to requests. For making our app.js connect to our controller we extract all the routing logic from the app.js to our new file bookRouter.js in routes folder.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">var</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> mongoose <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'mongoose'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">var</span> <span class="token function-variable function">router</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">Book</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">var</span> bookRouter <span class="token operator">=</span> express<span class="token punctuation">.</span><span class="token function">Router</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">var</span> bookController <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'../controllers/bookController.js'</span><span class="token punctuation">)</span><span class="token punctuation">(</span>Book<span class="token punctuation">)</span><span class="token punctuation">;</span>

  bookRouter<span class="token punctuation">.</span><span class="token function">route</span><span class="token punctuation">(</span><span class="token string">'/'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>bookController<span class="token punctuation">.</span>get<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span>bookController<span class="token punctuation">.</span>post<span class="token punctuation">)</span><span class="token punctuation">;</span>

  bookRouter<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token string">'/:id'</span><span class="token punctuation">,</span> bookController<span class="token punctuation">.</span>filterBook<span class="token punctuation">)</span><span class="token punctuation">;</span>

  bookRouter
    <span class="token punctuation">.</span><span class="token function">route</span><span class="token punctuation">(</span><span class="token string">'/:id'</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>bookController<span class="token punctuation">.</span>bookById<span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span>bookController<span class="token punctuation">.</span>update<span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">delete</span><span class="token punctuation">(</span>bookController<span class="token punctuation">.</span>remove<span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> bookRouter<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> router<span class="token punctuation">;</span></code></pre>
<p>It's  pretty straightforward, we create a new router using <code>express.Router</code> also we need our controller to bind to so we import it using require passing the same Book schema which we receive as an argument to the router. The reason behind injecting the Book schema is that it makes the module more easy to test, we can inject a mock Book schema from unit test case and test the router. We bind the get all books and post functionality to the <code>/</code> root of our route and any additional request for an individual book like the update, delete, view on <code>/:id</code> route. If you see <code>router.use()</code> in above that means this is a router-level middleware it's the same middleware which was previously application level but now route-level.</p>
<h3 id="final-app.js" tabindex="-1">Final app.js <a class="header-anchor" href="#final-app.js"></a></h3>
<p>The only final changes that are remaning for our application to work is the app.js file. We need to import our route and register.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">var</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> bodyParser <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'body-parser'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> mongoose <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'mongoose'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> db<span class="token punctuation">;</span>

<span class="token keyword">var</span> db <span class="token operator">=</span> mongoose<span class="token punctuation">.</span><span class="token function">connect</span><span class="token punctuation">(</span><span class="token string">'mongodb://localhost:27017/libraryApp'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">useMongoClient</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">var</span> app <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>
  bodyParser<span class="token punctuation">.</span><span class="token function">urlencoded</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    <span class="token literal-property property">extended</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>bodyParser<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">var</span> Book <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./models/bookModel'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> bookRouter <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./routes/bookRoutes'</span><span class="token punctuation">)</span><span class="token punctuation">(</span>Book<span class="token punctuation">)</span><span class="token punctuation">;</span>

app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token string">'/api/books'</span><span class="token punctuation">,</span> bookRouter<span class="token punctuation">)</span><span class="token punctuation">;</span>

app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Hello, Welcome to library rest API.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span>process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">PORT</span> <span class="token operator">||</span> <span class="token number">3000</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'App listening on port 3000!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2 id="explore-more%3A%3A" tabindex="-1">Explore more:: <a class="header-anchor" href="#explore-more%3A%3A"></a></h2>
<p>Looking for developing Express API using Typescript? You could read more about on <a href="https://www.toptal.com/express-js/nodejs-typescript-rest-api-pt-1" target="_blank">Toptal's Blog</a> By <a href="https://www.toptal.com/resume/marcos-henrique-da-silva" target="_blank">Marcos Henrique da Silva</a></p></p>
<!--kg-card-end: html-->

                ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Serializing Data Using Google Protobuf</title>
            <link href="https://iamninad.com/posts/serializing-data-using-google-proto-buf/"/>
            <updated>2018-03-05T00:00:00Z</updated>
            <id>https://iamninad.com/posts/serializing-data-using-google-proto-buf/</id>
            <content type="html">
                <![CDATA[
                <h2 id="1.-overview" tabindex="-1">1. Overview <a class="header-anchor" href="#1.-overview"></a></h2>
<p>In this post, we will see how to use Google Protocol Buffers a language-neutral, platform-neutral, extensible and a popular data format to serialize data structure. We can define a protocol message in a .proto file and then using compiler we can generate code in languages like Java, Python, Go, C++, C#.</p>
<p>There are many advantages to using Google ProtoBuffer like it's a platform-neutral, you can share data between two different languages. Backward compatibility can be handled easily, you can add new data to your format and your old generated code will work without any issue. The binary format generated by the google protobuf is very small than a normal json and conversion/parsing is very fast. The generated code also provides methods to create our protocol object instance and read-write it to any byte stream like a file, network etc saving us from writing the complex logic to encode decode data 😴.</p>
<h2 id="2.-defining-maven-dependency" tabindex="-1">2. Defining Maven Dependency <a class="header-anchor" href="#2.-defining-maven-dependency"></a></h2>
<p>Once we define the message and generate the code we need the code to be used in our java project and for this, we need to add google proto buffer dependency in our maven project.</p>
<pre class="language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">></span></span>com.google.protobuf<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">></span></span>protobuf-java<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">></span></span>3.5.0<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">></span></span></code></pre>
<h2 id="1.-defining-a-protobuf-message" tabindex="-1">1. Defining a Protobuf Message <a class="header-anchor" href="#1.-defining-a-protobuf-message"></a></h2>
<p>For defining a new protocol we need to create a .proto file, there is a standard format described according to which we have to write our .proto. We will write a very simple protocol in a protobuf format::</p>
<pre class="language-protobuf"><code class="language-protobuf"><span class="token keyword">message</span> <span class="token class-name">Post</span> <span class="token punctuation">{</span>
    <span class="token builtin">string</span> id <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
    <span class="token builtin">string</span> title <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>Defining a protocol message is simple, the above example defines a <code>Post.proto</code> message. It has two fields id and title of type string, similarly we can have fields of other scalar types like number, double, or another message field. Each field is given a unique tag number like <code>=1</code>, this tag number is used to identify the message in the binary format, field marked 1 will be saved first then field marked 2 and so on. You can read more about the structure of <code>.proto</code> file here.</p>
<p>Let's take a more complicated message format.</p>
<pre class="language-protobuf"><code class="language-protobuf"><span class="token keyword">syntax</span><span class="token operator">=</span><span class="token string">"proto3"</span><span class="token punctuation">;</span>

<span class="token keyword">package</span> com<span class="token punctuation">.</span>infinityworks<span class="token punctuation">.</span>google<span class="token punctuation">.</span>model<span class="token punctuation">;</span>

<span class="token keyword">option</span> java_outer_classname<span class="token operator">=</span><span class="token string">"LibraryModel"</span><span class="token punctuation">;</span>

<span class="token keyword">message</span> <span class="token class-name">Book</span><span class="token punctuation">{</span>
    <span class="token builtin">string</span> isbn <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
    <span class="token builtin">string</span> title <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>
    <span class="token builtin">string</span> publish_date <span class="token operator">=</span> <span class="token number">3</span><span class="token punctuation">;</span>
    <span class="token keyword">repeated</span> <span class="token positional-class-name class-name">Author</span> author <span class="token operator">=</span> <span class="token number">4</span><span class="token punctuation">;</span>
    <span class="token positional-class-name class-name">Genre</span> genre <span class="token operator">=</span> <span class="token number">5</span><span class="token punctuation">;</span>

    <span class="token keyword">message</span> <span class="token class-name">Author</span><span class="token punctuation">{</span>
        <span class="token builtin">string</span> name <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">enum</span> <span class="token class-name">Genre</span><span class="token punctuation">{</span>
        UNKNOWN <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
        SELF_DEVELOPMENT <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
        BUSINESS <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>
        TECHNOLOGY <span class="token operator">=</span> <span class="token number">3</span><span class="token punctuation">;</span>
        ROMANCE <span class="token operator">=</span> <span class="token number">4</span><span class="token punctuation">;</span>
        THRILLER <span class="token operator">=</span> <span class="token number">5</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">message</span> <span class="token class-name">Library</span><span class="token punctuation">{</span>
    <span class="token keyword">repeated</span> <span class="token positional-class-name class-name">Book</span> books <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>The first line <code>syntax=&quot;proto3&quot;</code> tells the compiler that we are using protobuff version 3. If we omit this line the compiler will compile the protocol using version 2. package and <code>java_outer_classname</code> options provides package and class name related information to the compiler, package is the java package in which the classes are put and classname is the outerclass name that will hold all the message type in our single .proto file, if <code>java_outer_classname</code> is not present then the name of first message name will be used as a class name in this case it will be <code>BookOuterClass.java</code>.</p>
<p>The message Book has five elements <code>isbn</code>, <code>title</code>, <code>published_date</code> of scalar type and author, genre of other message and enum type. Variables which are longer like <code>published_date</code> should be separated by _ and all the variable names should be small case. repeated is a special keyword both in proto2 and proto3, when we want to have multiple elements of the same type say a collection of same element type like in our case a Book can have one or more Author's then mark such field as repeated, the compiler generates list based java variable to hold multiple values of the same type and also provides builder for Author.</p>
<p>We have another message type Library which contains collection of our Book objects.</p>
<h2 id="4.-generating-code-from-a-.proto-file" tabindex="-1">4. Generating Code From a .proto File <a class="header-anchor" href="#4.-generating-code-from-a-.proto-file"></a></h2>
<p>Once we have defined our proto file we can generate code for it. To generate the code install the protobuff compiler to your local machine and add it to your environment path. Then run the below command.</p>
<pre class="language-shell-session"><code class="language-shell-session"><span class="token output">$> protoc -I=. --java_out=./src/main/java Library.proto
</span></code></pre>
<p>The protoc command will generate all java class files from <code>Library.proto.</code> The compiler also provides error information for any issue with the .proto file. The <code>-I</code> option specifies a directory where all the proto files resides. The <code>--java_out</code> specifies the directory where the generated class files will be created.</p>
<p>The generated class files have Data access classes with the setter, getter methods and provide fluent API builder using which you can generate the instance of the protocol. It also provides some additional methods to serialize and deserialize the instance to the binary format.</p>
<h2 id="5.-building-instance-of-a-protobuffer-defined-message" tabindex="-1">5. Building Instance of a Protobuffer Defined Message <a class="header-anchor" href="#5.-building-instance-of-a-protobuffer-defined-message"></a></h2>
<p>Once we have all the classes generated by compiler we can create our message instance for Book class.</p>
<pre class="language-java"><code class="language-java"><span class="token class-name">LibraryModel<span class="token punctuation">.</span>Book</span> book <span class="token operator">=</span> <span class="token class-name">LibraryModel<span class="token punctuation">.</span>Book</span><span class="token punctuation">.</span><span class="token function">newBuilder</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">setIsbn</span><span class="token punctuation">(</span><span class="token string">"1213-2322-3212-1231"</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">setTitle</span><span class="token punctuation">(</span><span class="token string">"The Next Imaginary Book of My Mind"</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">addAuthor</span><span class="token punctuation">(</span><span class="token class-name">LibraryModel<span class="token punctuation">.</span>Book<span class="token punctuation">.</span>Author</span><span class="token punctuation">.</span><span class="token function">newBuilder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">setName</span><span class="token punctuation">(</span><span class="token string">"Ninad"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">setGenre</span><span class="token punctuation">(</span><span class="token class-name">LibraryModel<span class="token punctuation">.</span>Book<span class="token punctuation">.</span>Genre</span><span class="token punctuation">.</span><span class="token constant">THRILLER</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token function">assertEquals</span><span class="token punctuation">(</span><span class="token string">"1213-2322-3212-1231"</span><span class="token punctuation">,</span> book<span class="token punctuation">.</span><span class="token function">getIsbn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">assertEquals</span><span class="token punctuation">(</span><span class="token string">"The Next Imaginary Book of My Mind"</span><span class="token punctuation">,</span> book<span class="token punctuation">.</span><span class="token function">getTitle</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">assertEquals</span><span class="token punctuation">(</span><span class="token class-name">LibraryModel<span class="token punctuation">.</span>Book<span class="token punctuation">.</span>Genre</span><span class="token punctuation">.</span><span class="token constant">THRILLER</span><span class="token punctuation">,</span> book<span class="token punctuation">.</span><span class="token function">getGenre</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">assertEquals</span><span class="token punctuation">(</span><span class="token string">"Ninad"</span><span class="token punctuation">,</span> book<span class="token punctuation">.</span><span class="token function">getAuthor</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>We can create a fluent builder using the <code>newBuilder()</code> method of <code>LibraryModel.Book</code> class, the builder provides methods to set the field data and the <code>build()</code> method will create the object of the Book class. The good thing about the builder api is that the instance generated after calling the <code>.build()</code> method are immutable.</p>
<h2 id="6.-serializing-and-deserializing-protobuffer-message" tabindex="-1">6. Serializing and Deserializing Protobuffer Message <a class="header-anchor" href="#6.-serializing-and-deserializing-protobuffer-message"></a></h2>
<p>When we have our object of Book class, we want to persist it to disc or send it across the network to some other system. We want to write it into a binary format that can easily be read. The generated class provide methods to write the object to any byte stream.</p>
<pre class="language-java"><code class="language-java"><span class="token class-name">LibraryModel<span class="token punctuation">.</span>Library</span> library <span class="token operator">=</span> <span class="token class-name">LibraryModel<span class="token punctuation">.</span>Library</span><span class="token punctuation">.</span><span class="token function">newBuilder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">addBooks</span><span class="token punctuation">(</span>book<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">FileOutputStream</span> outputStream <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">FileOutputStream</span><span class="token punctuation">(</span><span class="token string">"d:/data.dat"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
library<span class="token punctuation">.</span><span class="token function">writeTo</span><span class="token punctuation">(</span>outputStream<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>We have added the book object that we have created to our library builder, and using the <code>.writeTo()</code> method we save the library object to a file.</p>
<p>We can read the binary encoded format to load the saved data. The utility method <code>.parseFrom()</code> takes the stream from which data can be loaded.</p>
<pre class="language-java"><code class="language-java"><span class="token class-name">LibraryModel<span class="token punctuation">.</span>Library</span> parsedLibrary <span class="token operator">=</span> <span class="token class-name">LibraryModel<span class="token punctuation">.</span>Library</span><span class="token punctuation">.</span><span class="token function">parseFrom</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">FileInputStream</span><span class="token punctuation">(</span><span class="token string">"d:/data.dat"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">LibraryModel<span class="token punctuation">.</span>Book</span> book1 <span class="token operator">=</span> parsedLibrary<span class="token punctuation">.</span><span class="token function">getBooks</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token function">assertEquals</span><span class="token punctuation">(</span><span class="token string">"1213-2322-3212-1231"</span><span class="token punctuation">,</span> book1<span class="token punctuation">.</span><span class="token function">getIsbn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">assertEquals</span><span class="token punctuation">(</span><span class="token string">"The Next Imaginary Book of My Mind"</span><span class="token punctuation">,</span> book1<span class="token punctuation">.</span><span class="token function">getTitle</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">assertEquals</span><span class="token punctuation">(</span><span class="token class-name">LibraryModel<span class="token punctuation">.</span>Book<span class="token punctuation">.</span>Genre</span><span class="token punctuation">.</span><span class="token constant">THRILLER</span><span class="token punctuation">,</span> book<span class="token punctuation">.</span><span class="token function">getGenre</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">assertEquals</span><span class="token punctuation">(</span><span class="token string">"Ninad"</span><span class="token punctuation">,</span> book1<span class="token punctuation">.</span><span class="token function">getAuthor</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2 id="7.-conclusion" tabindex="-1">7. Conclusion <a class="header-anchor" href="#7.-conclusion"></a></h2>
<p>Thus, we have seen how to serialize and deserialize data to Google Protocol Buffer binary format.</p>
<p>We used basic example to understand how to define a protocol buffer message and use automatic code generation tool to create java based class file. Next, we saw how to serialize and deserialize the data using the generated files.</p>
<p>The examples and java implementation for the above examples can be found in the Github Project. Read more about the Google Protocol Buffer here.</p>

                ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Conditional Beans Creation In Spring Boot</title>
            <link href="https://iamninad.com/posts/conditional-beans-creation-in-spring-boot/"/>
            <updated>2017-08-14T00:00:00Z</updated>
            <id>https://iamninad.com/posts/conditional-beans-creation-in-spring-boot/</id>
            <content type="html">
                <![CDATA[
                <p>Spring Container is core to Spring Framework. It manages the entire lifecycle of Spring Beans. A bean is nothing but an instance of a class right?. You can declare a bean definition either using XML based configuration or Annotation based configuration, Annotation based is my personal favorite. But, have you came across a situation where you want to initialize bean based on a certain condition?</p>
<p>Like if my Java version is 7 and I want some beans to get created and if it's Java 8 than some other beans and not those that relate to Java 7. I know right now many of us add both the spring beans definition in our XML and java config file. And then, using some if...else logic to do the required thing, isn't it? But hey, we want to write programs that can be easily re-configured and doesn't require major code changes because in large application making a small change can trigger a big testing and build phase. And, you know how painful it is.</p>
<p>Well, to rescue us from such situations spring boot provides the support for conditional bean initialization out of the box and it's right built into spring boot (since version 1.1.0). That means you don't have to write unnecessary if...else blocks to check the conditions and then use the right bean. In this post, I will walk you through different ways of conditionally creating spring beans.</p>
<p>There are various Annotation that are provided by Spring Boot each having a specific purpose. The below list shows all the different Conditional Annotation in Spring.</p>
<ul>
<li><a href="http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/condition/ConditionalOnBean.html">ConditionalOnBean</a></li>
<li><a href="http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/condition/ConditionalOnClass.html">ConditionalOnClass</a></li>
<li><a href="http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/condition/ConditionalOnCloudPlatform.html">ConditionalOnCloudPlatform</a></li>
<li><a href="http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/condition/ConditionalOnExpression.html">ConditionalOnExpression</a></li>
<li><a href="http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/condition/ConditionalOnJava.html">ConditionalOnJava</a></li>
<li><a href="http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/condition/ConditionalOnJndi.html">ConditionalOnJndi</a></li>
<li><a href="http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/condition/ConditionalOnMissingBean.html">ConditionalOnMissingBean</a></li>
<li><a href="http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/condition/ConditionalOnMissingClass.html">ConditionalOnMissingClass</a></li>
<li><a href="http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/condition/ConditionalOnNotWebApplication.html">ConditionalOnNotWebApplication</a></li>
<li><a href="http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/condition/ConditionalOnProperty.html">ConditionalOnProperty</a></li>
<li><a href="http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/condition/ConditionalOnResource.html">ConditionalOnResource</a></li>
<li><a href="http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/condition/ConditionalOnSingleCandidate.html">ConditionalOnSingleCandidate</a></li>
<li><a href="http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/condition/ConditionalOnWebApplication.html">ConditionalOnWebApplication</a></li>
</ul>
<p>I won't be going through all the annotations in this post. However, after explaining you some of them you will get the idea of how to use others. Please look for the comments in the code blocks for explanations.</p>
<h2 id="conditionalonbean" tabindex="-1">ConditionalOnBean <a class="header-anchor" href="#conditionalonbean"></a></h2>
<p>Conditional that only matches when the given Bean name or classes are already present in the BeanFactory. The annotation when placed on a <code>@Bean</code> then the bean class is default to the return type of the bean definition.</p>
<pre class="language-java"><code class="language-java"><span class="token annotation punctuation">@Configuration</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ConditionalOnBeanConfig</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@Bean</span>
    <span class="token keyword">public</span> <span class="token class-name">A</span> <span class="token function">beanA</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">A</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Bean</span>
    <span class="token annotation punctuation">@ConditionalOnBean</span><span class="token punctuation">(</span>name<span class="token operator">=</span><span class="token string">"beanA"</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">B</span> <span class="token function">beanB</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">B</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// it will initialize as beanA is present in the beanFactory.</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Bean</span>
    <span class="token annotation punctuation">@ConditionalOnBean</span>
    <span class="token keyword">public</span> <span class="token class-name">C</span> <span class="token function">beanC</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">C</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// will not get initialized as there is no bean with return type C in BeanFactory.</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Bean</span>
    <span class="token keyword">public</span> <span class="token class-name">SimpleInt</span> <span class="token function">beanAInt</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">ASimpleInt</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Bean</span>
    <span class="token annotation punctuation">@ConditionalOnBean</span>
    <span class="token keyword">public</span> <span class="token class-name">SimpleInt</span> <span class="token function">beanBInt</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">BSimpleInt</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="conditionalonclass" tabindex="-1">ConditionalOnClass <a class="header-anchor" href="#conditionalonclass"></a></h2>
<p>Conditional that only matches when the specified class is available on the classpath. The attributes to the annotation are <code>name</code> and <code>value</code>. Use the name attribute in case if you want to specify the class name and you are not sure whether the classes will be available on the classpath and use value when the classes are available on the classpath.</p>
<pre class="language-java"><code class="language-java"><span class="token annotation punctuation">@Configuration</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ConditionOnClassConfig</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@Bean</span>
    <span class="token annotation punctuation">@ConditionalOnClass</span><span class="token punctuation">(</span>value<span class="token operator">=</span><span class="token punctuation">{</span><span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span>HashMap</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">A</span> <span class="token function">beanA</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">A</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// will get created as HashMap class is on the classpath</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Bean</span>
    <span class="token annotation punctuation">@ConditionalOnClass</span><span class="token punctuation">(</span>name<span class="token operator">=</span><span class="token string">"com.sample.Dummy"</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">B</span> <span class="token function">beanB</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">B</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// won't be created as Dummy class is not on classpath</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Bean</span>
    <span class="token annotation punctuation">@ConditionalOnClass</span><span class="token punctuation">(</span>value<span class="token operator">=</span><span class="token class-name"><span class="token namespace">com<span class="token punctuation">.</span>sample<span class="token punctuation">.</span>bean<span class="token punctuation">.</span>conditional<span class="token punctuation">.</span>model<span class="token punctuation">.</span></span>ASimpleInt</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">C</span> <span class="token function">beanC</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">C</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// ASimpleInt is on the classpath in the project.</span>
                        <span class="token comment">//So, C's instance will be created.</span>
    <span class="token punctuation">}</span>

<span class="token punctuation">}</span></code></pre>
<h2 id="conditionalonmissingbean" tabindex="-1">ConditionalOnMissingBean <a class="header-anchor" href="#conditionalonmissingbean"></a></h2>
<p>Conditional that only matches when the specified bean is missing from the beanfactory. This will only match when the bean definition is processed by the application context and as such is recommended to be used by auto-configuration classes only.</p>
<pre class="language-java"><code class="language-java"><span class="token annotation punctuation">@Configuration</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ConditionalOnMissingBeanConfig</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@Bean</span>
    <span class="token keyword">public</span> <span class="token class-name">A</span> <span class="token function">beanA</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">A</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// will initialize as normal</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Bean</span>
    <span class="token annotation punctuation">@ConditionalOnMissingBean</span><span class="token punctuation">(</span>name<span class="token operator">=</span><span class="token string">"beanA"</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">B</span> <span class="token function">beanB</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">B</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// it will not initialize as</span>
                        <span class="token comment">// beanA is present in the beanFactory.</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Bean</span>
    <span class="token annotation punctuation">@ConditionalOnMissingBean</span><span class="token punctuation">(</span>name<span class="token operator">=</span><span class="token string">"beanD"</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">C</span> <span class="token function">beanC</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">C</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// will get initialized as there is no</span>
                        <span class="token comment">// bean with name beanD in BeanFactory.</span>
    <span class="token punctuation">}</span>

<span class="token punctuation">}</span></code></pre>
<h2 id="conditionalonmissingclass" tabindex="-1">ConditionalOnMissingClass <a class="header-anchor" href="#conditionalonmissingclass"></a></h2>
<p>Conditional that only matches when the specified Class is missing from the classpath.</p>
<pre class="language-java"><code class="language-java"><span class="token annotation punctuation">@Configuration</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ConditionOnMissingClassConfig</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@Bean</span>
    <span class="token annotation punctuation">@ConditionalOnMissingClass</span><span class="token punctuation">(</span>value<span class="token operator">=</span><span class="token punctuation">{</span><span class="token string">"com.sample.Dummy"</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">A</span> <span class="token function">beanA</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">A</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// will get created as Dummy class is missing</span>
                        <span class="token comment">// from classpath.</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Bean</span>
    <span class="token annotation punctuation">@ConditionalOnMissingClass</span><span class="token punctuation">(</span>value<span class="token operator">=</span><span class="token punctuation">{</span><span class="token string">"com.sample.bean.conditional.model.C"</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">B</span> <span class="token function">beanB</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">B</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// won't be created as C is present in classpath.</span>
    <span class="token punctuation">}</span>

<span class="token punctuation">}</span></code></pre>
<h2 id="conditionalonwebapplication" tabindex="-1">ConditionalOnWebApplication <a class="header-anchor" href="#conditionalonwebapplication"></a></h2>
<p>Conditional that only matches when the application context is a web application context.</p>
<blockquote>
<p>Note:: Code is shown in next block.</p>
</blockquote>
<h2 id="conditionalonnotwebapplication" tabindex="-1">ConditionalOnNotWebApplication <a class="header-anchor" href="#conditionalonnotwebapplication"></a></h2>
<p>Conditional that only matches when the application context is not a web application context.</p>
<pre class="language-java"><code class="language-java"><span class="token annotation punctuation">@Configuration</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ConditionalBeanNotWebConfig</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@Bean</span>
    <span class="token annotation punctuation">@ConditionalOnWebApplication</span>
    <span class="token keyword">public</span> <span class="token class-name">A</span> <span class="token function">beanA</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">A</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// will initiate if the context is</span>
                        <span class="token comment">// WebApplicationContext.</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Bean</span>
    <span class="token annotation punctuation">@ConditionalOnNotWebApplication</span>
    <span class="token keyword">public</span> <span class="token class-name">B</span> <span class="token function">beanB</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">B</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// will initiate if the context is not</span>
                        <span class="token comment">// WebApplicationContext.</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="conditionalonresource" tabindex="-1">ConditionalOnResource <a class="header-anchor" href="#conditionalonresource"></a></h2>
<p>Conditional that only matches when the specified resource is available on the classpath.</p>
<pre class="language-java"><code class="language-java"><span class="token annotation punctuation">@Configuration</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ConditionalOnResourceConfig</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@Bean</span>
    <span class="token annotation punctuation">@ConditionalOnResource</span><span class="token punctuation">(</span>resources<span class="token operator">=</span><span class="token punctuation">{</span><span class="token string">"classpath:application.properties"</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">A</span> <span class="token function">beanA</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">A</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// will initiate as application.properties is in</span>
                        <span class="token comment">// classpath.</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Bean</span>
    <span class="token annotation punctuation">@ConditionalOnResource</span><span class="token punctuation">(</span>resources<span class="token operator">=</span><span class="token punctuation">{</span><span class="token string">"file:///e:/doc/data.txt"</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">B</span> <span class="token function">beanB</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">B</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// will not initialize as the file is not</span>
                        <span class="token comment">// present in the given location.</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="conditionalonjava" tabindex="-1">ConditionalOnJava <a class="header-anchor" href="#conditionalonjava"></a></h2>
<p>It checks whether the version matches the current JVM version the application is running. There are two properties to this annotation <code>value</code> and <code>range</code>. The <code>value</code> takes any one of the given <code>JavaVersion</code> enum as given below i.e. SIX, SEVEN, EIGHT, NINE.</p>
<pre class="language-java"><code class="language-java"><span class="token annotation punctuation">@Configuration</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ConditionalBeanJavaConfig</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@Bean</span>
    <span class="token annotation punctuation">@ConditionalOnJava</span><span class="token punctuation">(</span>value<span class="token operator">=</span><span class="token class-name">JavaVersion</span><span class="token punctuation">.</span><span class="token constant">EIGHT</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">A</span> <span class="token function">beanA</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">A</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Bean</span>
    <span class="token annotation punctuation">@ConditionalOnJava</span><span class="token punctuation">(</span>value<span class="token operator">=</span><span class="token class-name">JavaVersion</span><span class="token punctuation">.</span><span class="token constant">SEVEN</span><span class="token punctuation">,</span>range<span class="token operator">=</span><span class="token class-name">Range</span><span class="token punctuation">.</span><span class="token constant">OLDER_THAN</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">B</span> <span class="token function">beanB</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">B</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>In the above case, I am using JDK version 8. So, only <code>beanA</code> will get initialized while the <code>beanB</code> I am trying to check if the JDK version is below 7 using <code>range</code> property which initializes B.</p>
<h2 id="conditionalonproperty" tabindex="-1">ConditionalOnProperty <a class="header-anchor" href="#conditionalonproperty"></a></h2>
<p>Conditional on property checks if the specified property has the specific value. It checks by default if the property is in the Environment and not equals to <strong>false</strong>.</p>
<pre class="language-java"><code class="language-java"><span class="token annotation punctuation">@Configuration</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ConditionalBeanPropertyConfig</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@Bean</span>
    <span class="token annotation punctuation">@ConditionalOnProperty</span><span class="token punctuation">(</span>name<span class="token operator">=</span><span class="token string">"test.property"</span><span class="token punctuation">,</span> havingValue<span class="token operator">=</span><span class="token string">"A"</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">A</span> <span class="token function">beanA</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">A</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Bean</span>
    <span class="token annotation punctuation">@ConditionalOnProperty</span><span class="token punctuation">(</span>name<span class="token operator">=</span><span class="token string">"test.property"</span><span class="token punctuation">,</span> havingValue<span class="token operator">=</span><span class="token string">"B"</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">B</span> <span class="token function">beanB</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">B</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Bean</span>
    <span class="token annotation punctuation">@ConditionalOnProperty</span><span class="token punctuation">(</span>name<span class="token operator">=</span><span class="token string">"test.property"</span><span class="token punctuation">,</span> havingValue<span class="token operator">=</span><span class="token string">"C"</span><span class="token punctuation">,</span>matchIfMissing<span class="token operator">=</span><span class="token boolean">true</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">C</span> <span class="token function">beanC</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">C</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>The above example shows how to configure conditional on property annotation. The <code>havingValue</code> and <code>matchIfMissing</code> allows for additional customization. The having value checks if the given value equals to the value of the property and if it's true then initialize the bean. A <code>havingValue=&quot;&quot;</code> will always returns <strong>true</strong>. <code>matchIfMissing</code> specifies that the condition should match if the property is missing.</p>
<h3 id="junit-test%3A%3A" tabindex="-1">JUnit Test:: <a class="header-anchor" href="#junit-test%3A%3A"></a></h3>
<p>I have wrote JUnits for each of the above example I have given. You can find all those in the given below github link[^1]. To make the post short I didn't include all those. But to show you how the tests works I have put one test case for ConditionBeanPropertyConfig Class as below.</p>
<pre class="language-java"><code class="language-java"><span class="token annotation punctuation">@RunWith</span><span class="token punctuation">(</span><span class="token class-name">SpringRunner</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@SpringBootTest</span><span class="token punctuation">(</span>classes<span class="token operator">=</span><span class="token punctuation">{</span><span class="token class-name">ConditionalBeanPropertyConfig</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ConditionalBeanPropertyConfigTest</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@Autowired</span>
    <span class="token class-name">ApplicationContext</span> ctx<span class="token punctuation">;</span>

    <span class="token annotation punctuation">@Test</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">testBeanA</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">A</span> beanA <span class="token operator">=</span> ctx<span class="token punctuation">.</span><span class="token function">getBean</span><span class="token punctuation">(</span><span class="token class-name">A</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">assertNotNull</span><span class="token punctuation">(</span>beanA<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Test</span><span class="token punctuation">(</span>expected<span class="token operator">=</span><span class="token class-name">NoSuchBeanDefinitionException</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">testBeanB</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">B</span> beanB <span class="token operator">=</span> ctx<span class="token punctuation">.</span><span class="token function">getBean</span><span class="token punctuation">(</span><span class="token class-name">B</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">assertNotNull</span><span class="token punctuation">(</span>beanB<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Test</span><span class="token punctuation">(</span>expected<span class="token operator">=</span><span class="token class-name">NoSuchBeanDefinitionException</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">testBeanC</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">C</span> beanC <span class="token operator">=</span> ctx<span class="token punctuation">.</span><span class="token function">getBean</span><span class="token punctuation">(</span><span class="token class-name">C</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">assertNotNull</span><span class="token punctuation">(</span>beanC<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

<span class="token punctuation">}</span></code></pre>
<p>The Spring Boot Test checks for initialization of All the three beans. But, as the properties file is configured with the value <code>A</code> only <code>testBeanA</code> will return the bean instance while the other two methods will return <code>NoSuchBeanDefinitionException</code>. If the property value is changed to <code>B</code> then, in that case, bean B will get initialized likewise in the case of C. However, if the property <code>test.property</code> is missing from the environment only the <code>C</code> instance will get created leaving A and B uninitialized.</p>
<p><strong>Properties file for All above examples::</strong></p>
<pre class="language-properties"><code class="language-properties"><span class="token key attr-name">test.property</span><span class="token punctuation">=</span><span class="token value attr-value">A</span></code></pre>
<h4 id="test-output" tabindex="-1">Test Output <a class="header-anchor" href="#test-output"></a></h4>
<figure><img src="/images/conditional-beans-creation-in-spring-boot/35654891383_0d888c3f65_o.png" alt="ConditionalOnProperty Test"><figcaption>ConditionalOnProperty Test</figcaption></figure>
<p>I tried to explain most of the Annotation usage and for those that are missing you got the idea of how to use them. If you have any doubt don't bother to comment on the post I will get back to your queries as quickly as possible. Also, please <a href="#">subscribe</a> to the newsletter to get the blog updates. If there's anything else you want to discuss with me use the <a href="https://iamninad.com/contact/">Contact</a> form. Please don't forget to share the post using the below-given links. Thanks!.</p>
<h2 id="links%3A%3A" tabindex="-1">Links:: <a class="header-anchor" href="#links%3A%3A"></a></h2>
<p><a href="https://github.com/ninadingole/springcookbook">Download Code From Github</a></p>
<h4 id="other-entities-used" tabindex="-1">Other Entities Used <a class="header-anchor" href="#other-entities-used"></a></h4>
<pre class="language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">A</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">sayHello</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token string">"Hello From A"</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">B</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">sayHello</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token string">"Hello From B"</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">C</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">sayHello</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token string">"Hello From C"</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">SimpleInt</span> <span class="token punctuation">{</span>
    <span class="token keyword">void</span> <span class="token function">sample</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ASimpleInt</span> <span class="token keyword">implements</span> <span class="token class-name">SimpleInt</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">sample</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Hello From A implementation of SimpleInt"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">BSimpleInt</span> <span class="token keyword">implements</span> <span class="token class-name">SimpleInt</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">sample</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"Hello from B implementation of SimpleInt"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>

                ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Service Locator Using Spring Framework</title>
            <link href="https://iamninad.com/posts/service-locator-using-spring-framework/"/>
            <updated>2017-07-28T00:00:00Z</updated>
            <id>https://iamninad.com/posts/service-locator-using-spring-framework/</id>
            <content type="html">
                <![CDATA[
                <p>When you start with programming someday you will come to hear the words <em>Design Patterns</em>. Design Patterns are solutions to commonly recurring problems in software designs. These are not the final solution but an actual description or template on how to solve the problem. Design Patterns are categorised into 3 groups Creation, Structural &amp; Behavioural. I am not going to go through all those in this post but, if you want to read more about design patterns you can read a very famous book <em>Gang of Four</em>.</p>
<p>In this post, I will be more focusing on <em>Service Locator</em> design pattern or as some says anti-pattern using spring framework. It's a well-known pattern used in many frameworks or for JNDI lookup.</p>
<p>So how this works? The ServiceLocatorFactoryBean takes an interface which need to have method signature of form of Service xxx() or Service xxx(String id) like <code>Service getService() or Service getService(String id)</code> this creates a dynamic proxy which implements the given interface and delegates the task of locating the implementation to an underlying beanFactory.</p>
<p>Which means internally it's still calling getBean on application context, Such service locators permit the decoupling of calling code from the BeanFactory API. According to documentation of Spring, this should be typically used for prototype bean where a new bean instance should be returned on every call, and for singleton bean direct setter/getter injection is preferable.</p>
<h2 id="maven-pom.xml" tabindex="-1">Maven pom.xml <a class="header-anchor" href="#maven-pom.xml"></a></h2>
<pre class="language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>project</span> <span class="token attr-name">xmlns</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://maven.apache.org/POM/4.0.0<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xmlns:</span>xsi</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://www.w3.org/2001/XMLSchema-instance<span class="token punctuation">"</span></span>
	<span class="token attr-name"><span class="token namespace">xsi:</span>schemaLocation</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
	<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>modelVersion</span><span class="token punctuation">></span></span>4.0.0<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>modelVersion</span><span class="token punctuation">></span></span>
	<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">></span></span>com.spring.sample<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">></span></span>
	<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">></span></span>Service-Factory<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">></span></span>
	<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">></span></span>0.0.1-SNAPSHOT<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">></span></span>

	<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>parent</span><span class="token punctuation">></span></span>
		<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">></span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">></span></span>
		<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">></span></span>spring-boot-starter-parent<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">></span></span>
		<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">></span></span>1.5.4.RELEASE<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">></span></span>
	<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>parent</span><span class="token punctuation">></span></span>
	<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependencies</span><span class="token punctuation">></span></span>
		<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">></span></span>
			<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">></span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">></span></span>
			<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">></span></span>spring-boot-starter-web<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">></span></span>
		<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">></span></span>

		<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">></span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">></span></span>org.springframework.boot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">></span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">></span></span>spring-boot-starter-test<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">></span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>scope</span><span class="token punctuation">></span></span>test<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>scope</span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">></span></span>
	<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependencies</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>project</span><span class="token punctuation">></span></span></code></pre>
<p>All you need is the basic sring boot dependencies. You can also add individual jar dependencies but you will only need the spring core one's. The Classes I am using are packaged into the core jar so other packages of spring are not needed.</p>
<h2 id="project-structure%3A%3A" tabindex="-1">Project Structure:: <a class="header-anchor" href="#project-structure%3A%3A"></a></h2>
<figure><img src="/images/project-structure.PNG" alt="Project Structure"></figure>
<h2 id="factory-interface%3A%3A" tabindex="-1">Factory Interface:: <a class="header-anchor" href="#factory-interface%3A%3A"></a></h2>
<p><span>link</span> ShapeFactory.java</p>
<pre class="language-java"><code class="language-java"><span class="token keyword">package</span> <span class="token namespace">com<span class="token punctuation">.</span>spring<span class="token punctuation">.</span>factory</span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">com<span class="token punctuation">.</span>spring<span class="token punctuation">.</span>factory<span class="token punctuation">.</span>shape<span class="token punctuation">.</span></span><span class="token class-name">Shape</span></span><span class="token punctuation">;</span>

<span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ShapeFactory</span> <span class="token punctuation">{</span>

    <span class="token class-name">Shape</span> <span class="token function">getShape</span><span class="token punctuation">(</span><span class="token class-name">String</span> name<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token punctuation">}</span></code></pre>
<p>The ShapeFactory interface is the factory which will return the actual implementation of the Shape interface.</p>
<h2 id="shape-inteface%3A%3A" tabindex="-1">Shape Inteface:: <a class="header-anchor" href="#shape-inteface%3A%3A"></a></h2>
<p><span>link</span> Shape.java</p>
<pre class="language-java"><code class="language-java"><span class="token keyword">package</span> <span class="token namespace">com<span class="token punctuation">.</span>spring<span class="token punctuation">.</span>factory<span class="token punctuation">.</span>shape</span><span class="token punctuation">;</span>

<span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">Shape</span> <span class="token punctuation">{</span>

    <span class="token keyword">void</span> <span class="token function">draw</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token punctuation">}</span></code></pre>
<p>The Shape interface has only one method <code>draw()</code> this method is what the implementation classes will override and provide their own logic.</p>
<h2 id="shape-implementation%3A%3A" tabindex="-1">Shape Implementation:: <a class="header-anchor" href="#shape-implementation%3A%3A"></a></h2>
<p><span>link</span> Circle.java</p>
<pre class="language-java"><code class="language-java"><span class="token keyword">package</span> <span class="token namespace">com<span class="token punctuation">.</span>spring<span class="token punctuation">.</span>factory<span class="token punctuation">.</span>shape<span class="token punctuation">.</span>impl</span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>stereotype<span class="token punctuation">.</span></span><span class="token class-name">Component</span></span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">com<span class="token punctuation">.</span>spring<span class="token punctuation">.</span>factory<span class="token punctuation">.</span>shape<span class="token punctuation">.</span></span><span class="token class-name">Shape</span></span><span class="token punctuation">;</span>

<span class="token annotation punctuation">@Component</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Circle</span> <span class="token keyword">implements</span> <span class="token class-name">Shape</span><span class="token punctuation">{</span>

    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">draw</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"This is a cicle shape."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

<span class="token punctuation">}</span></code></pre>
<p><span>link</span> Square.java</p>
<pre class="language-java"><code class="language-java"><span class="token keyword">package</span> <span class="token namespace">com<span class="token punctuation">.</span>spring<span class="token punctuation">.</span>factory<span class="token punctuation">.</span>shape<span class="token punctuation">.</span>impl</span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>stereotype<span class="token punctuation">.</span></span><span class="token class-name">Component</span></span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">com<span class="token punctuation">.</span>spring<span class="token punctuation">.</span>factory<span class="token punctuation">.</span>shape<span class="token punctuation">.</span></span><span class="token class-name">Shape</span></span><span class="token punctuation">;</span>

<span class="token annotation punctuation">@Component</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Square</span> <span class="token keyword">implements</span> <span class="token class-name">Shape</span> <span class="token punctuation">{</span>

    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">draw</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"This is a box Shape."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

<span class="token punctuation">}</span></code></pre>
<p>The Circle and Square implementation are pretty simple, all they do is sysout the message to console. Now we need to configure the interface to act as a service locator.</p>
<h2 id="spring-configuration%3A%3A" tabindex="-1">Spring Configuration:: <a class="header-anchor" href="#spring-configuration%3A%3A"></a></h2>
<p><span>link</span> Config.java</p>
<pre class="language-java"><code class="language-java"><span class="token keyword">package</span> <span class="token namespace">com<span class="token punctuation">.</span>spring<span class="token punctuation">.</span>factory</span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>beans<span class="token punctuation">.</span>factory<span class="token punctuation">.</span>config<span class="token punctuation">.</span></span><span class="token class-name">ServiceLocatorFactoryBean</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>boot<span class="token punctuation">.</span>autoconfigure<span class="token punctuation">.</span></span><span class="token class-name">EnableAutoConfiguration</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>context<span class="token punctuation">.</span>annotation<span class="token punctuation">.</span></span><span class="token class-name">Bean</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>context<span class="token punctuation">.</span>annotation<span class="token punctuation">.</span></span><span class="token class-name">ComponentScan</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>context<span class="token punctuation">.</span>annotation<span class="token punctuation">.</span></span><span class="token class-name">Configuration</span></span><span class="token punctuation">;</span>

<span class="token annotation punctuation">@Configuration</span>
<span class="token annotation punctuation">@ComponentScan</span><span class="token punctuation">(</span><span class="token string">"com.spring.factory"</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Config</span> <span class="token punctuation">{</span>


    <span class="token annotation punctuation">@Bean</span>
    <span class="token keyword">public</span> <span class="token class-name">ServiceLocatorFactoryBean</span> <span class="token function">serviceLocatorBean</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token class-name">ServiceLocatorFactoryBean</span> bean <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ServiceLocatorFactoryBean</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        bean<span class="token punctuation">.</span><span class="token function">setServiceLocatorInterface</span><span class="token punctuation">(</span><span class="token class-name">ShapeFactory</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> bean<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>


<span class="token punctuation">}</span></code></pre>
<p>The <code>ServiceLocatorFactoryBean</code> does all the magic in this</p>
<h2 id="junit-test" tabindex="-1">Junit Test <a class="header-anchor" href="#junit-test"></a></h2>
<p><span>link</span> ShapeFactoryTest.java</p>
<pre class="language-java"><code class="language-java"><span class="token keyword">package</span> <span class="token namespace">com<span class="token punctuation">.</span>spring<span class="token punctuation">.</span>factory</span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token keyword">static</span> <span class="token import static"><span class="token namespace">org<span class="token punctuation">.</span>junit<span class="token punctuation">.</span></span><span class="token class-name">Assert</span><span class="token punctuation">.</span><span class="token operator">*</span></span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>junit<span class="token punctuation">.</span></span><span class="token class-name">Test</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>junit<span class="token punctuation">.</span>runner<span class="token punctuation">.</span></span><span class="token class-name">RunWith</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>beans<span class="token punctuation">.</span>factory<span class="token punctuation">.</span>annotation<span class="token punctuation">.</span></span><span class="token class-name">Autowired</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>boot<span class="token punctuation">.</span>test<span class="token punctuation">.</span>context<span class="token punctuation">.</span></span><span class="token class-name">SpringBootTest</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>test<span class="token punctuation">.</span>context<span class="token punctuation">.</span>junit4<span class="token punctuation">.</span></span><span class="token class-name">SpringRunner</span></span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">com<span class="token punctuation">.</span>spring<span class="token punctuation">.</span>factory<span class="token punctuation">.</span>shape<span class="token punctuation">.</span></span><span class="token class-name">Shape</span></span><span class="token punctuation">;</span>

<span class="token annotation punctuation">@RunWith</span><span class="token punctuation">(</span><span class="token class-name">SpringRunner</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@SpringBootTest</span><span class="token punctuation">(</span>classes<span class="token operator">=</span><span class="token punctuation">{</span><span class="token class-name">Config</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">}</span><span class="token punctuation">,</span>webEnvironment<span class="token operator">=</span><span class="token class-name">SpringBootTest<span class="token punctuation">.</span>WebEnvironment</span><span class="token punctuation">.</span><span class="token constant">NONE</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ShapeFactoryTest</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@Autowired</span>
    <span class="token keyword">private</span> <span class="token class-name">ShapeFactory</span> shapeFactory<span class="token punctuation">;</span>

    <span class="token annotation punctuation">@Test</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">testGetShape</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">Shape</span> circle <span class="token operator">=</span> shapeFactory<span class="token punctuation">.</span><span class="token function">getShape</span><span class="token punctuation">(</span><span class="token string">"circle"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">assertNotNull</span><span class="token punctuation">(</span>circle<span class="token punctuation">)</span><span class="token punctuation">;</span>
        circle<span class="token punctuation">.</span><span class="token function">draw</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">Shape</span> square <span class="token operator">=</span> shapeFactory<span class="token punctuation">.</span><span class="token function">getShape</span><span class="token punctuation">(</span><span class="token string">"square"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">assertNotNull</span><span class="token punctuation">(</span>square<span class="token punctuation">)</span><span class="token punctuation">;</span>
        square<span class="token punctuation">.</span><span class="token function">draw</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Test</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">testGetShapeForWrongShape</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token class-name">Shape</span> rectangle <span class="token operator">=</span> shapeFactory<span class="token punctuation">.</span><span class="token function">getShape</span><span class="token punctuation">(</span><span class="token string">"rectangle"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">assertNotNull</span><span class="token punctuation">(</span>rectangle<span class="token punctuation">)</span><span class="token punctuation">;</span>
        rectangle<span class="token punctuation">.</span><span class="token function">draw</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

<span class="token punctuation">}</span></code></pre>
<p>It's a normal Junit that I have written to test the functionality of our code. Its a normal Spring boot test class. The <code>RunWith(SpringRunner.class)</code> is needed for the Junit to run the unit test case as spring container. Next The annotation <code>SpringBootTest</code> is added with the attributes. I am injecting the ShapeFactory which you can use the same way in your own implementation. The method <code>testGetShape()</code> calls the getShape() method of the factory passing the attributes 'circle' &amp; 'square' and calling the <code>draw()</code> method on the retrieved instances.</p>
<h2 id="output" tabindex="-1">Output <a class="header-anchor" href="#output"></a></h2>
<p>As you can see in the output below, the right implementation instance is pulled from the ApplicationContext and the sysout statements are printed to the output.</p>
<figure><img src="/images/output_logs.PNG" alt="Ouput Logs"></figure>

                ]]>
            </content>
        </entry>
    
        
        <entry>
            <title>Unit Test logback Using JUnit</title>
            <link href="https://iamninad.com/posts/unit-test-logback-using-junit/"/>
            <updated>2017-06-18T00:00:00Z</updated>
            <id>https://iamninad.com/posts/unit-test-logback-using-junit/</id>
            <content type="html">
                <![CDATA[
                <p>There is not a single application I have ever seen without logging. Logging is such an essential part of every application, it provides the necessary details regarding what's going inside the application, how the flow is progressing &amp; in the case of exceptions details like the message &amp; stack trace.</p>
<p>I remember one time when I was working on one project and there was some problem with tivoli installer to install the application on my machine. To solve the issue I found out the log path of tivoli tool, I read the logs &amp; got to know where the problem was which I then solved it without requiring help from any team and it saved a lot of time not just mine but the different teams that were part of the problem resolution, it is so easy to find the issue when the logging is properly done.</p>
<p>Many times we find that in application design it's mentioned to log error logs in case when a certain condition is not met or some catastrophic event happens like if some record is not found in the database, network connection failed while calling a web service, or simply say while processing a file the layout of the file does not meet the required file format standard. In such a case we log the error to the log file and either stop the processing or continue to some recovery procedure or some different things that our business expects.</p>
<p>Sometimes we do have log monitoring tools in production environments that constantly monitor logs for any error and raise an incident when something goes wrong, so it becomes such an important task for a developer to check if the logs are properly formatted &amp; logged so that those get picked up by the monitoring tools, isn't it?</p>
<p>As a Java developer we many times use Log4j along with Slf4j. Sl4fj is the standard API for logging and there are various bindings available like log4j, logback etc. In this blog post, I will be discussing on slf4j + <a href="https://logback.qos.ch/documentation.html">logback</a> testing. For Log4j 2 I will be doing a separate blog.</p>
<h2 id="1.-maven-dependencies" tabindex="-1">1. Maven Dependencies <a class="header-anchor" href="#1.-maven-dependencies"></a></h2>
<pre class="language-xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">></span></span>org.mockito<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">></span></span>mockito-all<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">></span></span>1.9.5<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>scope</span><span class="token punctuation">></span></span>test<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>scope</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">></span></span>junit<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">></span></span>junit<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">></span></span>4.11<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>scope</span><span class="token punctuation">></span></span>test<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>scope</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">></span></span>org.slf4j<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">></span></span>slf4j-api<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">></span></span>1.7.25<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">></span></span>ch.qos.logback<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">></span></span>logback-core<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">></span></span>1.2.3<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">></span></span>ch.qos.logback<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">></span></span>logback-classic<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">></span></span>1.2.3<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">></span></span></code></pre>
<p>As we are working with Slf4j &amp; logback we have added those in our pom.xml. We need Mockito for mocking Logback Appender and capture logs on the mocked Appender. This is the minimum we required for the logging to work.</p>
<h2 id="2.-business-logic" tabindex="-1">2. Business Logic <a class="header-anchor" href="#2.-business-logic"></a></h2>
<pre class="language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">HeaderValidator</span> <span class="token punctuation">{</span>

    <span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token keyword">static</span> <span class="token class-name">Logger</span> log <span class="token operator">=</span> <span class="token class-name">LoggerFactory</span><span class="token punctuation">.</span><span class="token function">getLogger</span><span class="token punctuation">(</span><span class="token class-name">HeaderValidator</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token comment">/**
     * Validate Header Contents.
     *
     * @param data
     *            to validate
     * @return true if positive else false
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">validate</span><span class="token punctuation">(</span><span class="token class-name">String</span> data<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>data<span class="token punctuation">.</span><span class="token function">length</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token number">10</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            log<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span><span class="token string">"E2011 Invalid Header Content"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

<span class="token punctuation">}</span></code></pre>
<p>The above code is a simple example that validates the contents for valid length if the length is not 10 then the method will log an error message to the logger and will return false. This is a typical processing step in many file processing in spring batch framework. Now let's write a Unit Test case for the validation logic and check if the message is logged to the logger or not.</p>
<h2 id="3.-unit-test-case." tabindex="-1">3. Unit Test Case. <a class="header-anchor" href="#3.-unit-test-case."></a></h2>
<pre class="language-java"><code class="language-java"><span class="token keyword">import</span> <span class="token keyword">static</span> <span class="token import static"><span class="token namespace">org<span class="token punctuation">.</span>mockito<span class="token punctuation">.</span></span><span class="token class-name">Matchers</span><span class="token punctuation">.</span><span class="token static">argThat</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token keyword">static</span> <span class="token import static"><span class="token namespace">org<span class="token punctuation">.</span>mockito<span class="token punctuation">.</span></span><span class="token class-name">Mockito</span><span class="token punctuation">.</span><span class="token static">times</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token keyword">static</span> <span class="token import static"><span class="token namespace">org<span class="token punctuation">.</span>mockito<span class="token punctuation">.</span></span><span class="token class-name">Mockito</span><span class="token punctuation">.</span><span class="token static">verify</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token keyword">static</span> <span class="token import static"><span class="token namespace">org<span class="token punctuation">.</span>mockito<span class="token punctuation">.</span></span><span class="token class-name">Mockito</span><span class="token punctuation">.</span><span class="token static">when</span></span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>junit<span class="token punctuation">.</span></span><span class="token class-name">Before</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>junit<span class="token punctuation">.</span></span><span class="token class-name">Test</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>junit<span class="token punctuation">.</span>runner<span class="token punctuation">.</span></span><span class="token class-name">RunWith</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>mockito<span class="token punctuation">.</span></span><span class="token class-name">ArgumentMatcher</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>mockito<span class="token punctuation">.</span></span><span class="token class-name">Mock</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>mockito<span class="token punctuation">.</span>runners<span class="token punctuation">.</span></span><span class="token class-name">MockitoJUnitRunner</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>slf4j<span class="token punctuation">.</span></span><span class="token class-name">Logger</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>slf4j<span class="token punctuation">.</span></span><span class="token class-name">LoggerFactory</span></span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">ch<span class="token punctuation">.</span>qos<span class="token punctuation">.</span>logback<span class="token punctuation">.</span>classic<span class="token punctuation">.</span>spi<span class="token punctuation">.</span></span><span class="token class-name">ILoggingEvent</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">ch<span class="token punctuation">.</span>qos<span class="token punctuation">.</span>logback<span class="token punctuation">.</span>core<span class="token punctuation">.</span></span><span class="token class-name">Appender</span></span><span class="token punctuation">;</span>

<span class="token annotation punctuation">@RunWith</span><span class="token punctuation">(</span><span class="token class-name">MockitoJUnitRunner</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">HeaderValidatorLoggingTest</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@Mock</span>
    <span class="token class-name">Appender</span> appender<span class="token punctuation">;</span>

    <span class="token annotation punctuation">@Before</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setup</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name"><span class="token namespace">ch<span class="token punctuation">.</span>qos<span class="token punctuation">.</span>logback<span class="token punctuation">.</span>classic<span class="token punctuation">.</span></span>Logger</span> logger <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name"><span class="token namespace">ch<span class="token punctuation">.</span>qos<span class="token punctuation">.</span>logback<span class="token punctuation">.</span>classic<span class="token punctuation">.</span></span>Logger</span><span class="token punctuation">)</span> <span class="token class-name">LoggerFactory</span>
                <span class="token punctuation">.</span><span class="token function">getLogger</span><span class="token punctuation">(</span><span class="token class-name">Logger</span><span class="token punctuation">.</span><span class="token constant">ROOT_LOGGER_NAME</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">when</span><span class="token punctuation">(</span>appender<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">thenReturn</span><span class="token punctuation">(</span><span class="token string">"MOCK"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">when</span><span class="token punctuation">(</span>appender<span class="token punctuation">.</span><span class="token function">isStarted</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">thenReturn</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        logger<span class="token punctuation">.</span><span class="token function">addAppender</span><span class="token punctuation">(</span>appender<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Test</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">testValidate</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">HeaderValidator</span> validator <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HeaderValidator</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        validator<span class="token punctuation">.</span><span class="token function">validate</span><span class="token punctuation">(</span><span class="token string">"ABC"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token function">verify</span><span class="token punctuation">(</span>appender<span class="token punctuation">,</span> <span class="token function">times</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">doAppend</span><span class="token punctuation">(</span><span class="token function">argThat</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">ArgumentMatcher</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token annotation punctuation">@Override</span>
            <span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">matches</span><span class="token punctuation">(</span><span class="token class-name">Object</span> argument<span class="token punctuation">)</span> <span class="token punctuation">{</span>
                <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token class-name">ILoggingEvent</span><span class="token punctuation">)</span> argument<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getFormattedMessage</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span><span class="token string">"E2011 Invalid Header Content"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token punctuation">}</span>

<span class="token punctuation">}</span></code></pre>
<p>The setup method will add the mocked appender into the root logger. The <code>testValidate()</code> method calls the validate method of the Validator class passing an invalid value i.e. data with less than 10. In this case, an error log is generated by our HeaderValidator class. The verify method then checks whether the <code>doAppend()</code> method is called for once - <code>times(1)</code> and the argument to the method matches the expected message.</p>
<p>Another way to check for the message is by using <a href="https://static.javadoc.io/org.mockito/mockito-core/2.2.9/org/mockito/ArgumentCaptor.html">ArgumentCaptor</a> of Mockito</p>
<pre class="language-java"><code class="language-java"><span class="token keyword">package</span> <span class="token namespace">com<span class="token punctuation">.</span>logging<span class="token punctuation">.</span>sample</span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token keyword">static</span> <span class="token import static"><span class="token namespace">org<span class="token punctuation">.</span>mockito<span class="token punctuation">.</span></span><span class="token class-name">Mockito</span><span class="token punctuation">.</span><span class="token static">times</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token keyword">static</span> <span class="token import static"><span class="token namespace">org<span class="token punctuation">.</span>mockito<span class="token punctuation">.</span></span><span class="token class-name">Mockito</span><span class="token punctuation">.</span><span class="token static">verify</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token keyword">static</span> <span class="token import static"><span class="token namespace">org<span class="token punctuation">.</span>mockito<span class="token punctuation">.</span></span><span class="token class-name">Mockito</span><span class="token punctuation">.</span><span class="token static">when</span></span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span></span><span class="token class-name">List</span></span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>junit<span class="token punctuation">.</span></span><span class="token class-name">Assert</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>junit<span class="token punctuation">.</span></span><span class="token class-name">Before</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>junit<span class="token punctuation">.</span></span><span class="token class-name">Test</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>junit<span class="token punctuation">.</span>runner<span class="token punctuation">.</span></span><span class="token class-name">RunWith</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>mockito<span class="token punctuation">.</span></span><span class="token class-name">ArgumentCaptor</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>mockito<span class="token punctuation">.</span></span><span class="token class-name">Captor</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>mockito<span class="token punctuation">.</span></span><span class="token class-name">Mock</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>mockito<span class="token punctuation">.</span>runners<span class="token punctuation">.</span></span><span class="token class-name">MockitoJUnitRunner</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>slf4j<span class="token punctuation">.</span></span><span class="token class-name">Logger</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">org<span class="token punctuation">.</span>slf4j<span class="token punctuation">.</span></span><span class="token class-name">LoggerFactory</span></span><span class="token punctuation">;</span>

<span class="token keyword">import</span> <span class="token import"><span class="token namespace">ch<span class="token punctuation">.</span>qos<span class="token punctuation">.</span>logback<span class="token punctuation">.</span>classic<span class="token punctuation">.</span></span><span class="token class-name">Level</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">ch<span class="token punctuation">.</span>qos<span class="token punctuation">.</span>logback<span class="token punctuation">.</span>classic<span class="token punctuation">.</span>spi<span class="token punctuation">.</span></span><span class="token class-name">ILoggingEvent</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">ch<span class="token punctuation">.</span>qos<span class="token punctuation">.</span>logback<span class="token punctuation">.</span>core<span class="token punctuation">.</span></span><span class="token class-name">Appender</span></span><span class="token punctuation">;</span>

<span class="token annotation punctuation">@RunWith</span><span class="token punctuation">(</span><span class="token class-name">MockitoJUnitRunner</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">HeaderValidatorLoggingTest2</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@Mock</span>
    <span class="token class-name">Appender</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">ILoggingEvent</span><span class="token punctuation">></span></span> appender<span class="token punctuation">;</span>

    <span class="token annotation punctuation">@Captor</span>
    <span class="token class-name">ArgumentCaptor</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">ILoggingEvent</span><span class="token punctuation">></span></span> captor<span class="token punctuation">;</span>

    <span class="token annotation punctuation">@Before</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setup</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name"><span class="token namespace">ch<span class="token punctuation">.</span>qos<span class="token punctuation">.</span>logback<span class="token punctuation">.</span>classic<span class="token punctuation">.</span></span>Logger</span> logger <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name"><span class="token namespace">ch<span class="token punctuation">.</span>qos<span class="token punctuation">.</span>logback<span class="token punctuation">.</span>classic<span class="token punctuation">.</span></span>Logger</span><span class="token punctuation">)</span> <span class="token class-name">LoggerFactory</span>
                <span class="token punctuation">.</span><span class="token function">getLogger</span><span class="token punctuation">(</span><span class="token class-name">Logger</span><span class="token punctuation">.</span><span class="token constant">ROOT_LOGGER_NAME</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">when</span><span class="token punctuation">(</span>appender<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">thenReturn</span><span class="token punctuation">(</span><span class="token string">"MOCK"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">when</span><span class="token punctuation">(</span>appender<span class="token punctuation">.</span><span class="token function">isStarted</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">thenReturn</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        logger<span class="token punctuation">.</span><span class="token function">addAppender</span><span class="token punctuation">(</span>appender<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Test</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">testValidate</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">HeaderValidator</span> validator <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HeaderValidator</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        validator<span class="token punctuation">.</span><span class="token function">validate</span><span class="token punctuation">(</span><span class="token string">"ABC"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token function">verify</span><span class="token punctuation">(</span>appender<span class="token punctuation">,</span> <span class="token function">times</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">doAppend</span><span class="token punctuation">(</span>captor<span class="token punctuation">.</span><span class="token function">capture</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">ILoggingEvent</span><span class="token punctuation">></span></span> allValues <span class="token operator">=</span> captor<span class="token punctuation">.</span><span class="token function">getAllValues</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token class-name">ILoggingEvent</span> event<span class="token operator">:</span> allValues<span class="token punctuation">)</span><span class="token punctuation">{</span>
            <span class="token keyword">if</span><span class="token punctuation">(</span>event<span class="token punctuation">.</span><span class="token function">getLevel</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span><span class="token class-name">Level</span><span class="token punctuation">.</span><span class="token constant">ERROR</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
            <span class="token class-name">Assert</span><span class="token punctuation">.</span><span class="token function">assertEquals</span><span class="token punctuation">(</span><span class="token string">"E2011 Invalid Header Content"</span><span class="token punctuation">,</span> event<span class="token punctuation">.</span><span class="token function">getFormattedMessage</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

<span class="token punctuation">}</span></code></pre>
<p>The ArgumentCaptor is mocked to capture all the arugments of type ILogginEvent as our example is using logback-classic module the argument to the doAppend method is of ILoggingEvent type.</p>
<p>In the setup method we mock the appender methods like <code>getName()</code> &amp; <code>isStarted()</code> and we add the new mocked appender to the root Logger which is ch.qos.logback.classic.Logger.</p>
<p>The verify method in this example has a minor change as compared to the previous one that instead of passing the <code>argThat</code> method to the verify call we are passing the <code>captor.capture()</code> method, here captor will capture all the messages whenever the <code>doAppend()</code> method of the Logger class is called.</p>
<p>Other than the basic things that are done in the example you can do more than just checking the log message, there are various methods of <a href="https://logback.qos.ch/apidocs/ch/qos/logback/classic/spi/ILoggingEvent.html">ILoggingEvent</a> that you can test as per the requirement.</p>
<p>To learn more about logback logging framework please refer the <a href="https://logback.qos.ch/documentation.html">documentation site</a> of logback.</p>

                ]]>
            </content>
        </entry>
    
</feed>
