<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Shriharsh</title>
    <description>The latest articles on Forem by Shriharsh (@shriharshmishra).</description>
    <link>https://forem.com/shriharshmishra</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F11888%2FDSC00031.JPG</url>
      <title>Forem: Shriharsh</title>
      <link>https://forem.com/shriharshmishra</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/shriharshmishra"/>
    <language>en</language>
    <item>
      <title>Today I Learned: A simple trick to slim down a Docker image</title>
      <dc:creator>Shriharsh</dc:creator>
      <pubDate>Thu, 08 Feb 2018 12:38:45 +0000</pubDate>
      <link>https://forem.com/shriharshmishra/today-i-learned-a-simple-trick-to-slim-down-a-docker-image-ed4</link>
      <guid>https://forem.com/shriharshmishra/today-i-learned-a-simple-trick-to-slim-down-a-docker-image-ed4</guid>
      <description>&lt;p&gt;You may want to reduce the space used by your image. If you are building on top of an  Ubuntu image and during the build, you are invoking &lt;code&gt;apt-get update&lt;/code&gt; (you would be for sure if you are installing latest versions!) then you can delete some files downloaded by apt-get that won't be required later. The following Dockerfile snippet shows a way how it should be done. Notice that RUN instruction is doing 3 things, update the package cache, installing ant, and deleting the cache. This is done in such a ways so that Docker does all of this in a single layer of the image. If these steps are split in different RUN instructions then your Docker host and/or registry will use more space.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
FROM jenkins/jenkins:lts

&lt;span class="c"&gt;#Change user to root and install ant version 1.9.9-1 (available in Ubuntu packages)&lt;/span&gt;
USER root

&lt;span class="c"&gt;#&lt;/span&gt;
RUN apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nv"&gt;ant&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.9.9-1 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="c"&gt;# remove the cached files.&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my case, it saved about 138M of space. However, YMMV.&lt;/p&gt;

&lt;p&gt;By the way, &lt;strong&gt;what are you deleting&lt;/strong&gt;? You are only deleting the information about latest packages and versions available for download using &lt;code&gt;apt-get install&lt;/code&gt; or &lt;code&gt;apt-get upgrade&lt;/code&gt;. &lt;code&gt;apt-get&lt;/code&gt; caches this information later use. It is highly likely that you wouldn't need this information when you are running the containers based on this image. Installing software while running the container would be a big NO!.&lt;/p&gt;

&lt;p&gt;Similar, cache files would exist in other Linux distributions as well.&lt;/p&gt;

&lt;p&gt;I hope this helps you slim down your ubuntu images.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>ubuntu</category>
      <category>tips</category>
      <category>todayilearned</category>
    </item>
    <item>
      <title>"Behind the Corporate Proxy" </title>
      <dc:creator>Shriharsh</dc:creator>
      <pubDate>Wed, 17 Jan 2018 21:59:55 +0000</pubDate>
      <link>https://forem.com/shriharshmishra/behind-the-corporate-proxy-2jd8</link>
      <guid>https://forem.com/shriharshmishra/behind-the-corporate-proxy-2jd8</guid>
      <description>&lt;p&gt;Over the years, I have struggled to get past the corporate proxy, i.e. access to the internet was blocked because proxy details weren't set up properly. Usually, most software documentation wouldn't provide these details handy and one has search thru documentation. These are useless battles a developer has to fight in order to win the war. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fepfxlkjgh7qvajx3p1ae.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fepfxlkjgh7qvajx3p1ae.jpg" alt="Corporate Proxy!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I wish I could do what Liam Neeson does! But I have been able to win some of my battles and have accumulated some ammunition for a short post which might come handy to many in a similar situation. Here I list down some ways to set up proxy details in the following scenarios: &lt;/p&gt;

&lt;h3&gt;
  
  
  Running Vagrant behind the proxy
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Set up the proxy in your guest OS
&lt;/h4&gt;

