<?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>DEV Community: jbebar</title>
    <description>The latest articles on DEV Community by jbebar (@jbebar).</description>
    <link>https://dev.to/jbebar</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%2F293231%2Fc5bea09e-d588-4db6-82af-09e291f4e020.jpeg</url>
      <title>DEV Community: jbebar</title>
      <link>https://dev.to/jbebar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jbebar"/>
    <language>en</language>
    <item>
      <title>🍾 Nouvel article pour la nouvelle année 2022  (en français) sur Reactor RabbitMQ </title>
      <dc:creator>jbebar</dc:creator>
      <pubDate>Sun, 02 Jan 2022 17:34:18 +0000</pubDate>
      <link>https://dev.to/jbebar/nouvel-article-pour-la-nouvel-annee-2022-en-francais-sur-reactor-rabbitmq-39e6</link>
      <guid>https://dev.to/jbebar/nouvel-article-pour-la-nouvel-annee-2022-en-francais-sur-reactor-rabbitmq-39e6</guid>
      <description>&lt;p&gt;Bonjour à toutes et à tous, &lt;/p&gt;

&lt;p&gt;Je vous propose un nouvel article, cette fois en français, sur le blog tech de &lt;a href="https://www.lectra.com/fr"&gt;Lectra&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;C'est un article présentant la librairie Reactor et son application au travers de Reactor RabbitMQ :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tech-blog.lectra.com/article/791-presentation-de-reactor-rabbitmq"&gt;L'article&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bonne lecture et bonne année 2022 🍾 🎆!&lt;/p&gt;

&lt;p&gt;Julien :)&lt;/p&gt;

</description>
      <category>reactor</category>
      <category>rabbitmq</category>
      <category>jvm</category>
    </item>
    <item>
      <title>How to read messages reliably from RABBIT MQ broker?</title>
      <dc:creator>jbebar</dc:creator>
      <pubDate>Thu, 18 Mar 2021 22:14:31 +0000</pubDate>
      <link>https://dev.to/jbebar/how-to-read-messages-reliably-from-rabbit-mq-broker-4djh</link>
      <guid>https://dev.to/jbebar/how-to-read-messages-reliably-from-rabbit-mq-broker-4djh</guid>
      <description>&lt;h1&gt;
  
  
  What is Rabbit MQ 🐇?
&lt;/h1&gt;

&lt;p&gt;Rabbit MQ is a broker of messages implementing the AMQP protocal. It makes in possible for application to communicate in synchronous as well as in aynchronous way. Each application can subscribe and wait for new messages to arrive.&lt;/p&gt;

&lt;p&gt;AMQP involves three main actors: publishers, consumers and the broker.&lt;br&gt;
A publisher is an application that pushes messages to a Rabbit MQ broker.&lt;br&gt;
In the Rabbit MQ broker has two important elements: queues and exchanges binded by routing rules.&lt;br&gt;
When Rabbit MQ receives a message, it will check the routing information of the message and drop it the right queue according to the routing rules. The messages will stay in the queue until an application subscribes to the queue and reads the messages.&lt;/p&gt;

&lt;p&gt;In this article I will just talk about the consuming part based on a queue with existing messages and a consumer reading from it, so no need to understand the routing part :).&lt;/p&gt;

&lt;p&gt;There are two ways a consumer can read a message from a queue:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;auto acknowledgement mode (autoAck)&lt;/strong&gt;: the messages are automatically removed from the queue as soon as they are sent to the consumer, this is &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;manual Acknowledgement mode (manualAck)&lt;/strong&gt;: the consumer subscribes to a queue, and the messages are removed only when the consumer has sent back an acknowledgement (Ack) back to the broker.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will experiment these two ways of consuming messages.&lt;/p&gt;

&lt;h1&gt;
  
  
  A simple consumer example 🧪
&lt;/h1&gt;