&lt;p&gt;This depends on the guest OS. I use Ubuntu, so I find updating &lt;code&gt;/etc/environment&lt;/code&gt; file with proxy details as an easy option.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;cat&lt;/span&gt; /etc/environment 
&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"&lt;/span&gt;
    &lt;span class="nv"&gt;HTTP_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://proxy_host:port
    &lt;span class="nv"&gt;HTTPS_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://proxy_host:port
    &lt;span class="nv"&gt;FTP_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nv"&gt;NO_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;localhost,127.0.0.1
    &lt;span class="nv"&gt;http_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://proxy_host:port
    &lt;span class="nv"&gt;https_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://proxy_host:port
    &lt;span class="nv"&gt;ftp_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nv"&gt;no_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;localhost,127.0.0.1

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Use vagrant-proxyconf plugin
&lt;/h4&gt;

&lt;p&gt;With this plugin, you can setup the proxy details right into the Vagrantfile. To install the plugin run the following command on your shell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; vagrant plugin &lt;span class="nb"&gt;install &lt;/span&gt;vagrant-proxyconf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are not able to download the plugin behind the corporate proxy (duh!), then you can download the gem file from &lt;a href="https://rubygems.org/gems/vagrant-proxyconf/versions/1.5.2" rel="noopener noreferrer"&gt;Ruby Gems&lt;/a&gt; site and use the following command to install the plugin.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; vagrant plugin &lt;span class="nb"&gt;install&lt;/span&gt; /path/to/my-plugin.gem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and add following to the Vagrantfile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Vagrant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;Vagrant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has_plugin?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"vagrant-proxyconf"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;http&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"http://&amp;lt;your-proxy-host&amp;gt;:&amp;lt;port&amp;gt;/"&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;https&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"http://&amp;lt;your-proxy-host&amp;gt;:&amp;lt;port&amp;gt;/"&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;no_proxy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"localhost,127.0.0.1"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="c1"&gt;# ... other stuff&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you should be able to access the internet from your vagrant guest.&lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Running Docker behind proxy
&lt;/h3&gt;

&lt;p&gt;When you are working on docker behind the proxy, it becomes important that you ensure proxy settings are passed and are available at different stages -  for example,  image creation, container execution, and running services. There are different command options for either of these scenarios.&lt;/p&gt;

&lt;h4&gt;
  
  
  Setting proxy while building an image
&lt;/h4&gt;

&lt;p&gt;You might want to download some software while building your image so that every container has it pre-installed. While you can hardcode the proxy details as environment variables in the Dockerfile, it isn't the recommended way of doing so. It hampers the portability of the image and unnecessarily gives the container created by the image access to the internet. The better option would be to pass the proxy information while building the image using &lt;code&gt;build-arg&lt;/code&gt; option as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;http_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;yourproxyserverhost&amp;gt;:&amp;lt;port&amp;gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;https_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;yourproxyserverhost&amp;gt;:&amp;lt;port&amp;gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; docker build &lt;span class="nt"&gt;--build-arg&lt;/span&gt; &lt;span class="nv"&gt;http_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$http_proxy&lt;/span&gt; &lt;span class="nt"&gt;--build-arg&lt;/span&gt; &lt;span class="nv"&gt;https_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$https_proxy&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; &amp;lt;your-image&amp;gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;build-arg&lt;/code&gt; option would allow you to pass a value to an environment variable defined in your Dockerfile using &lt;code&gt;ARG&lt;/code&gt; instruction. However, it is a bit easier to pass proxy details. For proxy details, Dockerfile allows you to skip mentioning the proxy environment variable via &lt;code&gt;ARG&lt;/code&gt; instruction in the Dockerfile.&lt;sup id="fnref2"&gt;2&lt;/sup&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Setting up proxy when running the container
&lt;/h4&gt;

&lt;p&gt;Again as mentioned above, it isn't advisable to setup proxy details in the image or to enter each new container to setup proxy details. Docker provides a better way to do so using the &lt;code&gt;-e&lt;/code&gt; or &lt;code&gt;--env&lt;/code&gt; options with the run command. This option can be used to pass the proxy setting as environment variables to the container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; docker container run &lt;span class="nt"&gt;-e&lt;/span&gt; http_proxy nginx &lt;span class="c"&gt;#..........................(1)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; docker container run &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;https_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;proxyhost:port nginx &lt;span class="c"&gt;#.........(2)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the difference between two commands above. If &lt;code&gt;http_proxy&lt;/code&gt; is already defined on the docker host, we can directly pass its value to the container by just passing the name of the variable to &lt;code&gt;-e&lt;/code&gt; options as shown on line#(1) above. If you want to provide an alternate value you can pass name=value pair as shown in line#(2) above. Finally, you can also set up all the proxy variables in a file and use the &lt;code&gt;--env-file&lt;/code&gt; option to pass all of them at once.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;cat &lt;/span&gt;all-proxy-vars.txt 

&lt;span class="nv"&gt;http_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://proxy_host:port
&lt;span class="nv"&gt;https_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://proxy_host:port
&lt;span class="nv"&gt;ftp_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;no_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;localhost,127.0.0.1

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; docker container run &lt;span class="nt"&gt;--env-file&lt;/span&gt; ./all-proxy-vars.txt nginx 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Environment options on the Docker CLI commands offers quick way tweak and test an image. &lt;sup id="fnref3"&gt;3&lt;/sup&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Setup proxy for Docker Compose - The easiest thing.
&lt;/h4&gt;

&lt;p&gt;While the steps described above will come handy when you are experimenting with your images and containers. Once you have finalized your container and image details, the best approach would be to create a compose file for your service which would build the image. Docker compose allows you to pass the environment details easily using the &lt;code&gt;args&lt;/code&gt; instruction. You just need to mention the name of the proxy environment variables as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2.3'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
    &lt;span class="na"&gt;ngnix-service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-nginx-image&lt;/span&gt;
        &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
            &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
            &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# Environment variables available at build-time&lt;/span&gt;
                &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;http_proxy&lt;/span&gt;
                &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;https_proxy&lt;/span&gt;
                &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;no_proxy&lt;/span&gt;
        &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# Environment variables available at container run-time&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;https_proxy&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;http_proxy&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;no_proxy&lt;/span&gt;
        &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
&lt;span class="s"&gt;.........&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As noted in the code snippet, environment variables defined as &lt;code&gt;build &amp;gt; arg&lt;/code&gt; level are only available when image is being built. Whereas, &lt;code&gt;environment&lt;/code&gt; level list of environment variable is available at container run-time.&lt;/p&gt;

&lt;p&gt;So these are the corporate proxy battles that I have fought and won somehow. A long time back, I had a hard time getting thru an NTLM-based proxy. But a cool tool called CNTLM saved my day. However, I don't have the scenario or the steps handy to add to this article. &lt;/p&gt;

&lt;p&gt;One thing is for sure, once you have resolved such issues, you can quickly identify a similar issue with a new software. I would add to this article when I fight and win more such battles. I hope you this post helps you save some time. &lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Detailed instruction on Vagrant-proxyconf plugin can be found here. &lt;a href="http://tmatilai.github.io/vagrant-proxyconf/" rel="noopener noreferrer"&gt;http://tmatilai.github.io/vagrant-proxyconf/&lt;/a&gt;  ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;The official Docker documentation explains how to use &lt;code&gt;build-args&lt;/code&gt; &lt;a href="https://docs.docker.com/engine/reference/commandline/build/#set-build-time-variables-build-arg" rel="noopener noreferrer"&gt;https://docs.docker.com/engine/reference/commandline/build/#set-build-time-variables-build-arg&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;Environment options on the Docker CLI commands. &lt;a href="https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e-env-env-file" rel="noopener noreferrer"&gt;https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e-env-env-file&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>productivity</category>
      <category>httpproxy</category>
      <category>vagrant</category>
      <category>docker</category>
    </item>
    <item>
      <title>My Shell Workflow: Executing a command in lots of directories. </title>
      <dc:creator>Shriharsh</dc:creator>
      <pubDate>Wed, 03 Jan 2018 14:52:07 +0000</pubDate>
      <link>https://forem.com/shriharshmishra/my-shell-workflow-executing-a-command-in-lots-of-directories--3m9c</link>
      <guid>https://forem.com/shriharshmishra/my-shell-workflow-executing-a-command-in-lots-of-directories--3m9c</guid>
      <description>&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;p&gt;You want to run a shell command in many directories. For example, in my case, I wanted to execute a shell command in lots of directories(approx. 200)  to clean up build files. &lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;Writing a for-loop and running it on the shell did the trick for me.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for d in ./*/ ; do (cd "$d" &amp;amp;&amp;amp; mvn clean); done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Explanation
&lt;/h2&gt;

&lt;p&gt;The above for-loop would run &lt;code&gt;cd "$d" &amp;amp;&amp;amp; mvn clean&lt;/code&gt; in each item of the directory list defined by the path &lt;code&gt;./*/&lt;/code&gt;. &lt;code&gt;$d&lt;/code&gt; holds the directory name. You can be creative in defining the list of directories using a complex glob as well. &lt;/p&gt;