&lt;p&gt;Let's see the code of a simple consumer made in Kotlin:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;org.jbebar&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.rabbitmq.client.ConnectionFactory&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.rabbitmq.client.Delivery&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.concurrent.CountDownLatch&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.concurrent.TimeUnit&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.concurrent.atomic.AtomicInteger&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlin.system.exitProcess&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;arguments&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"="&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;toMap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;autoAck&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"autoAck"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;toBoolean&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;qOS&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"qos"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;toInt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;processDurationSeconds&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"processDurationSeconds"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLong&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;countDownLatch&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CountDownLatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;processedMessageCount&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AtomicInteger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;factory&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ConnectionFactory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"localhost"&lt;/span&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;connection&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newConnection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;channel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createChannel&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;qOS&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;basicQos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;deliveryCallback&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Delivery&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;receivedMessage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processing : $receivedMessage"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;processDurationSeconds&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;autoAck&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Acknowledging message $receivedMessage"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basicAck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;envelope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deliveryTag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;processedMessageCount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;incrementAndGet&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;countDownLatch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;countDown&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processed : $receivedMessage"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basicConsume&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"demo-queue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;autoAck&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;deliveryCallback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="n"&gt;countDownLatch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;await&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;TimeUnit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SECONDS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processed ${processedMessageCount.get()} messages."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;exitProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The first part of this code retrieves the command line arguments that will parameter our consumer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;"autoAck": parameters the way our consumers reads messages, if true it is in auto ack mode, if false we are in manualAck.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"qOS": quantity of outstanding messages, quantity of messages that the broker allows to be unacknowledged for one consumer. Also called the quantity of inflight messages.&lt;br&gt;
This parameter is meaningful only if we are in manualAck mode&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"processDuration": This parameter sets the time or application takes to process each message. It is not related to rabbit mq configuration, but it is a way to simulate a lagging consumer or a fast one.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;autoAck&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"autoAck"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;toBoolean&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;numberOfMessagesToProcess&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"numberOfMessagesToProcess"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;toInt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;qOS&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"qos"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;toInt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;processDuration&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ofSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"processDurationSeconds"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;toLong&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt; &lt;span class="mi"&gt;0L&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;We create connection based on the Qos passed earlier:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;factory&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ConnectionFactory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"localhost"&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;connection&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newConnection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;channel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createChannel&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;qOS&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;basicQos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;In this deliveryCallback, we simulate a business process and pass it to the channel which will consume from a queue called "demo-queue".&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;

     &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;deliveryCallback&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Delivery&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;receivedMessage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processing : $receivedMessage"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;processDurationSeconds&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;autoAck&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Acknowledging message $receivedMessage"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basicAck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;envelope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deliveryTag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;processedMessageCount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;incrementAndGet&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;countDownLatch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;countDown&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processed : $receivedMessage"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;One important part of the code is the &lt;code&gt;CountDownLatch&lt;/code&gt;.&lt;br&gt;
It prevents our application from exiting before receiving straight after it launched as it blocks and exits only on two conditions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;countDownLatch.countDown() has been called 10 times, that means 10 messages have been processed.&lt;/li&gt;
&lt;li&gt;it passes a duration of 10 seconds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see the full code here :).&lt;/p&gt;

&lt;h1&gt;
  
  
  Let's try our consumer 🧪 !
&lt;/h1&gt;