&lt;p&gt;I hope this helps you as well.&lt;/p&gt;

</description>
      <category>shell</category>
      <category>bash</category>
      <category>zsh</category>
      <category>productivity</category>
    </item>
    <item>
      <title> "My Shell Workflow: Using bash history"</title>
      <dc:creator>Shriharsh</dc:creator>
      <pubDate>Wed, 22 Nov 2017 16:39:24 +0000</pubDate>
      <link>https://forem.com/shriharshmishra/my-shell-workflow-using-bash-history-8k7</link>
      <guid>https://forem.com/shriharshmishra/my-shell-workflow-using-bash-history-8k7</guid>
      <description>&lt;h3&gt;
  
  
  Working on the shell with your hands tied :|
&lt;/h3&gt;

&lt;p&gt;While I try to use my vagrant box for work as much as possible, there are times when I have to connect to server machines over ssh and not have my favorite z-shell. It was getting irritatingly boring to repeat the same set of command every time. One option is to create my own aliases but I will have to do so everytime I login. Our sysadmin has (strangely) ensured that everyone sudo's to a common user to do any editing work. &lt;/p&gt;

&lt;h3&gt;
  
  
  Finding my way out :)
&lt;/h3&gt;

&lt;p&gt;So I use the following set of commands to ensure that I am not getting bogged down by the process. &lt;/p&gt;

&lt;p&gt;Suppose I want to search a command that I have previously used. I type  &lt;code&gt;history | grep &amp;lt;command-snippet&amp;gt;&lt;/code&gt; which gives me a numbered list when I have used the command earlier. Then I use the number to run the same command - &lt;code&gt;!&amp;lt;number&amp;gt;&lt;/code&gt; again. See below -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;history&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;vim
2795  vim scratch-pad.txt
2820  vim .git/config
2822  vim .git/config
2845  &lt;span class="nb"&gt;sudo &lt;/span&gt;vim /etc/hosts
2847  &lt;span class="nb"&gt;sudo &lt;/span&gt;vim /etc/hosts

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;2820
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; vim .git/config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This might still be tedius. So the other option is to search history without calling &lt;code&gt;history&lt;/code&gt; command. &lt;/p&gt;

&lt;h3&gt;
  
  
  The Savior &lt;code&gt;Ctrl+R&lt;/code&gt; :D
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;On the bash terminal, press &lt;code&gt;Ctrl+R&lt;/code&gt; to open reverse search dialog. &lt;/li&gt;
&lt;li&gt;Type the snippet of the command you would have executed earlier. &lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;Ctrl+O&lt;/code&gt; to execute the command. or Press &lt;code&gt;Ctrl+Space&lt;/code&gt; to print the command for editing before executing.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;reverse-i-search&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;install&lt;/span&gt;&lt;span class="s1"&gt;': sudo apt-get install ant #After pressing Ctrl+O
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
.... 


(reverse-i-search)`zsh'&lt;/span&gt;: &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;zsh &lt;span class="c"&gt;#After pressing Ctrl+Space&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;zsh  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A nifty side-effect of using &lt;code&gt;Ctrl+R&lt;/code&gt; on the bash prompt is that once the chosen command is completed, the next command from history is printed on the prompt for us to use if needed. Most of the time, I am restarting my server and tailing the logs. So using this option automatically returns the next command (&lt;code&gt;tail -f&lt;/code&gt;) after I execute the restart command. &lt;/p&gt;

&lt;p&gt;I hope this helps you as well. &lt;/p&gt;

</description>
      <category>shell</category>
      <category>bash</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Today I Learned: To use custom ClientHttpRequestFactory with MockRestServiceServer </title>
      <dc:creator>Shriharsh</dc:creator>
      <pubDate>Mon, 13 Nov 2017 15:07:11 +0000</pubDate>
      <link>https://forem.com/shriharshmishra/today-i-learned-to-use-custom-clienthttprequestfactory-with-mockrestserviceserver--3bo</link>
      <guid>https://forem.com/shriharshmishra/today-i-learned-to-use-custom-clienthttprequestfactory-with-mockrestserviceserver--3bo</guid>
      <description>&lt;p&gt;Despite having some reservations about using Spring RestTemplate for writing JAX-RS client (&lt;a href="https://dev.to/shriharshmishra/comparing-springs-resttemplate-and-jerseys-client-apis-350"&gt;see here&lt;/a&gt;), I chose to use Spring RestTemplate to implement a JAX RS client as I liked that I could write test cases by easily mocking the REST service I was consuming. Spring provides a very nice utility to mock REST service end-point: &lt;a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/test/web/client/MockRestServiceServer.html"&gt;MockRestServiceServer&lt;/a&gt;. However, I ran into an pesky issue. &lt;/p&gt;

&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;p&gt;I developed my code along with the test cases using the above nice utility by Spring framework. Next step was to log all incoming and outgoing traffic. I was able to implement the feature by registering a custom &lt;a href="https://stackoverflow.com/a/33009822/7007521"&gt;LoggingInterceptor&lt;/a&gt; along with the &lt;a href="https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/http/client/BufferingClientHttpRequestFactory.html"&gt;BufferingClientHttpRequestFactory&lt;/a&gt;. The logging worked fine but my test cases started to fail. Although I ensured that I use BufferingClientHttpRequestFactory so that the response from the server can be read twice - once for logging and next by the application code, the test code would fail on the second read. &lt;/p&gt;

&lt;h2&gt;
  
  
  Diagnosis
&lt;/h2&gt;

&lt;p&gt;I found that the MockRestServiceServer would override the BufferingClientHttpRequestFactory setup on the RestTemplate instance passed to it while creating the server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Override&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;MockRestServiceServer&lt;/span&gt; &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RequestExpectationManager&lt;/span&gt; &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;MockRestServiceServer&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MockRestServiceServer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="nc"&gt;MockClientHttpRequestFactory&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;MockClientHttpRequestFactory&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;restTemplate&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;restTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setRequestFactory&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asyncRestTemplate&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asyncRestTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setAsyncRequestFactory&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;On scouring further, I found that the there is a hack to work around this &lt;a href="https://github.com/spring-projects/spring-boot/issues/6686"&gt;issue&lt;/a&gt;. Once the server is created, read the &lt;code&gt;requestFactory&lt;/code&gt; instance created by the &lt;code&gt;MockRestServiceServer&lt;/code&gt; using ReflectionTestUtils on RestTemplate instance and wrap it up with BufferingClientHttpRequestFactory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Before&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setUp&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;mockServer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MockRestServiceServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createServer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;restTemplate&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ClientHttpRequestFactory&lt;/span&gt; &lt;span class="n"&gt;requestFactory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
        &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ClientHttpRequestFactory&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;ReflectionTestUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getField&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;restTemplate&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"requestFactory"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;restTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setRequestFactory&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BufferingClientHttpRequestFactory&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requestFactory&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I hope this helps you as well. &lt;/p&gt;

</description>
      <category>spring</category>
      <category>todayilearned</category>
      <category>httprequestfactory</category>
      <category>buffering</category>
    </item>
    <item>
      <title>Today I Learned: About Docker Volume</title>
      <dc:creator>Shriharsh</dc:creator>
      <pubDate>Fri, 27 Oct 2017 11:51:03 +0000</pubDate>
      <link>https://forem.com/shriharshmishra/today-i-learned--about-docker-volume-9pn</link>
      <guid>https://forem.com/shriharshmishra/today-i-learned--about-docker-volume-9pn</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F85wf0mwwix360i3xjckw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F85wf0mwwix360i3xjckw.png" title="Docker Volume" alt="Docker Volume"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In my experiements on running Jenkins on Docker, I wondered how the volumne worked when I provided &lt;code&gt;-v&lt;/code&gt; to the run command. &lt;/p&gt;

&lt;p&gt;I found a great article which succintly explains a lot about the Docker Volume - which will be handy for any docker beginer. &lt;/p&gt;

&lt;p&gt;Original article is &lt;a href="http://container-solutions.com/understanding-volumes-docker/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My summary goes below: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker Volume is the way to &lt;em&gt;persist data between container restarts&lt;/em&gt; and &lt;em&gt;share it between containers&lt;/em&gt;. &lt;/li&gt;
&lt;li&gt;A volume is stored on the host file system. Usually within obscure directories inside &lt;code&gt;/var/lib/docker&lt;/code&gt;. However, a specific directory on host system can also be mounted as volume in a container. &lt;/li&gt;
&lt;li&gt;Volumes can be managed using &lt;code&gt;docker volume&lt;/code&gt; and its sub commands. &lt;/li&gt;
&lt;li&gt;Docker won't delete volume unless specifically instructed to do so. This can result in stale data on the host system. So tidying up once in a while might come handy. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Important Caveat&lt;/strong&gt; - Don't try to modify the content of the volume in the Dockerfile (via RUN) as each build step creates a &lt;em&gt;new&lt;/em&gt; volume and your changes will be discarded. If you want to change the volume content, do so using the &lt;em&gt;ENTRYPOINT&lt;/em&gt; command in the Dockerfile. Have a look at this &lt;a href="https://stackoverflow.com/a/34843099/7007521" rel="noopener noreferrer"&gt;link&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;If you are looking for a thorough overview of different approaches to manage application data, including the use of &lt;strong&gt;Volume, Bind mounts, tmpfs mounts&lt;/strong&gt;, read this &lt;a href="https://docs.docker.com/engine/admin/volumes/" rel="noopener noreferrer"&gt;longer article&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Image Credit: &lt;a href="https://docs.docker.com/engine/admin/volumes/images/types-of-mounts-volume.png" rel="noopener noreferrer"&gt;https://docs.docker.com/engine/admin/volumes/images/types-of-mounts-volume.png&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>volume</category>
      <category>todayilearned</category>
    </item>
    <item>
      <title>Today I Learned: Some VIM tricks</title>
      <dc:creator>Shriharsh</dc:creator>
      <pubDate>Wed, 18 Oct 2017 08:41:24 +0000</pubDate>
      <link>https://forem.com/shriharshmishra/today-i-learned-some-vim-tricks-5d3</link>
      <guid>https://forem.com/shriharshmishra/today-i-learned-some-vim-tricks-5d3</guid>
      <description>&lt;h1&gt;
  
  
  VIM Trick 1 - Create new file using NERDTree plugin
&lt;/h1&gt;

&lt;p&gt;Many VIM users depend on NERDTree plugin to browse directory but rare use it to create a new file on without leaving Vim (at least I was one such Vim user). &lt;/p&gt;

&lt;p&gt;I found nice blog entry which told me how to do so - &lt;a href="https://sookocheff.com/post/vim/creating-a-new-file-or-directoryin-vim-using-nerdtree/"&gt;Link here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To summarize - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open NERDTree panel&lt;/li&gt;
&lt;li&gt;Navigate to the directory where you want to create new file or directory. &lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;m&lt;/code&gt; - which opens up NERDTree Filesystem Menu. &lt;/li&gt;
&lt;li&gt;Type &lt;code&gt;a&lt;/code&gt; to create the child node and type the name of file or directory. For directory append &lt;code&gt;/&lt;/code&gt; at the end. &lt;/li&gt;
&lt;li&gt;That's it. &lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  VIM Trick 2 - Create new file using VIM built-in feature.
&lt;/h1&gt;

&lt;p&gt;While I was experimenting on the steps above I made a silly mistake. I didn't open the newly created file before typing my experiment with NERDTree. So I typed my content in an un-named buffer. To wiggle out, I decided to rely on VIM help. This is what I did - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Type &lt;code&gt;:h save&lt;/code&gt; - this opened up the help window with VIM&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;saveas&lt;/code&gt; command in VIM helps us same the current buffer into a file. &lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;!&lt;/code&gt; option to save to an existing file. &lt;/li&gt;
&lt;li&gt;I will let the reader experiment with this with their own hands-on exercise. &lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>vim</category>
      <category>nerdtree</category>
      <category>file</category>
      <category>todayilearned</category>
    </item>
    <item>
      <title>Comparing Spring’s RestTemplate and Jersey’s Client APIs</title>
      <dc:creator>Shriharsh</dc:creator>
      <pubDate>Tue, 17 Oct 2017 14:34:37 +0000</pubDate>
      <link>https://forem.com/shriharshmishra/comparing-springs-resttemplate-and-jerseys-client-apis-350</link>
      <guid>https://forem.com/shriharshmishra/comparing-springs-resttemplate-and-jerseys-client-apis-350</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F6l86g9pdpwyr7n0ct4v2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F6l86g9pdpwyr7n0ct4v2.png" title="Comapring Spring's RestTemplate and Jersey's Client APIs" alt="Comapring Spring's RestTemplate and Jersey's Client APIs"&gt;&lt;/a&gt;&lt;br&gt;
Recently I had an opportunity to use two different REST libraries to write client side code for consuming REST web services. The libraries were Spring RestTemplate (spring-web, 4.3.10.RELEASE)  and Jersey Client (jersey-client, 1.18). Although the latter is an older version, it was much easier to use it. My goals were very simple and  specifically the following: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Invoke different HTTP methods on the service&lt;/li&gt;
&lt;li&gt;Setup Basic Authentication on the client code. &lt;/li&gt;
&lt;li&gt;Log request and response. &lt;/li&gt;
&lt;li&gt;Handle the HTTP error responses. &lt;/li&gt;
&lt;li&gt;Write test cases which mock the server. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Spring provides &lt;a href="https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html" rel="noopener noreferrer"&gt;RestTemplate API&lt;/a&gt; to invoke various HTTP methods on a REST Web Service. Although there are methods dedicated to most HTTP method such as &lt;a href="https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html#getForObject-java.lang.String-java.lang.Class-java.lang.Object...-" rel="noopener noreferrer"&gt;getForObject&lt;/a&gt; GET, &lt;a href="https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html#postForObject-java.lang.String-java.lang.Object-java.lang.Class-java.lang.Object...-" rel="noopener noreferrer"&gt;postForObject&lt;/a&gt;POST, PUT etc., the methods don't provide full control over what is to be sent out. So you have to rely on the generic methods such as &lt;a href="https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html#exchange-java.lang.String-org.springframework.http.HttpMethod-org.springframework.http.HttpEntity-java.lang.Class-java.lang.Object...-" rel="noopener noreferrer"&gt;exchange&lt;/a&gt; or &lt;a href="https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html#execute-java.lang.String-org.springframework.http.HttpMethod-org.springframework.web.client.RequestCallback-org.springframework.web.client.ResponseExtractor-java.lang.Object...-" rel="noopener noreferrer"&gt;execute&lt;/a&gt;.When using these method one has to supply parameter such as HttpEntity even when you don't want to send any and this ambiguously named class is used to setup HTTP headers on the request (some examples on this &lt;a href="https://stackoverflow.com/questions/11579621/spring-resttemplate-postforobject-with-header-webservice-cant-find-my-header-p" rel="noopener noreferrer"&gt;thread&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The API provides ways to build the URI dynamically with simple templating for path param and HTTP parameters. However, the approach is clunky as there are two approaches to achieve data binding on the URI template. One is using a map which would be used to replace the key in the URI template. Second is by passing var args to methods in the same sequence as the placeholders appear on the URI templates. Both the approaches require that HTTP parameter name is mentioned on the URI template. Either of the approaches can lead to a messy code where it can be difficult to track on which parameter which value is being set.You can see the examples on this &lt;a href=""&gt;thread&lt;/a&gt;. On the other hand, Jersey client provides a &lt;a href="https://en.wikipedia.org/wiki/Fluent_interface" rel="noopener noreferrer"&gt;fluent API&lt;/a&gt; to implement the client code. The API is very intuitive and doesn't require any specific order in which one must provide data for the URI template.The query and path parameters can be easily supplied using methods on the &lt;a href="http://javadox.com/com.sun.jersey/jersey-bundle/1.18/com/sun/jersey/api/client/WebResource.html" rel="noopener noreferrer"&gt;WebResource&lt;/a&gt; API. Some more examples on this &lt;a href="http://buraktas.com/jersey-client-example-with-json-support/" rel="noopener noreferrer"&gt;page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Setting basic authentication using either of the libraries wasn't difficult. Spring requires us to setup an interceptor on the RestTemplate instance whereas Jersey requires adding filter class. Both the libraries provide built-in implementations which can be extended if required. Spring provides &lt;a href="https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/http/client/support/BasicAuthorizationInterceptor.html" rel="noopener noreferrer"&gt;BasicAuthorizationInterceptor&lt;/a&gt; and Jersey provides &lt;a href="https://github.com/jersey/jersey-1.x/blob/master/jersey-client/src/main/java/com/sun/jersey/api/client/filter/HTTPBasicAuthFilter.java" rel="noopener noreferrer"&gt;HTTPBasicAuthFilter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Logging request and response is an important feature for investigation. Like basic authentication, this feature is to be implemented using an interceptor in Spring and a filter in Jersey. Jersey gives a very handy implementation of such as filter called &lt;a href="https://github.com/jersey/jersey-1.x/blob/master/jersey-server/src/main/java/com/sun/jersey/api/container/filter/LoggingFilter.java" rel="noopener noreferrer"&gt;LoggingFilter&lt;/a&gt; which can help in logging all kinds of incoming and outgoing traffic. Spring requires you to implement your own interceptor. But that's not enough, you also need to configure the RestTemplate instance to use &lt;a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/client/BufferingClientHttpRequestFactory.html" rel="noopener noreferrer"&gt;BufferingClientRequestFactory&lt;/a&gt; which helps in reading the response from input stream twice - once for logging and another for application code. Sample implementation can be seen &lt;a href="https://stackoverflow.com/a/22620168" rel="noopener noreferrer"&gt;here&lt;/a&gt;. The sample implementation of LoggingFilter in Jersey has this aspect built-in. So Jersey gives us a headstart.&lt;/p&gt;

&lt;p&gt;Spring RestTemplate approach towards handling HTTP status codes which are not in the 2xx range isn't user-friendly in my opinion. Spring will throw an exception - &lt;a href="https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/HttpClientErrorException.html" rel="noopener noreferrer"&gt;HttpClientErrorException&lt;/a&gt; or &lt;a href="https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/HttpServerErrorException.html" rel="noopener noreferrer"&gt;HttpServerErrorException&lt;/a&gt; if it doesn't see successful response. This forces developer to implement a try-catch block to handle the error or register an error handler with RestTemplate. Whereas Jersey's approach is to hand over the &lt;a href="http://javadox.com/com.sun.jersey/jersey-client/1.18.3/com/sun/jersey/api/client/ClientResponse.html" rel="noopener noreferrer"&gt;ClientResponse&lt;/a&gt; instance and it is up to the developer to decide how to treat the response i.e. more freedom.&lt;/p&gt;

&lt;p&gt;Finally, let's get into writing test cases. The first thing that is crucial here is to mock server response. Spring is the clear winner here. It provides a very handy set of APIs to mock a REST web service response which allows us to focus on testing the business logic. Have a look at &lt;a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/test/web/client/MockRestServiceServer.html" rel="noopener noreferrer"&gt;MockRestServiceServer&lt;/a&gt;.With Jersey, you have to rely on mocking APIs like Mockito to mock Jersey client APIs which is very distracting and boring.   &lt;/p&gt;

&lt;p&gt;Considering how easy I found using Jersey to write code that consumes a REST web service, I would say Jersey win in comparison.Spring framework is open enough give us libraries which lets us use Jersey along with Spring. So even if you are working on a Spring based application you can safely use Jersey for your JAX-RS needs. &lt;/p&gt;

&lt;p&gt;Disclaimer: I am writing this blog to share my experience in a fairly simple use case. So YMMV.  Spring lovers may disagree with me. There are other libraries which such as RESTEasy which I haven't explored. You may share your experience/opinion so that I can learn from your experience too.  &lt;/p&gt;

</description>
      <category>spring</category>
      <category>resttemplate</category>
      <category>jersey</category>
      <category>jaxrsclient</category>
    </item>
  </channel>
</rss>