&lt;p&gt;3 steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 Launch the rabbit Mq broker (check the admin interface on &lt;a href="http://localhost:15672/#/" rel="noopener noreferrer"&gt;http://localhost:15672/#/&lt;/a&gt; )&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

docker run -d --rm --hostname my-rabbit --name rabbit-broker -p 5672:5672 -p 15672:15672 rabbitmq:3-management


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

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;2 Build and launch the publisher to publish 10 messages:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

git clone https://github.com/jbebar/rabbit-mq-sample-sender.git
mvn clean package
java -jar target/amqp-sender-jar-with-dependencies.jar 10


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

&lt;/div&gt;

&lt;p&gt;You should see the queue in the admin interface of rabbit mq, if you go in the detail of the queue you will see this:&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%2F9dxx8oi46j0fsrqs356n.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9dxx8oi46j0fsrqs356n.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3 Build and launch the app: &lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

git clone https://github.com/jbebar/rabbit-mq-sample-receiver.git
mvn clean package
java -jar target/amqp-consumer-jar-with-dependencies.jar autoAck=true processDurationSeconds=0


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

&lt;/div&gt;

&lt;p&gt;Out put:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Processing : Message 1
Processed : Message 1
Processing : Message 2
Processed : Message 2
Processing : Message 3
Processed : Message 3
Processing : Message 4
Processed : Message 4
Processing : Message 5
Processed : Message 5
Processing : Message 6
Processed : Message 6
Processing : Message 7
Processed : Message 7
Processing : Message 8
Processed : Message 8
Processing : Message 9
Processed : Message 9
Processing : Message 10
Processed : Message 10
Processed 10 messages.


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

&lt;/div&gt;

&lt;p&gt;The process is fast enough to consume all messages before the 10 seconds time out.&lt;br&gt;
But if we try with a business process duration of 5 seconds:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

java -jar target/amqp-consumer-jar-with-dependencies.jar autoAck=true processDurationSeconds=5

Processing : Message_1
Processing : Message_2
Processing : Message_3
Processed 2 messages.


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

&lt;/div&gt;

&lt;p&gt;Our consumer has time to process only two messages before application exits and the queue is now empty meaning we lost 8 messages before they could be processed by our service.&lt;br&gt;
Our consumer had all its messages in memory and they vanished when it shutdown.&lt;/p&gt;

&lt;p&gt;In real life scenario this is dangerous: what if a payment service missed a payment because the service restarted or because our application simply crashes?&lt;/p&gt;

&lt;h1&gt;
  
  
  Using manual ack and Qos to the rescue
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Manual ack
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

java -jar target/amqp-consumer-jar-with-dependencies.jar autoAck=false processDurationSeconds=5

Processing : Message_1
Acknowledging message Message_1
Processed : Message_1
Processing : Message_2
Acknowledging message Message_2
Processing : Message_3
Processed 1 messages.


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

&lt;/div&gt;

&lt;p&gt;If we look at the history of our queue we have 9 messages remaining, no more losses.&lt;br&gt;
The broker behaviour with manualAck is to requeue the messages that have not been acknowledged after a certain period of time or because of a consumer disconnection.&lt;br&gt;
In our case, our consumer was delivered all the messages, that's why the number of messages ready drops suddenly, then we had time to process just one of them and send the ack.&lt;br&gt;
The message was then removed from the queue by the broker.&lt;br&gt;
Finally, the number of ready messages goes back up to 9 because rabbit mq sees the connexion is lost with the consumer as the consumer shutdown.&lt;br&gt;
You can see in the following graph, first the ready messages are dropping in favor of the unacknwoledged messages going up. Then when the consumer disconnects, the number of ready messages for other consumers goes back up.&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%2Fwwewg2ywh91svsqtars4.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwwewg2ywh91svsqtars4.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting the Qos
&lt;/h2&gt;

&lt;p&gt;The Qos limits the number of messages unacknowledged for a given consumer. This means it limits the number of messages buffered in the memory of the consumer and not yet processed.&lt;br&gt;
This a way to protect our consumer from crashing permanently when reading from a queue with many messages. Also, if the consumer is too long to ack the messages, they are not available for other consumers.&lt;/p&gt;

&lt;p&gt;The optimal value depends on the capacity of the consumer, the documentations advices a Qos from 100 to 300 :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.rabbitmq.com/confirms.html#channel-qos-prefetch-throughput" rel="noopener noreferrer"&gt;qos-value-documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To continue this article, an interesting experiment would be to upload a large amount of messages to the queue, reduce the memory available for a our consumer and see at which Qos it will explode 💥 🤓.&lt;/p&gt;

&lt;p&gt;Thanks for reading and feel free to comment or ask any question.&lt;/p&gt;

</description>
      <category>rabbitmq</category>
      <category>jvm</category>
      <category>kotlin</category>
      <category>messaging</category>
    </item>
    <item>
      <title>🔍 Kotlin: Let's look at inline classes bytecode 🔍</title>
      <dc:creator>jbebar</dc:creator>
      <pubDate>Sun, 17 Jan 2021 16:48:37 +0000</pubDate>
      <link>https://dev.to/jbebar/kotlin-let-s-look-at-inline-classes-bytecode-mdn</link>
      <guid>https://dev.to/jbebar/kotlin-let-s-look-at-inline-classes-bytecode-mdn</guid>
      <description>&lt;p&gt;Inline classes aim to reduce the overhead due to boxing of primitives. Inline classes are experimental since kotlin 1.3.&lt;br&gt;
You can use them without warning with the following configuration added to the kotlin-maven-plugin, for instance in maven:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;plugin&amp;gt;
        &amp;lt;groupId&amp;gt;org.jetbrains.kotlin&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;kotlin-maven-plugin&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;1.4.21&amp;lt;/version&amp;gt;
    ...
        &amp;lt;configuration&amp;gt;
            &amp;lt;args&amp;gt;
                &amp;lt;arg&amp;gt;-Xinline-classes&amp;lt;/arg&amp;gt;
            &amp;lt;/args&amp;gt;
        &amp;lt;/configuration&amp;gt;
    ...
    &amp;lt;/plugin&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The inline keyword means the compiler will replace wherever possible the wrapper class by its enclosing primitive.&lt;br&gt;
Let's have a look at this piece of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;age&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Age&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;weight&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Weight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;87&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello I am ${age.value}, my weight is ${weight.value} !"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Age&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;inline&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Weight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using intellij idea we can see the byte code generated by the main method by putting our cursor in the main function and searching the action &lt;code&gt;ByteCode viewer&lt;/code&gt;, we obtain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LINENUMBER 2 L0
    NEW Age
    DUP
    BIPUSH 18
    INVOKESPECIAL Age.&amp;lt;init&amp;gt; (I)V
    ASTORE 0
   L1
    LINENUMBER 3 L1
    BIPUSH 87
    INVOKESTATIC Weight.constructor-impl (I)I
    ISTORE 1
   L2
    LINENUMBER 4 L2
    NEW java/lang/StringBuilder
    DUP
    INVOKESPECIAL java/lang/StringBuilder.&amp;lt;init&amp;gt; ()V
    LDC "Hello I am "
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    ALOAD 0
    INVOKEVIRTUAL Age.getValue ()I
    INVOKEVIRTUAL java/lang/StringBuilder.append (I)Ljava/lang/StringBuilder;
    LDC ", my weight is "
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    ILOAD 1
    INVOKEVIRTUAL java/lang/StringBuilder.append (I)Ljava/lang/StringBuilder;
    LDC " !"
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
    ASTORE 2
    ICONST_0
    ISTORE 3
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    ALOAD 2
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
   L3
    LINENUMBER 5 L3
    RETURN
   L4
    LOCALVARIABLE weight I L2 L4 1
    LOCALVARIABLE age LAge; L1 L4 0
    MAXSTACK = 3
    MAXLOCALS = 4
  // access flags 0x1009
  public static synthetic main([Ljava/lang/String;)V
    INVOKESTATIC MainKt.main ()V
    RETURN
    MAXSTACK = 0
    MAXLOCALS = 1
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not very sexy 😱 right? Even without being a byte code expert let's decrypt the structure first:&lt;/p&gt;

&lt;p&gt;We can recognize the different parts of our &lt;code&gt;main&lt;/code&gt; function. From &lt;code&gt;LINENUMBER 2&lt;/code&gt; to &lt;code&gt;LINENUMBER 4&lt;/code&gt; we can see the declaration of age and weight variable.&lt;br&gt;
From &lt;code&gt;LINENUMBER 4&lt;/code&gt; to &lt;code&gt;LINENUMBER 5&lt;/code&gt; we can see the invocation of the &lt;code&gt;println&lt;/code&gt; function and the use of the &lt;code&gt;java/lang/StringBuilder&lt;/code&gt; which is how a template string from Kotlin in translated into bytecode.&lt;/p&gt;

&lt;p&gt;If we look again at the declaration of variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LINENUMBER 2 L0
    NEW Age
    DUP
    BIPUSH 18
    INVOKESPECIAL Age.&amp;lt;init&amp;gt; (I)V
    ASTORE 0
   L1
    LINENUMBER 3 L1
    BIPUSH 87
    INVOKESTATIC Weight.constructor-impl (I)I
    ISTORE 1
   L2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We notice the two variables declaration are similar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;first: a value is pushed on the stack, with the &lt;code&gt;BIPUSH&lt;/code&gt; 18 in the case of the age and 87 in the case of the weight command,&lt;/li&gt;
&lt;li&gt;second: the constructor is invoked with INVOKESTATIC for the inline class weight and INVOKESPECIAL for the class Age.&lt;/li&gt;
&lt;li&gt;third: a step of storage into the variable pool of the thread is done with &lt;code&gt;ISTORE 0&lt;/code&gt; for weight variable and &lt;code&gt;ASTORE 1&lt;/code&gt; for Age variable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's focus on what makes the difference now:&lt;/p&gt;

&lt;p&gt;We use &lt;code&gt;ASTORE&lt;/code&gt; in the case of the Age variable and &lt;code&gt;ISTORE&lt;/code&gt; in the case of the weight variable. If we go on this &lt;a href="https://en.wikipedia.org/wiki/Java_bytecode_instruction_listings"&gt;reference&lt;/a&gt;&lt;br&gt;
of bytecode instructions for java, we can see that commands prefixed by &lt;code&gt;A&lt;/code&gt; deals with references to object whereas &lt;code&gt;I&lt;/code&gt; deals with integer.&lt;br&gt;
So &lt;code&gt;ASTORE 0&lt;/code&gt; command designates the storage of an object reference at index &lt;code&gt;0&lt;/code&gt; of the local variables of the thread, that's how the reference to the Age object is stored.&lt;br&gt;
On the other hand, our Weight object doesn't exist in the byte code, it is directly stored at index 1 with the type integer, that is why we have &lt;code&gt;ISTORE 1&lt;/code&gt; instruction.&lt;/p&gt;

&lt;p&gt;The StringBuilder calls confirms this replacement of the reference with a primitive:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;LDC ", my weight is "&lt;br&gt;
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;&lt;br&gt;
ILOAD 1&lt;br&gt;
INVOKEVIRTUAL java/lang/StringBuilder.append (I)Ljava/lang/StringBuilder;&lt;br&gt;
LDC " !"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The call to the integer primitive value stored at index 1 is made with &lt;code&gt;ILOAD 1&lt;/code&gt;, &lt;strong&gt;so no object reference is used there either&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Another interesting thing to do is to replace the weight class with an integer, and see that the generated bytecode is very close from the one shown above. The main difference we will see are the static calls to the constructor of Weight &lt;code&gt;INVOKESTATIC Weight.constructor-impl (I)I&lt;/code&gt; will not be in the bytecode anymore.&lt;/p&gt;

&lt;p&gt;Conclusion&lt;/p&gt;

&lt;p&gt;With the &lt;code&gt;inline&lt;/code&gt; keyword, the kotlin compiler replaces in the bytecode the object reference with the primitive type being boxed.&lt;br&gt;
The point of this is to reduce memory consumption while keeping the advantage of value classes for readability and domain design.&lt;br&gt;
In some cases, though, the compiler doesn't replace the inline class with the primitive type, for instance if more than one property is boxed.&lt;br&gt;
Why looking through the bytecode? Just out of curiosity :), I could also have used the decompiler plugin from intellij to decompile the bytecode into java code to see that the inlined class is indeed replaced, I let you try ;)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sources:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For more details about inline classes: the kotlin documentation &lt;a href="https://kotlinlang.org/docs/reference/inline-classes.html"&gt;https://kotlinlang.org/docs/reference/inline-classes.html&lt;/a&gt;&lt;br&gt;
To deep dive more into how java byte code is written, this article is useful : &lt;a href="http://arhipov.blogspot.com/2011/01/java-bytecode-fundamentals.html"&gt;http://arhipov.blogspot.com/2011/01/java-bytecode-fundamentals.html&lt;/a&gt;&lt;br&gt;
Wikipedia reference of bytecode instructions : &lt;a href="https://en.wikipedia.org/wiki/Java_bytecode_instruction_listings"&gt;https://en.wikipedia.org/wiki/Java_bytecode_instruction_listings&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>jvm</category>
    </item>
    <item>
      <title>Native CLI with Picocli and GraalVM</title>
      <dc:creator>jbebar</dc:creator>
      <pubDate>Thu, 20 Aug 2020 18:06:47 +0000</pubDate>
      <link>https://dev.to/jbebar/native-cli-with-picocli-and-graalvm-566m</link>
      <guid>https://dev.to/jbebar/native-cli-with-picocli-and-graalvm-566m</guid>
      <description>&lt;h2&gt;
  
  
  Situation
&lt;/h2&gt;

&lt;p&gt;Let's imagine a CLI which takes as parameters option a client name and selects a random beer for this person, example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;./beer ---name "Jean-Michel"
Let's see what the barman found....
Hey Jean-Michel, you should try: Strong IPA 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CLI is written in Kotlin and uses Picocli to generate a standard help menu and to parse command line options. I will not detail Picocli in this post but the build process of an executable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Graal VM?
&lt;/h2&gt;

&lt;p&gt;If we run this CLI using a jar packaging and java command we have two downsides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;startup time of the JVM, users will not want to wait to order their beer.&lt;/li&gt;
&lt;li&gt;ask the user to install a JVM in the right version&lt;/li&gt;
&lt;li&gt;the command to launch the CLI will look like &lt;code&gt;java -jar name-of-the-cli.jar&lt;/code&gt; whereas we would expect a simple command like this &lt;code&gt;name-of-the-cli&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's where GraalVM can save us here, it can compile directly java byte code down to binaries for a particular machine (Linux in our example): &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No more JVM to install for our users&lt;/li&gt;
&lt;li&gt;Almost no startup time&lt;/li&gt;
&lt;li&gt;A simple command, as we just have to call the executable file from command line.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GraalVM is a polyglot VM to run many languages (Java, Kotlin among many others) in an optimized way. GraalVM can also be used as a JDK if you develop in Java/Kotlin to compile to Java bytecode.&lt;/p&gt;

&lt;p&gt;It comes with the &lt;code&gt;native-image&lt;/code&gt; tool can be installed on top of GraalVM to build natives executables from java bytecode.&lt;br&gt;
 For this purpose, GraalVM needs to anticipate any runtime reflections operations done, for instance, by the Picocli library. This special compilation is called &lt;em&gt;ahead of time&lt;/em&gt;. Every annotation used at runtime in our code will need to come with it's configuration file. These configurations files can be done manually, but usually frameworks provides tools to generate them. Fortunately, that's the case for Picocli.&lt;/p&gt;
&lt;h2&gt;
  
  
  Adapt our configuration to generate GraalVM configuration files:
&lt;/h2&gt;

&lt;p&gt;Our only source file is the following, we won't need to adapt it but let's keep it here for our understanding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;
&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;org.jbebar.beer.picocli&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;picocli.CommandLine&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;picocli.CommandLine.Command&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;picocli.CommandLine.Option&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.concurrent.Callable&lt;/span&gt;


&lt;span class="nd"&gt;@Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"beer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;mixinStandardHelpOptions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"beer 0.0.1"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Chooses a random beer for you."&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BeerCallable&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Callable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;names&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"-n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"--name"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Your name."&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"John Doe"&lt;/span&gt;

    &lt;span class="nd"&gt;@Throws&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;beers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Black IPA Beer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Light Blond"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Strong IPA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Red Beer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"White Beer"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Let's see what the barman found...."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hey $name, you should try: ${beers.shuffled().first()} !"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;companion&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;@JvmStatic&lt;/span&gt;
        &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;exitCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CommandLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BeerCallable&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exitCode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our initial build.gradle looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;
&lt;span class="nf"&gt;plugins&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;kotlin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"jvm"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="s"&gt;"1.3.72"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"org.jbebar"&lt;/span&gt;
&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1.0-SNAPSHOT"&lt;/span&gt;

&lt;span class="nf"&gt;repositories&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;mavenCentral&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;kotlin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"stdlib-jdk8"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"info.picocli:picocli:4.5.0"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;tasks&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;compileKotlin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;kotlinOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;jvmTarget&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1.8"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;compileTestKotlin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;kotlinOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;jvmTarget&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1.8"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To use the configuration files generators for picocli library we need to add these lines to our build.gradle.kts :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;plugins { kotlin("kapt") version "1.3.72" }&lt;/code&gt; : this will enable annotation processing for kotlin.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dependencies { kapt("info.picocli:picocli-codegen:4.5.0") }&lt;/code&gt; : Using annotation processing from kotlin during java compilation, it will scan for picocli annotations and generate the corresponding configuration files for graalVM.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kapt { arguments { arg("project", "${project.group}/${project.name}")  } }&lt;/code&gt; : this will give the jar a unique name and prevent shading from other jars in the case of a uber jar.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After adapting our build.gradle and running &lt;code&gt;gradle clean build&lt;/code&gt; we can see the following structure in the generated jar:&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%2Fi%2Ftl1ca0xnf0whdssfj3fm.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftl1ca0xnf0whdssfj3fm.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we have a look closer, only one configuration file is filled, the reflect-config.json. It refers to the runtimes annotations used by our code and picocli dependency: the field annotated in their class are detailed in the config.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"org.jbebar.beer.picocli.BeerCallable"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allDeclaredConstructors"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allPublicConstructors"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allDeclaredMethods"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allPublicMethods"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"fields"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"picocli.CommandLine$AutoHelpMixin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allDeclaredConstructors"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allPublicConstructors"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allDeclaredMethods"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allPublicMethods"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"fields"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"helpRequested"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"versionRequested"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we check the rentention policy of these annotations, we see that &lt;code&gt;@Option&lt;/code&gt; has &lt;code&gt;RUNTIME&lt;/code&gt; retention on our field &lt;code&gt;name&lt;/code&gt; of class BeerCallable.&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%2Fi%2F1oye3kma0kaeffomln2s.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1oye3kma0kaeffomln2s.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Same for the AutoHelpMixin class.&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%2Fi%2Fiel3tc7d8hrqn61pab9r.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fiel3tc7d8hrqn61pab9r.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Install GraalVM
&lt;/h2&gt;

&lt;p&gt;To install GraalVM, I let you refer to the documentation for your platform. GraalVM needs C/C++ compilation tools to build the native-images.&lt;/p&gt;

&lt;p&gt;After installing GraalVM you can run:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gu install native-image&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Compile to native code
&lt;/h2&gt;

&lt;p&gt;Before compiling to native code, it is good to check our application is running using &lt;code&gt;java&lt;/code&gt; command, gathering all the dependencies and the source jar in the same folder and use the &lt;code&gt;--classpath&lt;/code&gt; or &lt;code&gt;-cp&lt;/code&gt; option like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;
java -cp annotations-13.0.jar:kotlin-stdlib-1.3.72.jar:kotlin-stdlib-common-1.3.72.jar:kotlin-stdlib-jdk7-1.3.72.jar:kotlin-stdlib-jdk8-1.3.72.jar:picocli-4.5.0.jar:beer-picocli-1.0-SNAPSHOT.jar org.jbebar.beer.picocli.BeerCallable
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Be careful about putting the source file containing the Main class as last dependency in the list passed to &lt;code&gt;-cp&lt;/code&gt;. The only argument to pass on top of the option is the name of the class containing the main method.&lt;/p&gt;

&lt;p&gt;This will give the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Let's see what the barman found....
Hey John Doe, you should try: Red Beer !
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, to compile we can stay in the same folder containing our dependencies and CLI jar and run:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;native-image -cp annotations-13.0.jar:kotlin-stdlib-1.3.72.jar:kotlin-stdlib-common-1.3.72.jar:kotlin-stdlib-jdk7-1.3.72.jar:kotlin-stdlib-jdk8-1.3.72.jar:picocli-4.5.0.jar:beer-picocli-1.0-SNAPSHOT.jar -H:Name=beer  org.jbebar.beer.picocli.BeerCallable&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;where &lt;code&gt;-H:Name=beer&lt;/code&gt; is the name of the generated executable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Execution
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;
./beer -h
&lt;/span&gt;&lt;span class="gp"&gt;Usage: beer [-hV] [-n=&amp;lt;name&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="go"&gt;Chooses a random beer for you.
  -h, --help          Show this help message and exit.
&lt;/span&gt;&lt;span class="gp"&gt;  -n, --name=&amp;lt;name&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;Your name.
&lt;span class="go"&gt;  -V, --version       Print version information and exit.
./beer -n "Jean-Michel"
Let's see what the barman found....
Hey Jean-Michel, you should try: Strong IPA !
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also compare the execution times :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;
time java -cp annotations-13.0.jar:kotlin-stdlib-1.3.72.jar:kotlin-stdlib-common-1.3.72.jar:kotlin-stdlib-jdk7-1.3.72.jar:kotlin-stdlib-jdk8-1.3.72.jar:picocli-4.5.0.jar:beer-picocli-1.0-SNAPSHOT.jar org.jbebar.beer.picocli.BeerCallable
Let's see what the barman found....
Hey John Doe, you should try: Black IPA Beer !

real    0m0.316s
user    0m0.473s
sys 0m0.060s
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With graal VM we can see that the real time is nearly 8 times faster.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;
time ./beer
Let's see what the barman found....
Hey John Doe, you should try: Black IPA Beer !

real    0m0.044s
user    0m0.006s
sys 0m0.005s

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

&lt;/div&gt;



&lt;p&gt;Don't take this "8 times" for granted, of course, it will depend on the type of program you run. But this gives a good idea of how fast it is. The user will not see the difference between this or any system command run from terminal, and that's kind of magical.&lt;/p&gt;

&lt;p&gt;To see even more the difference, it could be interesting to run this with programs manipulating larger sets of data.&lt;br&gt;
    I hope now our client will not wait to know which beer to drink and take it right out of the fridge.&lt;br&gt;
    More seriously, would you now try GraalVM and Picocli combination? Or do you have any other way of writing your CLI apps? Feel free to comment :) and see you soon.&lt;/p&gt;

</description>
      <category>todayilearned</category>
      <category>kotlin</category>
      <category>picocli</category>
      <category>graalvm</category>
    </item>
    <item>
      <title>Efficiently manage dependencies thanks to maven  BOM</title>
      <dc:creator>jbebar</dc:creator>
      <pubDate>Sun, 02 Aug 2020 20:13:44 +0000</pubDate>
      <link>https://dev.to/jbebar/effectively-manage-dependencies-thanks-to-maven-bom-449f</link>
      <guid>https://dev.to/jbebar/effectively-manage-dependencies-thanks-to-maven-bom-449f</guid>
      <description>&lt;h2&gt;
  
  
  Situation
&lt;/h2&gt;

&lt;p&gt;Imagine having several applications using maven for dependency management. You have to make sure all these applications remain consistent in their dependency versions.&lt;br&gt;
For instance, if these applications use a shared database server like mongo db, you want to be sure they are all up to date with mongo db API or they will break.&lt;br&gt;
Updating all these applications can take a lot of your time, also you may have many other dependencies to maintain: security, plugins etc...&lt;/p&gt;
&lt;h2&gt;
  
  
  Solution: Use a Maven BOM
&lt;/h2&gt;

&lt;p&gt;BOM stands for Bills Of Materials. A BOM gather multiple versions of dependencies and can be imported in your application POM.&lt;br&gt;
BOM dependencies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; will override all the transient dependencies versions of your project.&lt;/li&gt;
&lt;li&gt;will be overriden by direct dependencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's take an example with dependencies of one of our CLI app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;project&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://maven.apache.org/POM/4.0.0"&lt;/span&gt;
         &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;
         &lt;span class="na"&gt;xsi:schemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;modelVersion&amp;gt;&lt;/span&gt;4.0.0&lt;span class="nt"&gt;&amp;lt;/modelVersion&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.jbebar&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;my-cli-app&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.0-SNAPSHOT&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;dependencies&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.mongodb&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;mongodb-driver-sync&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;4.1.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;info.picocli&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;picocli&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;4.4.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dependencies&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/project&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's create a BOM to manage these two dependencies, and also spring jdbc as it is used in other of our CLI apps and we need to share this BOM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;project&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://maven.apache.org/POM/4.0.0"&lt;/span&gt;
         &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;
         &lt;span class="na"&gt;xsi:schemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;modelVersion&amp;gt;&lt;/span&gt;4.0.0&lt;span class="nt"&gt;&amp;lt;/modelVersion&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.jbebar&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;sample-BOM&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.0.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;dependencyManagement&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;dependencies&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.mongodb&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;mongodb-driver-sync&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;4.1.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;info.picocli&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;picocli&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;4.4.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-jdbc&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;5.2.8.RELEASE&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dependencies&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dependencyManagement&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/project&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's now add this BOM in dependency management section of our app with the type &lt;code&gt;pom&lt;/code&gt; and the scope &lt;code&gt;import&lt;/code&gt; and remove the versions of our dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;project&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://maven.apache.org/POM/4.0.0"&lt;/span&gt;
         &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;
         &lt;span class="na"&gt;xsi:schemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;modelVersion&amp;gt;&lt;/span&gt;4.0.0&lt;span class="nt"&gt;&amp;lt;/modelVersion&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.jbebar&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;my-cli-app&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.0-SNAPSHOT&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;dependencyManagement&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;dependencies&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.jbebar&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;sample-BOM&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.0.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;type&amp;gt;&lt;/span&gt;pom&lt;span class="nt"&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;import&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dependencies&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dependencyManagement&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;dependencies&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.mongodb&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;mongodb-driver-sync&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;info.picocli&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;picocli&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dependencies&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/project&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We notice our versions are the same has in the maven BOM we created after running &lt;code&gt;mvn dependency:tree&lt;/code&gt; or checking in our IDE. The BOM settles the dependencies versions for us.&lt;/p&gt;

&lt;p&gt;Also, if we change the version of Picocli to 3.3.0 in the project POM, maven will prioritize the direct dependencies versions and not take the BOM version of picocli into account, we can run a &lt;code&gt;mvn dependency:tree&lt;/code&gt; to see this:&lt;/p&gt;

&lt;p&gt;[INFO] org.jbebar:my-cli-app:jar:1.0-SNAPSHOT&lt;br&gt;
[INFO] +- org.mongodb:mongodb-driver-sync:jar:4.1.0:compile&lt;br&gt;
[INFO] |  +- org.mongodb:bson:jar:4.1.0:compile&lt;br&gt;
[INFO] |  - org.mongodb:mongodb-driver-core:jar:4.1.0:compile&lt;br&gt;
[INFO] - info.picocli:picocli:jar:3.3.0:compile&lt;/p&gt;

&lt;p&gt;Moreover, the jdbc dependency is not present. That is why it is common to see BOM's with dozens of dependencies. The spring boot BOM is a good example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example of commonly used BOM: the spring boot BOM
&lt;/h2&gt;

&lt;p&gt;To see the list of dependencies managed by spring boot you can have a look &lt;a href="https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-dependency-versions.html"&gt;here&lt;/a&gt; It manages spring dependencies as well as other dependencies (ex: kotlin coroutines, mongo db driver).&lt;/p&gt;

&lt;p&gt;Another good reason to use this BOM is to avoid inconsistency between spring dependencies.&lt;br&gt;
As said at the beginning, the BOM overrides transient dependencies.&lt;br&gt;
Two springs dependencies can be present as two transient dependencies, for instance it can come from dependency A and dependency E:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A -&amp;gt; B -&amp;gt; C:2.0.0&lt;/p&gt;

&lt;p&gt;E -&amp;gt; C:1.0.1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In that case, C will be in version C:1.0.1. This makes it hard to know which dependency is chosen.&lt;br&gt;
Above all it can lead to unexpected issues, what happens if dependency C is shared and needs to be at least in 2.0.0 for a given dependency but is set at 1.0.0 by a more direct dependency?&lt;br&gt;
Using the spring boot BOM prevents from these issues between spring dependencies as it overrides all the transient versions.&lt;/p&gt;

&lt;p&gt;Thanks for reading, any suggestions are welcome :).&lt;/p&gt;

</description>
      <category>todayilearned</category>
      <category>spring</category>
    </item>
  </channel>
</rss>
