<?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: Ivelin Yanev</title>
    <description>The latest articles on DEV Community by Ivelin Yanev (@yanev).</description>
    <link>https://dev.to/yanev</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%2F1971354%2F972c3c91-9972-4b75-b8fd-11a809d11359.jpg</url>
      <title>DEV Community: Ivelin Yanev</title>
      <link>https://dev.to/yanev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yanev"/>
    <language>en</language>
    <item>
      <title>The state of AI code reviews: An 18-month retrospective</title>
      <dc:creator>Ivelin Yanev</dc:creator>
      <pubDate>Wed, 31 Dec 2025 16:09:20 +0000</pubDate>
      <link>https://dev.to/yanev/the-state-of-ai-code-reviews-an-18-month-retrospective-1j1c</link>
      <guid>https://dev.to/yanev/the-state-of-ai-code-reviews-an-18-month-retrospective-1j1c</guid>
      <description>&lt;p&gt;It has been almost a year and a half since our company started using AI intensively in our everyday work. We've tested various tools- such as Windsurf, GitHub Copilot, Cursor, Claude, and LibreChat- and I can now confidently comment on how AI models affect software engineering as a discipline.&lt;/p&gt;

&lt;p&gt;In this article, I'll try to present my objective opinion on using AI for code reviews.&lt;/p&gt;

&lt;p&gt;First, let me clarify- I'm not an AI specialist. I don't have the deep technical knowledge to discuss models or their architecture, as so many people on the Internet tend to do these days. It feels like everyone thinks they're an expert on LLMs, which obviously isn't realistic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Review: A Critical Step in Software Development
&lt;/h2&gt;

&lt;p&gt;Code review is a key stage in every software project, and neglecting it often leads to unpredictable and critical problems later on. Since the very beginning of the software era, reviewing written code- regardless of programming language- has been seen as a required step before the code is used in production.&lt;/p&gt;

&lt;p&gt;Let's look at an example from history- the Apollo spacecraft software.&lt;/p&gt;

&lt;p&gt;Hundreds of engineers worked on it during those years, creating the software without which a safe lunar landing and return would have been impossible. The Apollo software, called &lt;a href="https://www.ibiblio.org/apollo/Luminary.html#gsc.tab=0" rel="noopener noreferrer"&gt;Luminary&lt;/a&gt;, contained over 145,000 lines of code. Every single file included comments (see on &lt;a href="https://github.com/chrislgarry/Apollo-11/tree/master/Luminary099" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;), and the entire codebase went through multiple review and approval iterations.&lt;/p&gt;

&lt;p&gt;Today, we have automated tools, compilers, and sophisticated software practices. But back then, every line was written, reviewed, and optimized by hand. Even in the early 1960s, processes like defining requirements, design, coding, testing, and maintenance were strictly followed.&lt;/p&gt;

&lt;p&gt;Margaret Hamilton, who led the lab developing the Apollo flight software, once said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What became apparent with Apollo- though it is not how it worked- is that it is better to define your system up front to minimize errors, rather than producing a bunch of code that then has to be corrected with patches on patches. It's a message that seems to have gone unheeded- in this respect, software today is still built the way it was 50 years ago.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By focusing on finding and fixing errors early, the system was stable enough to handle unexpected CPU overloads just seconds before the lunar landing. No software errors were reported during any of the manned Apollo missions- a remarkable testament to human precision.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fv0e4k25oxmhqiescg7gm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fv0e4k25oxmhqiescg7gm.png" alt="Margaret Hamilton" width="556" height="719"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Code Review Pyramid
&lt;/h2&gt;

&lt;p&gt;A well-known concept in software engineering is the Code Review Pyramid, which illustrates the relative importance of different review aspects: Code Style, Documentation, Testing, Implementation, and Functionality &amp;amp; Design.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fj4quw5kk1xi66j9ualnu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fj4quw5kk1xi66j9ualnu.png" alt="The Code Review Pyramid" width="800" height="634"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From my own experience, I've always applied this approach when reviewing others code. But the first review always happens with my own code- by me.&lt;/p&gt;

&lt;p&gt;Before you push your changes or ask an AI to check them, revisit the pyramid yourself.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Don't just check for syntax.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Imagine you are reading it for the first time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What is confusing? What is implicit?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I find it helpful to take a break between writing and reviewing my code. Many developers submit changes at the end of the day, but that's when fatigue leads to overlooked errors. Waiting until morning and reviewing the changes with fresh eyes dramatically improves the result.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Does AI Excel?
&lt;/h2&gt;

&lt;p&gt;Several parts of the review process can be automated- checking code style, syntax errors, test coverage, code optimization, and error detection.&lt;/p&gt;

&lt;p&gt;AI models are exceptionally precise in finding mistakes and identifying poor coding practices. Their consistency is remarkable: they spot the same problems every single time. When it comes to adherence to conventions or catching minor flaws, AI is laser-focused.&lt;/p&gt;

&lt;p&gt;Moreover, AI effortlessly scales- it can review dozens of pull requests per day without fatigue, something almost impossible for a human reviewer.&lt;/p&gt;

&lt;p&gt;Here are a few clear advantages of using AI in code review:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Immediate feedback&lt;/strong&gt; – In traditional reviews, responses might take hours or even days, leaving developers waiting. With AI, the feedback comes instantly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No cognitive fatigue&lt;/strong&gt; – Reviewing hundreds of lines of someone else's code can be mentally draining. AI never tires.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Productivity scaling&lt;/strong&gt; – In large teams, human reviewers spend significant time on reviews, impacting productivity. For AI, team size doesn't matter- it performs equally fast and effectively regardless.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A &lt;a href="https://static1.smartbear.co/support/media/resources/cc/book/code-review-cisco-case-study.pdf" rel="noopener noreferrer"&gt;Cisco&lt;/a&gt; study found that reviewing more than 400 lines of code at once reduces one's ability to find bugs, with most defects discovered in the first 200 lines. This insight shaped industry practices- but AI doesn't suffer from this limitation. It can handle large reviews without performance degradation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fi0m49ne1qcnmbn7s1dvb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fi0m49ne1qcnmbn7s1dvb.png" alt="LOC under Review" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Human Mind: The Unbeatable Factor
&lt;/h2&gt;

&lt;p&gt;While AI performs flawlessly on the tasks mentioned above- and I rely on it heavily. It still lacks something fundamental- &lt;strong&gt;understanding&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;As experts have pointed out, current AI systems are, in many ways, quite limited. We're fooled into thinking they're intelligent because they handle language so well. But they don't understand the physical world. They lack persistent memory, true reasoning, and long-term planning- all crucial aspects of genuine intelligence.&lt;/p&gt;

&lt;p&gt;Machine learning generally operates under three paradigms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Supervised learning&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the classical approach. The model is trained using a dataset of examples that have both input and the correct output (labels). For instance, if you train a system to recognize objects, you might show it an image of a table and label it "table". The model then produces its own output and receives feedback: if it's wrong, its internal parameters are adjusted. Repeating this process millions of times helps the system form strong associations between inputs and correct predictions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reinforcement learning&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This technique more closely resembles certain aspects of human learning. Instead of being told the exact right answer, the AI acts, observes the consequences, and receives a reward or penalty. It adjusts its future actions to maximize the long‑term reward. Think of how you learned to ride a bike- through trial, error, and correction. However, this paradigm has limitations. It’s inefficient and effective only in clearly defined environments (like playing chess, Go, or poker) where success metrics are known and unambiguous. In complex, real‑world settings without clear feedback, reinforcement learning becomes impractical.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Self-supervised learning&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the foundation of the most recent revolution in AI, including large language models such as ChatGPT. Here, the system learns from unlabeled data by creating its own predictive tasks- for example, trying to predict missing words in a sentence. By training on vast quantities of text, the model builds internal representations of patterns and relationships between words and concepts. This approach allows AI to gain an impressive ability to generate coherent and context‑aware language, but it still does not give the model genuine understanding or reasoning ability- it is pattern recognition, not comprehension.&lt;/p&gt;

&lt;p&gt;Even with all this sophistication, AI remains fundamentally limited by its training data and objectives. It does not understand things as humans do; it merely models statistical relationships.&lt;/p&gt;

&lt;p&gt;Software, by definition, is a tool that must operate according to human needs and actions- sometimes even playing a role in life-critical systems. This gap is where human consciousness and intuition remain irreplaceable.&lt;/p&gt;

&lt;p&gt;Final Thoughts&lt;/p&gt;

&lt;p&gt;I'll end with a visual that perfectly captures how the development landscape has shifted in the past two years.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fbqd8lclqc8et5wmpoi30.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fbqd8lclqc8et5wmpoi30.png" alt=" " width="800" height="261"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Writing code itself has never truly been the problem. The real challenge has always been delivering error-free and dependable software.&lt;/p&gt;

&lt;p&gt;The lesson is clear: AI is a powerful ally—especially for automating repetitive parts of the review process—but the human element remains the final safeguard of wisdom, empathy, and understanding that no algorithm can yet fully emulate.&lt;/p&gt;

</description>
      <category>codereview</category>
      <category>ai</category>
      <category>programming</category>
    </item>
    <item>
      <title>Java 25: Top 3 Features That Redefine Performance, Startup, and Efficiency</title>
      <dc:creator>Ivelin Yanev</dc:creator>
      <pubDate>Fri, 31 Oct 2025 19:25:44 +0000</pubDate>
      <link>https://dev.to/yanev/java-25-top-3-features-that-redefine-performance-startup-and-efficiency-2il9</link>
      <guid>https://dev.to/yanev/java-25-top-3-features-that-redefine-performance-startup-and-efficiency-2il9</guid>
      <description>&lt;p&gt;It’s been a month since the release of the new Long-Term Support (LTS) version of Java. This release brings a host of new language and compiler features, but in this post, I’ll focus on several that stand out as truly transformative for developers and production systems alike.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Memory Efficiency: Compact Object Headers
&lt;/h2&gt;

&lt;p&gt;One of the most exciting improvements in JDK 25 is the introduction of Compact Object Headers, now a finalized feature via JEP 519. This enhancement builds upon JEP 450, where Compact Object Headers were first introduced as an experimental feature.&lt;/p&gt;

&lt;p&gt;In short, this feature compresses the Java object header from 96 bits down to 64 bits, dramatically reducing heap memory usage for existing applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How It Works?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Previously, the Mark Word contained several unused bits — 27 in total. Out of 96 bits, only 69 were actually needed. Java 25 reorganizes and optimizes the structure to fit into a compact 64-bit format.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F1row9xljl7i6kl8kmmbp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F1row9xljl7i6kl8kmmbp.png" alt="Metrics" width="800" height="287"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The new header structure now directly stores:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A compressed class pointer (reduced from 32 bits to 22 bits)&lt;/li&gt;
&lt;li&gt;A 31-bit identity hash code (unchanged)&lt;/li&gt;
&lt;li&gt;4 bits reserved for Project Valhalla&lt;/li&gt;
&lt;li&gt;4 bits for object age (unchanged)&lt;/li&gt;
&lt;li&gt;1 bit for the “Self Forwarded Tag”&lt;/li&gt;
&lt;li&gt;2 tag bits (unchanged)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Performance results&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/rkennke/talks/blob/master/Lilliput-FOSDEM-2025.pdf" rel="noopener noreferrer"&gt;Early testing&lt;/a&gt; shows substantial performance and memory gains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Up to 22% less heap usage&lt;/li&gt;
&lt;li&gt;8% faster execution times&lt;/li&gt;
&lt;li&gt;Amazon reports up to 30% CPU reduction across hundreds of production services&lt;/li&gt;
&lt;li&gt;15% fewer garbage collection cycles for both G1 and Parallel collectors&lt;/li&gt;
&lt;li&gt;JSON parsing benchmarks show 10% faster execution&lt;/li&gt;
&lt;li&gt;Throughput overhead stays below 5% even in worst-case scenarios&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These improvements make Compact Object Headers a massive win for both cloud and on-premise deployments.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Faster Startup: Project Leyden Integration
&lt;/h2&gt;

&lt;p&gt;One of Java’s longest-standing challenges has been slow startup and warmup times. JDK 25 makes a significant leap forward in this area through enhancements connected to Project Leyden.&lt;/p&gt;

&lt;p&gt;Project Leyden’s main goal is to improve application startup and warmup performance by introducing profile-guided optimizations and ahead-of-time (AOT) capabilities at the JVM level.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How It Works?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;During a typical application run, the JVM collects profiling data — information about which methods are invoked most frequently or consume the most CPU. Traditionally, this profiling happens at runtime during the first execution phase.&lt;/p&gt;

&lt;p&gt;With Java 25 and Leyden’s enhancements, these profiles can now be saved during a “training run” and reused later. In subsequent executions, the JVM can skip the early profiling stage and begin optimized compilation immediately, resulting in much faster startup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benchmark Example&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Recent benchmark results running over the Quarkus framework show measurable improvements in startup times and warmup efficiency.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Foo4d8wp0w5iqar5pqw7y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Foo4d8wp0w5iqar5pqw7y.png" alt="Benchmark" width="800" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="https://github.com/openjdk/leyden/blob/premain/README.md" rel="noopener noreferrer"&gt;OpenJDK Project Leyden README&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These enhancements align well with modern deployment patterns — especially for containerized or serverless environments — where rapid startup is critical.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Stable Values: Safe, On-Demand Initialization
&lt;/h2&gt;

&lt;p&gt;JDK 25 introduces a powerful new construct called Stable Values — a mechanism for defining values that are initialized exactly once and then remain immutable throughout the lifetime of the application.&lt;/p&gt;

&lt;p&gt;This feature standardizes lazy initialization patterns that developers often implement manually and allows the JVM to optimize these values in the same way as final fields through constant folding and other compiler optimizations.&lt;/p&gt;

&lt;p&gt;A StableValue behaves like a container that holds an object — the so-called “content.”&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It starts uninitialized.&lt;/li&gt;
&lt;li&gt;It is initialized once, when first accessed.&lt;/li&gt;
&lt;li&gt;After initialization, it becomes immutable and thread-safe.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s a simple example:&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ConfigService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// Create a StableValue container for caching configuration&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;StableValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AppConfig&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StableValue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;AppConfig&lt;/span&gt; &lt;span class="nf"&gt;getConfig&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Initialize lazily on first access&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orElseSet&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="n"&gt;loadConfig&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;AppConfig&lt;/span&gt; &lt;span class="nf"&gt;loadConfig&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Loading configuration from file..."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// Simulate reading configuration data&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AppConfig&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"prod"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&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;printConfig&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;AppConfig&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getConfig&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;printf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Mode: %s | Workers: %d | Cache: %s%n"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;workerCount&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cacheEnabled&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Sample record representing configuration structure&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;AppConfig&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;workerCount&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;cacheEnabled&lt;/span&gt;&lt;span class="o"&gt;)&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;What happens here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first call to getConfig() triggers loadConfig() and stores the result in the stable value.&lt;/li&gt;
&lt;li&gt;All subsequent accesses return the same cached instance without reloading.

&lt;ul&gt;
&lt;li&gt;Even in multithreaded contexts, orElseSet() ensures initialization happens exactly once.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This pattern eliminates the need for manually synchronized lazy initialization blocks. Once populated, the stable value behaves just like a final constant, and the JVM can optimize it accordingly.&lt;/p&gt;

&lt;p&gt;JDK 25 also includes related classes such as:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;StableList&lt;/em&gt; – for lists initialized once&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;StableMap&lt;/em&gt; – for single-initialization maps&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;StableFunction&lt;/em&gt; – for functions that compute a result once, then cache it immutably&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Java 25 marks a pivotal moment in the evolution of the Java platform.&lt;/p&gt;

&lt;p&gt;With Compact Object Headers, Project Leyden startup optimizations, and Stable Values, the focus is clear: greater performance, efficiency, and modernized application behavior for cloud-native environments.&lt;/p&gt;

&lt;p&gt;If you’re maintaining long-lived services or performance-critical applications, upgrading to Java 25 should definitely be on your roadmap.&lt;/p&gt;

</description>
      <category>java</category>
      <category>java25</category>
      <category>jdk</category>
    </item>
    <item>
      <title>How to programmatically look up a bean in Quarkus</title>
      <dc:creator>Ivelin Yanev</dc:creator>
      <pubDate>Thu, 15 May 2025 17:51:43 +0000</pubDate>
      <link>https://dev.to/yanev/how-to-programmatically-look-up-a-bean-in-quarkus-1h7m</link>
      <guid>https://dev.to/yanev/how-to-programmatically-look-up-a-bean-in-quarkus-1h7m</guid>
      <description>&lt;p&gt;In Quarkus, a modern Java framework optimized for cloud-native and serverless applications, Contexts and Dependency Injection (CDI) is a core feature for managing beans. While dependency injection via &lt;code&gt;@Inject&lt;/code&gt; is the standard way to access beans, there are scenarios where you need to programmatically look up beans at runtime. This article explores various methods to programmatically look up beans in Quarkus, with practical examples and best practices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why would you need programmatic bean lookup?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You need to resolve beans dynamically based on runtime conditions (e.g., selecting a specific implementation).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You’re working in a non-CDI-managed class (e.g., a static context, utility class or third-party integrations).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You need to iterate over all beans of a given type or select beans with specific qualifiers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You want to check for bean availability or defer bean resolution for performance reasons.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Quarkus provides several approaches to programmatically look up beans, leveraging its optimized CDI implementation, &lt;code&gt;Arc&lt;/code&gt;. The primary methods include using the Arc container, the standard CDI API, &lt;code&gt;Instance&amp;lt;T&amp;gt;&lt;/code&gt; with or without &lt;code&gt;@Any&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Methods for programmatic bean lookup
&lt;/h2&gt;

&lt;p&gt;For all examples, we'll use the following bean interface and implementation:&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;MyBean&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@ApplicationScoped&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BeanImpl1&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;MyBean&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="nd"&gt;@Override&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getName&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="s"&gt;"Standard Bean"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@Override&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;doSomething&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"BeanImpl1 is working!"&lt;/span&gt;&lt;span class="o"&gt;);&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;ul&gt;
&lt;li&gt;&lt;strong&gt;Using the Arc Container(Quarkus-specific)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Arc container is Quarkus CDI implementation, optimized for fast startup and low memory usage. It provides a straightforward API for programmatic bean lookup via &lt;code&gt;Arc.container()&lt;/code&gt;.&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="nc"&gt;InstanceHandle&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyBean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;beanHandle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Arc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MyBean&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&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="n"&gt;beanHandle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isAvailable&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="nc"&gt;MyBean&lt;/span&gt; &lt;span class="n"&gt;myBean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;beanHandle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
      &lt;span class="n"&gt;myBean&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;doSomething&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MyBean not found"&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;However, when running this code, you might encounter the following error:&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;================================================================================&lt;/span&gt;
CDI: programmatic lookup problem detected
&lt;span class="nt"&gt;-----------------------------------------&lt;/span&gt;
At least one bean matched the required &lt;span class="nb"&gt;type &lt;/span&gt;and qualifiers but was marked as unused and removed during build

Stack frame: 
Required &lt;span class="nb"&gt;type&lt;/span&gt;: interface org.acme.beans.MyBean
Required qualifiers: &lt;span class="o"&gt;[&lt;/span&gt;@jakarta.enterprise.inject.Default&lt;span class="o"&gt;()]&lt;/span&gt;
Removed beans:
        - CLASS bean  &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;types&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;interface org.acme.beans.MyBean, class org.acme.beans.BeanImpl1], &lt;span class="nv"&gt;qualifiers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null]
Solutions:
        - Application developers can eliminate &lt;span class="nb"&gt;false &lt;/span&gt;positives via the @Unremovable annotation
        - Extensions can eliminate &lt;span class="nb"&gt;false &lt;/span&gt;positives via build items, e.g. using the UnremovableBeanBuildItem
        - See also https://quarkus.io/guides/cdi-reference#remove_unused_beans
        - Enable the DEBUG log level to see the full stack trace
&lt;span class="o"&gt;================================================================================&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Understanding the Problem&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Quarkus uses build-time optimization to improve startup time and reduce memory usage. Part of this optimization is unused bean removal, where Quarkus analyzes your application at build time and removes beans that appear to be unused.&lt;/p&gt;

&lt;p&gt;When using &lt;code&gt;Arc.container().instance(MyBean.class)&lt;/code&gt; for programmatic lookup, you're encountering this error because Quarkus couldn't detect at build time that &lt;code&gt;BeanImpl1&lt;/code&gt; (which implements MyBean) would be needed at runtime. The bean was considered "unused" and was removed during the build process, and when you try to look it up at runtime, it's no longer available.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Solutions to Fix the Problem&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;1.Mark Your Bean as &lt;code&gt;@Unremovable&lt;/code&gt;&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;@Unremovable&lt;/span&gt;
&lt;span class="nd"&gt;@ApplicationScoped&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BeanImpl1&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;MyBean&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Implementation&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2.Disable Unused Bean Removal (in application.properties)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;quarkus.arc.remove-unused-beans=false&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Using the Standard CDI API&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="nc"&gt;MyBean&lt;/span&gt; &lt;span class="n"&gt;myBean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;CDI&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;current&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;select&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MyBean&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;myBean&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;doSomething&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Using &lt;code&gt;@Inject&lt;/code&gt; with &lt;code&gt;Instance&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For CDI-managed beans, using &lt;code&gt;Instance&amp;lt;T&amp;gt;&lt;/code&gt; offers a flexible approach to dynamic lookup.&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;@Inject&lt;/span&gt;
  &lt;span class="nc"&gt;Instance&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyBean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;myBeanInstance&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="n"&gt;myBeanInstance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isResolvable&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="nc"&gt;MyBean&lt;/span&gt; &lt;span class="n"&gt;bean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;myBeanInstance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
      &lt;span class="n"&gt;bean&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;doSomething&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;ul&gt;
&lt;li&gt;&lt;strong&gt;Using &lt;code&gt;@Any&lt;/code&gt; with &lt;code&gt;Instance&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;@Any&lt;/code&gt; qualifier extends &lt;code&gt;Instance&amp;lt;T&amp;gt;&lt;/code&gt; capabilities to access all beans of a type regardless of qualifiers, which is particularly useful for plugins or strategy patterns. &lt;/p&gt;

&lt;p&gt;Let's create an additional implementation for our bean:&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;@ApplicationScoped&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BeanImpl2&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;MyBean&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="nd"&gt;@Override&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getName&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="s"&gt;"Specific BeanImpl2"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@Override&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;doSomething&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"BeanImpl2 (specificBean) is working!"&lt;/span&gt;&lt;span class="o"&gt;);&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;Now we can look up all beans:&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;@Inject&lt;/span&gt;
  &lt;span class="nd"&gt;@Any&lt;/span&gt;
  &lt;span class="nc"&gt;Instance&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyBean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;allBeans&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Found "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;allBeans&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"implementations"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;allBeans&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bean&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processing bean: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;bean&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getClass&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getSimpleName&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
      &lt;span class="n"&gt;bean&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;doSomething&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;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Found 2 implementations
Processing bean: BeanImpl1_ClientProxy
BeanImpl1 is working!
Processing bean: BeanImpl2_ClientProxy
BeanImpl2 &lt;span class="o"&gt;(&lt;/span&gt;specificBean&lt;span class="o"&gt;)&lt;/span&gt; is working!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Programmatic bean lookup in Quarkus provides flexibility for dynamic bean resolution and working with multiple implementations. While @Inject should remain your primary approach for accessing beans in most scenarios, the methods described in this article offer powerful alternatives for specific use cases.&lt;/p&gt;

&lt;p&gt;When choosing a lookup method, consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build-time optimization impacts (remember the @Unremovable annotation when needed)&lt;/li&gt;
&lt;li&gt;Whether you need to access multiple beans or specific implementations&lt;/li&gt;
&lt;li&gt;The context in which you're performing the lookup (CDI-managed vs. non-CDI-managed.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>quarkus</category>
      <category>cdi</category>
      <category>java</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to Build an AI Application with Quarkus and LangChain4j</title>
      <dc:creator>Ivelin Yanev</dc:creator>
      <pubDate>Sun, 16 Mar 2025 19:06:09 +0000</pubDate>
      <link>https://dev.to/yanev/how-to-build-an-ai-application-with-quarkus-and-langchain4j-3do5</link>
      <guid>https://dev.to/yanev/how-to-build-an-ai-application-with-quarkus-and-langchain4j-3do5</guid>
      <description>&lt;p&gt;In light of the LLM boom over the past year, we can conclude that virtually everyone has, for one reason or another, used a model from one of the major providers, such as Facebook, Google, Microsoft, Amazon, and others.&lt;/p&gt;

&lt;p&gt;From a technical standpoint, it's fascinating to explore how we can develop software that leverages LLMs. In this comprehensive guide, we'll walk through building an AI application using Quarkus and LangChain4j.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Basic knowledge of Java, Quarkus and LangChain4j&lt;/li&gt;
&lt;li&gt;JDK 17 or newer&lt;/li&gt;
&lt;li&gt;Maven or Gradle&lt;/li&gt;
&lt;li&gt;An API key from an LLM provider (e.g., OpenAI)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is LangChain4j?
&lt;/h2&gt;

&lt;p&gt;LangChain4j is a powerful Java framework designed to simplify the integration of Large Language Models (LLMs) and other AI capabilities into Java applications. As a Java port of the popular LangChain project, it provides developers with a robust and type safe way to build AI-powered applications while maintaining the reliability and structure that Java is known for.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ffjp07sr4jjf2af9pho0j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ffjp07sr4jjf2af9pho0j.png" alt="LangChain4j - Overview" width="545" height="413"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;LangChain4j - Overview&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The framework is built around composable components that can be mixed and matched to create custom AI solutions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Language Models&lt;/li&gt;
&lt;li&gt;Memory Systems&lt;/li&gt;
&lt;li&gt;Document Loaders&lt;/li&gt;
&lt;li&gt;Vector Stores&lt;/li&gt;
&lt;li&gt;Embeddings&lt;/li&gt;
&lt;li&gt;Tools and Agents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fmm61r7ofvtnx1p7wnyld.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fmm61r7ofvtnx1p7wnyld.png" alt="LangChain4j - Components" width="800" height="355"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;LangChain4j - Components&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Core Components Explained
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Language Models&lt;br&gt;
Language Models (LLMs) are the AI engines that process and generate text, with LangChain4j primarily supporting OpenAI's GPT models and other compatible LLMs. They handle tasks like text generation, summarization, and structured data extraction through a unified interface.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Memory Systems&lt;br&gt;
Memory Systems maintain conversation history and context between interactions, allowing for coherent multi-turn conversations. The can be configured to store messages in various backends (in-memory, database) and manage conversation context with customizable retention policies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document Loaders&lt;br&gt;
Document Loaders provide interfaces to read and process various file formats (PDF, TXT, HTML) into a standardized format for AI processing. They handle the complexities of file reading and initial text extraction, making documents ready for further processing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Vector Stores&lt;br&gt;
Vector Stores are specialized databases that store and retrieve text embeddings, enabling semantic search capabilities. They support various backends like Pinecone or local storage, making it efficient to find semantically similar content.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Embeddings&lt;br&gt;
Embeddings convert text into numerical vectors that capture semantic meaning, essential for similarity searches and content comparison. They work with various embedding models (like OpenAI's embeddings) to transform text into mathematical representations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tools and Agents&lt;br&gt;
Tools and Agents are components that extend LLM capabilities by providing specific functionalities (like calculations or API calls) and autonomous decision-making abilities. They allow LLMs to interact with external systems and perform complex tasks through defined interfaces.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Configuration Setup
&lt;/h2&gt;

&lt;p&gt;Adding LangChain4j extensions:&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="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;io.quarkiverse.langchain4j&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;quarkus-langchain4j&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;${langchain4j.version}&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;dev.langchain4j&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;langchain4j-core&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;${langchain4j-core.version}&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OpenAI Configuration&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;quarkus.langchain4j.openai.api-key=${OPENAI_API_KEY}
quarkus.langchain4j.openai.timeout=60s
quarkus.langchain4j.openai.chat-model.temperature=0.7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Simple AI Service
&lt;/h2&gt;

&lt;p&gt;The Simple AI Service is designed for straightforward AI tasks, such as generating text based on a given prompt. In your project, this is implemented in the &lt;code&gt;SimplePostAiService&lt;/code&gt; interface&lt;/p&gt;

&lt;p&gt;How It Works&lt;/p&gt;

&lt;p&gt;Interface Definition:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;@RegisterAiService&lt;/code&gt; annotation marks the interface as an AI service that LangChain4j will implement.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;writeNews&lt;/code&gt; method takes a topic and length as input and generates a news article.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example Code:&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;@RegisterAiService&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;SimplePostAiService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;writeNews&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;length&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;Use Case:&lt;/p&gt;

&lt;p&gt;This service can be used to generate short news articles or summaries based on a specific topic. For example, calling &lt;code&gt;writeNews("technology", 100)&lt;/code&gt; might generate a 100-word article about the latest tech trends.&lt;/p&gt;

&lt;p&gt;Integration:&lt;/p&gt;

&lt;p&gt;The service is injected into the &lt;code&gt;GreetingResource&lt;/code&gt; class and exposed via a REST endpoint:&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;@GET&lt;/span&gt;
&lt;span class="nd"&gt;@Path&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/news/{topic}/{length}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;writeNews&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@PathParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"topic"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;@PathParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"length"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;length&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;simplePostAiService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writeNews&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;length&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;
  
  
  Advanced AI Service with Memory
&lt;/h2&gt;

&lt;p&gt;Memory is a fundamental component in LangChain4j that plays a crucial role in creating meaningful and contextual interactions between users and AI models. Unlike traditional request-response systems where each interaction stands alone, memory enables applications to maintain context and create more natural, flowing conversations.&lt;/p&gt;

&lt;p&gt;The primary purpose of memory in LangChain4j is to maintain conversation history and context. Without memory, each interaction with an AI model would be isolated, forcing users to repeatedly provide context or background information. For example, in a conversation about travel planning, memory allows the AI to remember previously mentioned destinations, dates, or preferences without requiring the user to restate this information in each message.&lt;/p&gt;

&lt;p&gt;The Advanced AI Service with Memory enhances AI interactions by maintaining context across multiple requests. This is implemented in the &lt;code&gt;AdvancedPostAiService&lt;/code&gt; interface.&lt;/p&gt;

&lt;p&gt;Interface Definition:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;@RegisterAiService&lt;/code&gt; annotation marks the interface as an AI service.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;chatWithMailPostBotWithMemory&lt;/code&gt; method uses the &lt;code&gt;@MemoryId&lt;/code&gt; annotation to associate a memory with a specific user.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example Code:&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;@RegisterAiService&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;AdvancedPostAiService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;chatWithMailPostBotWithMemory&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@MemoryId&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;text&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;Use Case:&lt;/p&gt;

&lt;p&gt;This service is ideal for applications like chatbots, where maintaining context across conversations is crucial. For example, a user could ask, &lt;em&gt;"What’s the weather today?"&lt;/em&gt; and follow up with &lt;em&gt;"What about tomorrow?"&lt;/em&gt; without needing to repeat the location.&lt;/p&gt;

&lt;p&gt;Integration:&lt;/p&gt;

&lt;p&gt;The service is injected into the &lt;code&gt;GreetingResource&lt;/code&gt; class and exposed via a REST endpoint&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;@GET&lt;/span&gt;
&lt;span class="nd"&gt;@Path&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/mail-with-memory"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;writeNewsWithMemory&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="nd"&gt;@QueryParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;@QueryParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"userId"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;userId&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;advancedPostAiService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;chatWithMailPostBotWithMemory&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&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;
  
  
  Understanding Message Types in LangChain4j
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;System Messages (&lt;code&gt;@SystemMessage&lt;/code&gt;)&lt;br&gt;
System messages serve as instructions or context-setting &lt;br&gt;
information for the AI model. They help define the behavior, role, &lt;br&gt;
or constraints for the AI's responses. These messages are not &lt;br&gt;
typically visible to end users but are crucial for controlling how &lt;br&gt;
the AI behaves.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;User Messages (&lt;code&gt;@UserMessage&lt;/code&gt;)&lt;br&gt;
User messages represent the actual input from users interacting with the AI system. These messages contain the queries, statements, or requests that the AI needs to respond to. They form the core of the interaction between users and the AI.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Understanding Retrieval-Augmented Generation (RAG)
&lt;/h2&gt;

&lt;p&gt;Retrieval-Augmented Generation (RAG) is an advanced approach that combines the power of large language models (LLMs) with a knowledge base of specific information. Instead of relying solely on an LLM's pre-trained knowledge, RAG retrieves relevant information from a custom document collection before generating responses. This approach significantly improves the accuracy and reliability of AI generated responses by grounding them in specific, verified information.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why RAG is Needed?
&lt;/h2&gt;

&lt;p&gt;Traditional LLMs face several limitations that RAG helps to overcome:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LLMs have knowledge limited to their training data cutoff date. RAG allows them to access current information.&lt;/li&gt;
&lt;li&gt;LLMs might generate plausible but incorrect information. RAG reduces this by providing specific, accurate source material.&lt;/li&gt;
&lt;li&gt;Companies often need responses based on their specific documentation, policies, or knowledge base. RAG enables this customization.&lt;/li&gt;
&lt;li&gt;With RAG, responses can be traced back to source documents, making the system more transparent and trustworthy.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Components of RAG: A Step-by-Step Process
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Document Processing&lt;br&gt;
The first crucial step in implementing RAG involves preparing and processing your documents. This starts with loading documents from various sources such as files, databases, or web content. Documents are then split into smaller, manageable chunks that are optimal for processing and retrieval. The splitting process must balance chunk size with context preservation, ensuring that each segment maintains meaningful information while staying within the model's token limits. This stage also includes cleaning and standardizing the text, removing irrelevant information, and structuring the content appropriately.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Embedding Generation&lt;br&gt;
Once documents are processed and split, the next step is converting these text chunks into embeddings. Embeddings are numerical representations of text that capture semantic meaning, allowing for efficient similarity searches. This process uses embedding models (such as those from OpenAI or other providers) to transform text into high-dimensional vectors. These embeddings serve as the foundation for semantic search capabilities, enabling the system to find relevant information based on meaning rather than just keywords.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Vector Storage&lt;br&gt;
The third key component involves storing and organizing these embeddings in a vector database. Vector stores are specialized databases designed to efficiently store and retrieve high-dimensional vectors. They index the embeddings in a way that enables fast similarity searches, which is crucial for retrieving relevant context during query processing. The choice of vector store depends on factors like data volume, performance requirements, and scaling needs. Popular options include Pinecone, Weaviate, or local vector stores for smaller applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Retrieval Mechanism&lt;br&gt;
When a query is received, the system converts it into an embedding and searches the vector store for similar vectors. This retrieval process identifies the most relevant document chunks based on semantic similarity. The mechanism can be enhanced with filters, metadata search, and hybrid approaches combining semantic and keyword search for better accuracy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Context Assembly&lt;br&gt;
After retrieving relevant chunks, the system assembles them into a coherent context. This involves selecting the most pertinent information, ordering it logically, and ensuring it fits within the model's context window. The assembly process might include deduplication, relevance ranking, and context summarization to optimize the input for the language model.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Response Generation&lt;br&gt;
The final step involves combining the assembled context with the original query to create a prompt for the language model. This prompt engineering ensures the model understands how to use the provided context to generate accurate, relevant responses. The system then processes this through the LLM to generate the final response, which should be grounded in the retrieved information while maintaining natural language fluency.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fjgc2che1eduhjouc4hom.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fjgc2che1eduhjouc4hom.png" alt="RAG" width="800" height="375"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Retrieval-Augmented Generation (RAG)&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;The Document Retrieval Service leverages LangChain4j’s embedding models and document storage to retrieve relevant information.&lt;/p&gt;

&lt;p&gt;This is implemented in the &lt;code&gt;DocsAiService&lt;/code&gt; interface.&lt;/p&gt;

&lt;p&gt;Interface Definition:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;@RegisterAiService&lt;/code&gt; annotation marks the interface as an AI service.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;chatWithQuarkusDocsBot&lt;/code&gt; method takes a user prompt and retrieves relevant information from a document store.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example Code:&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;@RegisterAiService&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;DocsAiService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;chatWithQuarkusDocsBot&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@UserMessage&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;prompt&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;Embedding Ingesters:&lt;/p&gt;

&lt;p&gt;Embedding ingesters are responsible for processing and storing documents in a way that makes them searchable. They split documents into chunks, generate embeddings, and store them in a vector database.&lt;/p&gt;

&lt;p&gt;Document Splitting:&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="nc"&gt;DocumentSplitter&lt;/span&gt; &lt;span class="n"&gt;splitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DocumentSplitters&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recursive&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Embedding Generation:&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="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Embedding&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;embeddings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;embeddingModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;embed&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunks&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Storage in Vector Store:&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="nc"&gt;EmbeddingStoreIngestor&lt;/span&gt; &lt;span class="n"&gt;ingestor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;EmbeddingStoreIngestor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;embeddingStore&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;embeddingStore&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;embeddingModel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;embeddingModel&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;documentSplitter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;splitter&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;ingestor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ingest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;DocumentsRetriever&lt;/code&gt; class is a Quarkus-managed bean that provides a &lt;code&gt;RetrievalAugmentor&lt;/code&gt; for integrating retrieval-augmented generation (RAG) into your application. It is annotated with &lt;code&gt;@ApplicationScoped&lt;/code&gt;, meaning it is instantiated once and shared across the application. The class constructs an &lt;code&gt;EmbeddingStoreContentRetriever&lt;/code&gt; using a provided &lt;code&gt;RedisEmbeddingStore&lt;/code&gt; and &lt;code&gt;EmbeddingModel&lt;/code&gt;. This retriever fetches relevant documents based on semantic similarity. It configures a &lt;code&gt;DefaultRetrievalAugmentor&lt;/code&gt; with the retriever, which can be used to augment LLM responses with contextually relevant information. The &lt;code&gt;maxResults&lt;/code&gt; parameter is set to 20, limiting the number &lt;br&gt;
of documents retrieved per query. The &lt;code&gt;get()&lt;/code&gt; method returns the configured &lt;code&gt;RetrievalAugmentor&lt;/code&gt;, which can be injected into other components to enhance LLM interactions.&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;@ApplicationScoped&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DocumentsRetriever&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Supplier&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RetrievalAugmentor&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;RetrievalAugmentor&lt;/span&gt; &lt;span class="n"&gt;augmentor&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;DocumentsRetriever&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;RedisEmbeddingStore&lt;/span&gt; &lt;span class="n"&gt;store&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;EmbeddingModel&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;EmbeddingStoreContentRetriever&lt;/span&gt; &lt;span class="n"&gt;contentRetriever&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="nc"&gt;EmbeddingStoreContentRetriever&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;embeddingModel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;embeddingStore&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;maxResults&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;augmentor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DefaultRetrievalAugmentor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;contentRetriever&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contentRetriever&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@Override&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;RetrievalAugmentor&lt;/span&gt; &lt;span class="nf"&gt;get&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;augmentor&lt;/span&gt;&lt;span class="o"&gt;;&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;You can explore the complete source code for this project in the &lt;a href="https://github.com/iqnev/quarkus-langchain4j-demo" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Building AI applications with Quarkus and LangChain4j provides a powerful combination for creating intelligent, production-ready solutions. Through this guide, we've explored the essential components and implementation patterns, from basic AI services to advanced features like RAG and embedding ingesters.&lt;/p&gt;

</description>
      <category>quarkus</category>
      <category>langchain</category>
      <category>ai</category>
      <category>programming</category>
    </item>
    <item>
      <title>A Deep Dive into Graceful Shutdown in Go</title>
      <dc:creator>Ivelin Yanev</dc:creator>
      <pubDate>Mon, 10 Feb 2025 19:02:17 +0000</pubDate>
      <link>https://dev.to/yanev/a-deep-dive-into-graceful-shutdown-in-go-484a</link>
      <guid>https://dev.to/yanev/a-deep-dive-into-graceful-shutdown-in-go-484a</guid>
      <description>&lt;p&gt;When developing web services in Go, implementing proper shutdown handling is crucial for maintaining system reliability and data integrity. A graceful shutdown ensures that your service can terminate safely while completing existing operations, rather than abruptly stopping and potentially leaving tasks unfinished.&lt;/p&gt;

&lt;p&gt;Let's understand the core mechanism of graceful shutdown through a practical example.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Concept
&lt;/h2&gt;

&lt;p&gt;Graceful shutdown involves coordinating between incoming termination signals, ongoing operations, and resource cleanup. In Go, this is typically achieved using signal handling, goroutines, and context-based cancellation. Here's a minimal implementation that demonstrates these concepts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"context"&lt;/span&gt;
    &lt;span class="s"&gt;"errors"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;
    &lt;span class="s"&gt;"os/signal"&lt;/span&gt;
    &lt;span class="s"&gt;"syscall"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;mux&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewServeMux&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;mux&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&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="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, World!"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;})&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;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Addr&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;         &lt;span class="s"&gt;":8787"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Handler&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="n"&gt;mux&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;ReadTimeout&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="m"&gt;15&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;WriteTimeout&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;IdleTimeout&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="m"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;serverError&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Server is running on http://localhost%s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&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="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrServerClosed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;serverError&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;

    &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Interrupt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;syscall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIGTERM&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;serverError&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Server error: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;sig&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received shutdown signal: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Server is shutting down..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&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="n"&gt;Shutdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Server shutdown error: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Server exited properly"&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;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;The implementation starts by running the HTTP server in a separate goroutine. This allows the main goroutine to handle shutdown signals without blocking the server's operation. We create two channels: one for server errors and another for OS signals.&lt;/p&gt;

&lt;p&gt;The signal handling channel (stop) is buffered to ensure we don't miss the shutdown signal even if we're not immediately ready to process it. We register this channel to receive both &lt;code&gt;SIGINT (Ctrl+C)&lt;/code&gt; and &lt;code&gt;SIGTERM&lt;/code&gt; signals, which are common ways to request server shutdown.&lt;/p&gt;

&lt;p&gt;We use a select statement to wait for either a server error or a shutdown signal. This creates a blocking point where our program waits for something to happen. When either occurs, we begin the shutdown process.&lt;/p&gt;

&lt;p&gt;The shutdown itself uses a context with timeout to ensure we don't hang indefinitely. The &lt;code&gt;server.Shutdown&lt;/code&gt; method stops accepting new connections immediately while allowing existing requests to complete. If ongoing requests take longer than our timeout (15 seconds in this case), the shutdown will be forced.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Shutdown Sequence
&lt;/h2&gt;

&lt;p&gt;When a shutdown signal is received, the following sequence occurs:&lt;/p&gt;

&lt;p&gt;First, the server stops accepting new connections. This prevents new requests from starting while we're trying to shut down.&lt;/p&gt;

&lt;p&gt;Next, the server waits for all existing connections to complete their current requests. This is the "graceful" part of the shutdown - we're giving ongoing operations a chance to finish properly.&lt;/p&gt;

&lt;p&gt;If any requests are still running when the context timeout expires, they will be forcefully terminated. This prevents the server from hanging indefinitely if some requests take too long.&lt;/p&gt;

&lt;p&gt;Finally, once all requests are complete or the timeout is reached, the server exits and the program can terminate cleanly.&lt;/p&gt;

&lt;p&gt;This visual representation helps understand how different components interact during the shutdown process and how the program coordinates between normal operation and graceful termination.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fs0y1qzafydoz93pqh4a9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fs0y1qzafydoz93pqh4a9.png" alt="Graceful Shutdown Flow in Go" width="800" height="714"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Considerations
&lt;/h2&gt;

&lt;p&gt;In production environments, you might need to handle additional cleanup tasks during shutdown. This could include closing database connections, saving state, or cleaning up temporary files. These operations should be added before the &lt;code&gt;server.Shutdown&lt;/code&gt; call and should respect the same context timeout.&lt;/p&gt;

&lt;p&gt;It's also worth noting that the 15-second timeout we've used is arbitrary. In practice, you should choose a timeout value that makes sense for your application's typical request duration and cleanup needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing the Implementation
&lt;/h2&gt;

&lt;p&gt;You can test this implementation by running the server and sending it a shutdown signal. For example, pressing &lt;code&gt;Ctrl+C&lt;/code&gt; in the terminal will trigger the graceful shutdown process. You should see the shutdown messages in the logs, and any in-flight requests should complete before the server exits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Benefits of This Implementation
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Non-blocking Operation

&lt;ul&gt;
&lt;li&gt;Server runs in a separate goroutine&lt;/li&gt;
&lt;li&gt;Main goroutine remains responsive to signals&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Controlled Shutdown

&lt;ul&gt;
&lt;li&gt;Existing requests are allowed to complete&lt;/li&gt;
&lt;li&gt;New requests are rejected&lt;/li&gt;
&lt;li&gt;Timeout prevents hanging&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Error Handling

&lt;ul&gt;
&lt;li&gt;Captures both server errors and shutdown errors&lt;/li&gt;
&lt;li&gt;Distinguishes between normal shutdown and errors&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Graceful shutdown is a crucial pattern for production-ready Go services. This implementation provides a solid foundation that ensures your service can handle termination requests properly, complete ongoing work, and exit cleanly. While the concept is straightforward, proper implementation ensures reliability and maintains a good user experience even during service termination.&lt;/p&gt;

&lt;p&gt;The key to understanding graceful shutdown is recognizing that it's about managing the transition from running to stopped states in a way that preserves system integrity and user experience. This implementation demonstrates how Go's concurrency primitives and standard library make this possible in a clean and efficient way.&lt;/p&gt;

</description>
      <category>go</category>
      <category>programming</category>
      <category>coding</category>
    </item>
    <item>
      <title>Mastering Pointers in Go: Enhancing Safety, Performance, and Code Maintainability</title>
      <dc:creator>Ivelin Yanev</dc:creator>
      <pubDate>Sun, 12 Jan 2025 19:00:13 +0000</pubDate>
      <link>https://dev.to/yanev/mastering-pointers-in-go-enhancing-safety-performance-and-code-maintainability-2ep1</link>
      <guid>https://dev.to/yanev/mastering-pointers-in-go-enhancing-safety-performance-and-code-maintainability-2ep1</guid>
      <description>&lt;p&gt;Pointers play a crucial role in Go programming, offering a powerful tool for developers to directly access and manipulate the memory addresses of variables. Unlike traditional variables that store actual data values, pointers store the memory locations where these values are kept. This unique capability enables pointers to modify the original data in memory, providing an efficient way to handle data and optimize program performance.&lt;/p&gt;

&lt;p&gt;Memory addresses, represented in hexadecimal format (e.g., &lt;code&gt;0xAFFFF&lt;/code&gt;), serve as the foundation for pointers. When you declare a pointer variable, it is essentially a special type of variable designed to hold a memory address of another variable, not the data itself.&lt;/p&gt;

&lt;p&gt;Take, for example, a pointer &lt;code&gt;p&lt;/code&gt; in Go, which contains the reference &lt;code&gt;0x0001&lt;/code&gt;, pointing directly to the memory address of another variable &lt;code&gt;x&lt;/code&gt;. This relationship allows &lt;code&gt;p&lt;/code&gt; to directly interact with a's value, showcasing the power and utility of pointers in Go.&lt;/p&gt;

&lt;p&gt;Here's a visual representation of how pointers work:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fakibxvw51mrqeye2ymlz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fakibxvw51mrqeye2ymlz.png" alt="Pointer" width="800" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Deep Dive into Pointers in Go
&lt;/h2&gt;

&lt;p&gt;To declare a pointer in Go, the syntax var &lt;code&gt;p *T&lt;/code&gt; is used, where &lt;code&gt;T&lt;/code&gt; represents the type of the variable to which the pointer will refer. Consider the following example where p is a pointer to an int variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="m"&gt;1.&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
&lt;span class="m"&gt;2.&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;p&lt;/code&gt; stores the address of &lt;code&gt;a&lt;/code&gt;, and through pointer dereferencing (&lt;code&gt;*p&lt;/code&gt;), it can access or modify the value of &lt;code&gt;a&lt;/code&gt;. This mechanism is fundamental in Go for efficient data manipulation and memory management.&lt;/p&gt;

&lt;p&gt;Let's see a basic example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;42&lt;/span&gt;
    &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"x: %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&amp;amp;x: %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"p: %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"*p: %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;pp&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"**pp: %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;pp&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;Output&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Value of x: 42
Address of x: 0xc000012120
Value stored &lt;span class="k"&gt;in &lt;/span&gt;p: 0xc000012120
Value at the address p: 42
&lt;span class="k"&gt;**&lt;/span&gt;pp: 42
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pointers in Go don’t function the way they do in C/C++
&lt;/h2&gt;

&lt;p&gt;A common misconception about when to use pointers in Go stems from comparing pointers in Go directly with pointers in C. It's crucial to understand the distinctions between the two to grasp how pointers function within each language's ecosystem. Let's delve into these differences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No Pointer Arithmetic&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unlike C, where pointer arithmetic allows direct manipulation of memory addresses, Go does not support pointer arithmetic. This intentional design choice by Go leads to several significant advantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prevents Buffer Overflow Vulnerabilities:&lt;/strong&gt; By eliminating pointer arithmetic, Go inherently reduces the risk of buffer overflow vulnerabilities, a common security issue in C programs that allows attackers to execute arbitrary code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Makes Code Safer and More Maintainable:&lt;/strong&gt; Without the complexity introduced by direct memory manipulation, Go code becomes easier to understand, safer to work with, and inherently more maintainable. Developers can focus on the logic of their applications rather than the intricacies of memory management.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reduces Memory-Related Bugs:&lt;/strong&gt; The elimination of pointer arithmetic minimizes common pitfalls such as memory leaks and segmentation faults, making Go programs more robust and stable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simplifies Garbage Collection:&lt;/strong&gt; Go's approach to pointers and memory management streamlines garbage collection, as the compiler and runtime have a clearer understanding of object lifecycles and memory usage patterns. This simplification leads to more efficient garbage collection and, subsequently, better performance.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By eliminating pointer arithmetic, Go safeguards against the misuse of pointers, resulting in more reliable and maintainable code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Memory Management and Dangling Pointers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Go, memory management is significantly simplified compared to languages like C, thanks to its garbage collector.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;// In Go - No manual memory management is needed
func createPerson&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;Person &lt;span class="o"&gt;{&lt;/span&gt;
    p :&lt;span class="o"&gt;=&lt;/span&gt; &amp;amp;Person&lt;span class="o"&gt;{&lt;/span&gt;Name: &lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;p // Safe: Go&lt;span class="s1"&gt;'s garbage collector handles cleanup automatically
}

// In C
struct Person* createPerson() {
    struct Person* p = malloc(sizeof(struct Person));
    // It'&lt;/span&gt;s necessary to remember to free&lt;span class="o"&gt;(&lt;/span&gt;p&lt;span class="o"&gt;)&lt;/span&gt; later to avoid memory leaks
    &lt;span class="k"&gt;return &lt;/span&gt;p&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No Manual Memory Allocation/Deallocation:&lt;/strong&gt; Go abstracts away the complexities of memory allocation and deallocation through its garbage collector, simplifying programming and minimizing errors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Absence of Dangling Pointers:&lt;/strong&gt; Dangling pointers, which occur when a memory address referenced by a pointer is freed or reallocated without updating the pointer, are a common source of bugs in manual memory management systems. Go's garbage collector ensures that objects are only cleaned up when there are no existing references to them, effectively preventing dangling pointers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prevention of Memory Leaks:&lt;/strong&gt; Memory leaks, often caused by forgetting to deallocate memory that is no longer needed, are significantly mitigated in Go. While objects with reachable pointers are not freed in Go, thereby preventing leaks due to lost references, in C, programmers must diligently manage memory manually to avoid such issues.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Nil Pointer Behavior&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Go, attempting to dereference a nil pointer results in a panic. This behavior places an additional responsibility on developers to carefully handle all possible cases of nil references and avoid unintended modifications. While this can increase the overhead of code maintenance and debugging, it also serves as a safeguard against some types of bugs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Student&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Age&lt;/span&gt;  &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;student&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Student&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;student&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;student&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Age&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 output indicates a panic due to an invalid memory address or nil pointer dereference:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;panic: runtime error: invalid memory address or nil pointer dereference
&lt;span class="o"&gt;[&lt;/span&gt;signal SIGSEGV: segmentation violation &lt;span class="nv"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0x1 &lt;span class="nv"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0x0 &lt;span class="nv"&gt;pc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0x48f6fa]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because &lt;code&gt;student&lt;/code&gt; is a nil pointer, not associated with any valid memory address, attempting to access its fields (Name and Age) leads to a runtime panic.&lt;/p&gt;

&lt;p&gt;In contrast, in C, dereferencing a null pointer is considered unsafe. Uninitialized pointers in C point to random parts of memory (undefined), making them even more hazardous. Dereferencing such an undefined pointer could mean the program continues operating with corrupt data, leading to unpredictable behavior, data corruption, or even worse outcomes.&lt;/p&gt;

&lt;p&gt;This approach does come with its trade-offs - it results in a more complex Go compiler compared to the C compiler, which is relatively simpler. Consequently, this complexity can sometimes make Go programs appear slower in execution compared to their C counterparts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Common misconception:&lt;/strong&gt; &lt;em&gt;"Pointers are always faster"&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A prevalent notion suggests that utilizing pointers can enhance your application's speed by minimizing data copying. This concept stems from Go's architecture as a garbage-collected language. When a pointer is passed to a function, Go conducts Escape Analysis to determine whether the variable in question should reside on the stack or be allocated on the heap. While essential, this process introduces a certain level of overhead. Moreover, if the outcome of the analysis dictates heap allocation for the variable, further time is consumed during garbage collection (GC) cycles. This dynamic illustrates that while pointers reduce direct data copying, their impact on performance is nuanced, influenced by the underlying mechanisms of memory management and garbage collection in Go.&lt;/p&gt;

&lt;h2&gt;
  
  
  Escape analysis
&lt;/h2&gt;

&lt;p&gt;Go employs escape analysis to determine the dynamic scope of values within its environment. This process is integral to how Go manages memory allocation and optimization. At its core, the goal is to allocate Go values within the function stack frame whenever possible. The Go compiler takes on the task of predetermining which memory allocations can be safely deallocated, subsequently emitting machine instructions to handle this cleanup process efficiently.&lt;/p&gt;

&lt;p&gt;The compiler conducts a static code analysis to ascertain whether a value should be allocated on the stack frame of the function that constructs it, or if it must "escape" to the heap. It's important to note that Go does not provide any specific keywords or functions that allow developers to explicitly direct this behavior. Rather, it is the conventions and patterns in how the code is written that influence this decision-making process.&lt;/p&gt;

&lt;p&gt;A value may escape to the heap for several reasons. If the compiler cannot determine the size of a variable, if the variable is too large for the stack, or if the compiler cannot reliably discern whether the variable will be used after the function concludes, the value will likely be allocated on the heap. Additionally, if the function stack frame becomes obsolete, this can also trigger a value to escape to the heap.&lt;/p&gt;

&lt;p&gt;However, can we definitively know whether a value is stored on the heap or the stack? The reality is that only the compiler has full visibility into where a value is ultimately stored at any given time.&lt;/p&gt;

&lt;p&gt;Whenever a value is shared beyond the immediate scope of a function's stack frame, it will be allocated on the heap. This is where escape analysis algorithms come into play, identifying these scenarios to ensure the program remains integral. This integrity is crucial for maintaining accurate, consistent, and efficient access to any value within the program. Escape analysis is, therefore, a fundamental aspect of Go's approach to memory management, optimizing for performance and safety of the executed code.&lt;/p&gt;

&lt;p&gt;Look at this example to learn the basic mechanics behind escape analysis:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;student&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;st1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;createStudent1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;st2&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;createStident2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"st1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;st1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"st2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;st2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;//go:noinline&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;createStudent1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;student&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;st&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;student&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;"Name1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"name1@mail.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"V1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;//go:noinline&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;createStudent2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;student&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;st&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;student&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;"Name2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"anme2@mail.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"V2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The &lt;strong&gt;//go:noinline&lt;/strong&gt; directive prevents inlining these functions, ensuring that our examples show clear calls for escape analysis illustration purposes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We've defined two functions, &lt;code&gt;createStudent1&lt;/code&gt; and &lt;code&gt;createStudent2&lt;/code&gt;, to demonstrate different outcomes of escape analysis. Both versions attempt to create a user instance but differ in their return types and how they handle memory.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;createStudent1&lt;/code&gt;: Value Semantics&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;createStudent1&lt;/code&gt;, a student instance is created and returned by value. This means a copy of &lt;code&gt;st&lt;/code&gt; is made and passed up the call stack when the function returns. The Go compiler determines that &lt;code&gt;&amp;amp;st&lt;/code&gt; does not escape to the heap in this scenario. The value exists on the stack frame of &lt;code&gt;createStudent1&lt;/code&gt; and a copy is made for the stack frame of main.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fftuayodxyc80llmb5pte.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fftuayodxyc80llmb5pte.png" alt="Value Semantics" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 1 – Value Semantics&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;createStudent2&lt;/code&gt;: Pointer Semantics&lt;/p&gt;

&lt;p&gt;In contrast, &lt;code&gt;createStudent2&lt;/code&gt; returns a pointer to a &lt;code&gt;student&lt;/code&gt; instance, designed to share the student value across stack frames. This scenario underscores the crucial role of escape analysis. Sharing a pointer risks accessing invalid memory if not managed correctly.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the situation described in &lt;strong&gt;Figure 2&lt;/strong&gt; actually occurred, it would present a significant integrity issue. The pointer would be targeting memory down the call stack that has been invalidated. The subsequent function call by main would result in this previously pointed-to memory being re-allocated and re-initialized.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fmz0bu1elzb268ltvxma0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fmz0bu1elzb268ltvxma0.png" alt="Pointer Semantics" width="800" height="529"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 2 – Pointer Semantics&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here, escape analysis steps in to preserve the integrity of the system. Given this scenario, the compiler determines that it is unsafe to allocate the student value within the stack frame of &lt;code&gt;createStudent2&lt;/code&gt;. Consequently, it opts to allocate this value on the heap instead, a decision made at the moment of construction.&lt;/p&gt;

&lt;p&gt;Functions have direct access to memory within their own frames via the frame pointer. However, accessing memory outside their frame requires indirect access through a pointer. This implies that values destined to escape to the heap are accessed indirectly as well.&lt;/p&gt;

&lt;p&gt;In Go, the process of constructing a value does not inherently indicate where in memory that value resides. It is only upon executing the return statement that it becomes apparent a value must escape to the heap.&lt;/p&gt;

&lt;p&gt;Thus, following the execution of such a function, one could conceptualize the stack in a manner reflecting these dynamics.&lt;/p&gt;

&lt;p&gt;You could visualize the stack looking like this after the function call.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;st&lt;/code&gt; variable on the stack frame for &lt;code&gt;createStudent2&lt;/code&gt;, represents a value that is on the heap, not the stack. This means using &lt;code&gt;st&lt;/code&gt; to access the value, requires pointer access and not the direct access the syntax is suggesting.&lt;/p&gt;

&lt;p&gt;To understand the compiler's decisions regarding memory allocation, you can request a detailed report. This is achieved by using the &lt;code&gt;-gcflags&lt;/code&gt; switch with the &lt;code&gt;-m&lt;/code&gt; option in a go build command.&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="nv"&gt;$ &lt;/span&gt;go build &lt;span class="nt"&gt;-gcflags&lt;/span&gt; &lt;span class="s2"&gt;"-m -m"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Consider the output from this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./main.go:16:6: cannot inline createStudent1: marked go:noinline
./main.go:27:6: cannot inline createStudent2: marked go:noinline
./main.go:8:6: cannot inline main: &lt;span class="k"&gt;function &lt;/span&gt;too complex: cost 133 exceeds budget 80
./main.go:28:2: st escapes to heap:
./main.go:28:2:   flow: ~r0 &lt;span class="o"&gt;=&lt;/span&gt; &amp;amp;st:
./main.go:28:2:     from &amp;amp;st &lt;span class="o"&gt;(&lt;/span&gt;address-of&lt;span class="o"&gt;)&lt;/span&gt; at ./main.go:34:9
./main.go:28:2:     from &lt;span class="k"&gt;return&lt;/span&gt; &amp;amp;st &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; at ./main.go:34:2
./main.go:28:2: moved to heap: st

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

&lt;/div&gt;



&lt;p&gt;This output showcases the compiler's escape analysis results. Here's a breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The compiler reports that it cannot inline certain functions (&lt;code&gt;createUser1&lt;/code&gt;, &lt;code&gt;createUser2&lt;/code&gt;, and &lt;code&gt;main&lt;/code&gt;) due to specific directives (&lt;code&gt;go:noinline&lt;/code&gt;) or because they are non-leaf functions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For &lt;code&gt;createUser1&lt;/code&gt;, the output indicates the reference to &lt;code&gt;st&lt;/code&gt; within the function doesn't escape to the heap. This means the object's lifetime is confined to the stack frame of the function. In contrast, during &lt;code&gt;createUser2&lt;/code&gt;, it’s noted that &lt;code&gt;&amp;amp;st&lt;/code&gt; escapes to the heap. This is explicitly linked to the return statement, which causes the variable u, assigned inside the function, to be moved to heap memory. This is essential as the function is returning a reference to &lt;code&gt;st&lt;/code&gt;, necessitating its existence beyond the function scope.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Garbage collection
&lt;/h2&gt;

&lt;p&gt;Go incorporates a built-in garbage collection mechanism that automatically handles memory allocation and deallocation, contrasting sharply with languages like C/C++ which require manual management of memory. While garbage collection alleviates developers from the complexities of memory management, it introduces latency as a trade-off.&lt;/p&gt;

&lt;p&gt;One notable characteristic in Go is that passing pointers might be slower than passing values directly. This behavior is attributed to Go's nature as a garbage-collected language. Whenever a pointer is passed to a function, Go performs an escape analysis to determine whether the variable should reside on the heap or the stack. This process incurs overhead, and variables allocated on the heap further exacerbate latency during garbage collection cycles. Conversely, variables constrained to the stack bypass the garbage collector entirely, benefiting from the simple and efficient &lt;code&gt;push/pop&lt;/code&gt; operations associated with stack memory management.&lt;/p&gt;

&lt;p&gt;Memory management on the stack is inherently faster due to its straightforward access pattern, where memory allocation and deallocation are accomplished by merely incrementing or decrementing a pointer or an integer. In contrast, heap memory management involves more complex bookkeeping for allocations and deallocations.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to use pointers in Go
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Copying Large Structs&lt;/strong&gt; &lt;br&gt;
While it may seem that pointers are less performant due to the overhead of garbage collection, they prove advantageous with large structs. In such cases, the efficiency gained by avoiding the duplication of large datasets can outweigh the overhead introduced by garbage collection.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mutability&lt;/strong&gt; &lt;br&gt;
To mutate a variable passed to a function, passing a pointer is essential. The default pass-by-value approach means any modifications are made on a copy, thus not affecting the original variable in the calling function.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;API Consistency&lt;/strong&gt; &lt;br&gt;
Employing pointer receivers consistently across your API can maintain its uniformity, especially beneficial if at least one method requires a pointer receiver to mutate the struct.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why I prefer values?
&lt;/h2&gt;

&lt;p&gt;My preference for passing values over pointers is rooted in several key arguments, detailed below:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fixed-sized Types&lt;/strong&gt; &lt;br&gt;
We're considering types such as integers, floats, small structs, and arrays here. These types maintain a consistent memory footprint, often comparable to or smaller than the size of a pointer on many systems. Utilizing values for these smaller, fixed size data types is not only memory efficient but also in line with best practices for minimizing overhead.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Immutability&lt;/strong&gt; &lt;br&gt;
Passing by value ensures the receiving function gets an independent copy of the data. This characteristic is crucial for avoiding unintended side effects; any modifications made within the function remain localized, preserving the original data outside the function's scope. The call-by-value mechanism thus serves as a protective barrier, ensuring data integrity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Performance Benefits of Passing Values&lt;/strong&gt; &lt;br&gt;
Despite potential concerns, passing values is frequently fast and, in many scenarios, can outpace the use of pointers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Efficiency in Data Copying:&lt;/strong&gt; For small-sized data, the act of copying can be more efficient than dealing with pointer indirection. The direct access to data mitigates the delays introduced by additional layers of memory dereferencing typical of pointer usage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduced Garbage Collector Workload:&lt;/strong&gt; Directly passing values lessens the burden on the garbage collector. With fewer pointers to track, the garbage collection process becomes more streamlined, contributing to overall performance gains.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory Locality:&lt;/strong&gt; Data passed by value is often stored contiguously in memory. This arrangement favors the processor's caching mechanisms, allowing faster data access due to improved cache hits. The spatial locality of value-based data access lends itself to significant performance enhancements, particularly in computational-heavy operations.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In summary, pointers in Go provide direct memory address access, facilitating data manipulation and optimization not just for efficiency but also for programming pattern flexibility. Unlike pointer arithmetic in C, Go's approach to pointers is designed to enhance safety and maintainability, crucially supported by its built-in garbage collection system. While the understanding and use of pointers versus values in Go can deeply impact application performance and safety, Go's design inherently guides developers towards making informed and effective choices. Through mechanisms like escape analysis, Go ensures optimal memory management, balancing the power of pointers with the safety and simplicity of value semantics. This careful balance allows developers to craft robust, efficient Go applications with a clear understanding of when and how to use pointers to their advantage.&lt;/p&gt;

</description>
      <category>go</category>
      <category>memory</category>
      <category>programming</category>
      <category>gc</category>
    </item>
    <item>
      <title>Building Robust REST Client with Quarkus: A Comprehensive Guide</title>
      <dc:creator>Ivelin Yanev</dc:creator>
      <pubDate>Fri, 27 Dec 2024 17:00:59 +0000</pubDate>
      <link>https://dev.to/yanev/building-robust-rest-clients-with-quarkus-a-comprehensive-guide-51h8</link>
      <guid>https://dev.to/yanev/building-robust-rest-clients-with-quarkus-a-comprehensive-guide-51h8</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When building modern microservices applications, consuming external REST services is a common requirement. Quarkus provides powerful built-in support for REST clients, offering both traditional Java EE approaches and modern MicroProfile solutions. In this article, we'll focus on the MicroProfile REST Client approach, as it provides a more modern, maintainable, and feature-rich way to build REST clients in Quarkus applications. This approach aligns better with microservices architectures and provides superior integration with other MicroProfile features like Config, Fault Tolerance, and Metrics.&lt;/p&gt;

&lt;p&gt;It offers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Declarative, interface-based client definitions;&lt;/li&gt;
&lt;li&gt;Type-safe request/response handling;&lt;/li&gt;
&lt;li&gt;Automatic client generation;&lt;/li&gt;
&lt;li&gt;Built-in integration with MicroProfile Configl&lt;/li&gt;
&lt;li&gt;Better integration with CDI and other MicroProfile features;&lt;/li&gt;
&lt;li&gt;Simplified error handling and resilience pattern.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fyjfr23yey5ksnq3cuuon.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fyjfr23yey5ksnq3cuuon.png" alt="Rest Client" width="800" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Adding Required Dependencies&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight xml"&gt;&lt;code&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;io.quarkus&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;quarkus-rest-client-jackson&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;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Creating Your First REST Client&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="nd"&gt;@RegisterRestClient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;configKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"simple-api"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
     &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;SimpleRestClient&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
     &lt;span class="nd"&gt;@GET&lt;/span&gt;
     &lt;span class="nd"&gt;@Path&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/simple"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
     &lt;span class="nc"&gt;Response&lt;/span&gt; &lt;span class="nf"&gt;simple&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;/li&gt;
&lt;li&gt;&lt;p&gt;Configuration&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Configure your REST client in application.properties:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;quarkus.rest-client.simple-api.url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;http://simple-api:8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@RegisterRestClient&lt;/code&gt;: Registers the interface for CDI injection as a REST Client;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@Path&lt;/code&gt;, &lt;code&gt;@GET&lt;/code&gt;: Standard Jakarta REST annotations defining service access;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;configKey&lt;/code&gt;: Allows using a custom configuration key instead of the fully qualified interface name.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Real-World Example: Cryptocurrency API Client
&lt;/h2&gt;

&lt;p&gt;Let's build a practical example using the &lt;a href="https://docs.coincap.io/" rel="noopener noreferrer"&gt;CoinCap API&lt;/a&gt; to fetch cryptocurrency data.&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;@RegisterRestClient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;configKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"crypto-currency"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;CryptoCurrencyRestClient&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@GET&lt;/span&gt;
    &lt;span class="nd"&gt;@Path&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/assets"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;AssetData&lt;/span&gt; &lt;span class="nf"&gt;getAssets&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="nd"&gt;@GET&lt;/span&gt;
    &lt;span class="nd"&gt;@Path&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/assets/{id}/history"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;AssetHistoryData&lt;/span&gt; &lt;span class="nf"&gt;getAssetHistory&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nd"&gt;@PathParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nd"&gt;@QueryParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"interval"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;interval&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;and the record classes:&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="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;AssetData&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Crypto&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Crypto&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;rank&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;supply&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;maxSupply&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;marketCapUsd&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;volumeUsd24Hr&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;priceUsd&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;changePercent24Hr&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;vwap24Hr&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;explorer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;AssetHistoryData&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DataPoint&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;DataPoint&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
      &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;priceUsd&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
      &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
      &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;circulatingSupply&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
      &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;
  &lt;span class="o"&gt;)&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;You can easily inject and use the REST client within your Quarkus application. Implementation in a Resource:&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;@Path&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/crypto"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CryptoCurrencyResource&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;CryptoCurrencyRestClient&lt;/span&gt; &lt;span class="n"&gt;cryptoCurrencyRestClient&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;CryptoCurrencyResource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@RestClient&lt;/span&gt; &lt;span class="nc"&gt;CryptoCurrencyRestClient&lt;/span&gt; &lt;span class="n"&gt;cryptoCurrencyRestClient&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;cryptoCurrencyRestClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cryptoCurrencyRestClient&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@GET&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;AssetData&lt;/span&gt; &lt;span class="nf"&gt;getCurrency&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;cryptoCurrencyRestClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAssets&lt;/span&gt;&lt;span class="o"&gt;();&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;
  
  
  Advanced Features
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Fault Tolerance
&lt;/h2&gt;

&lt;p&gt;In distributed systems, network calls can fail. Quarkus provides robust fault tolerance features through SmallRye Fault Tolerance:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Add the dependency:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight xml"&gt;&lt;code&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;io.quarkus&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;quarkus-smallrye-fault-tolerance&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;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement fault tolerance patterns:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Retry Pattern
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;@Retry&lt;/code&gt; annotation provides sophisticated retry capabilities when service calls fail. Here are the key configuration options:&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;@GET&lt;/span&gt;
&lt;span class="nd"&gt;@Path&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/assets/{id}/history"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Retry&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;maxRetries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;                    &lt;span class="c1"&gt;// Maximum number of retry attempts&lt;/span&gt;
    &lt;span class="n"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;                       &lt;span class="c1"&gt;// Delay between retries in milliseconds&lt;/span&gt;
    &lt;span class="n"&gt;jitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;                      &lt;span class="c1"&gt;// Random variation added to delay&lt;/span&gt;
    &lt;span class="n"&gt;retryOn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;                        &lt;span class="c1"&gt;// Specify which exceptions trigger retry&lt;/span&gt;
        &lt;span class="nc"&gt;IOException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;TimeoutException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;
    &lt;span class="o"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;abortOn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;                        &lt;span class="c1"&gt;// Exceptions that immediately abort retry&lt;/span&gt;
        &lt;span class="nc"&gt;SecurityException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;
    &lt;span class="o"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;maxDuration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;                 &lt;span class="c1"&gt;// Maximum duration for all retry attempts&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;AssetHistoryData&lt;/span&gt; &lt;span class="nf"&gt;getAssetHistory&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="nd"&gt;@PathParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nd"&gt;@QueryParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"interval"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;interval&lt;/span&gt;
&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also implement exponential backoff:&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;@Retry&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;maxRetries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;delayUnit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ChronoUnit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;MILLIS&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;exponential&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;                 &lt;span class="c1"&gt;// Enable exponential backoff&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Fallback Pattern
&lt;/h2&gt;

&lt;p&gt;Fallbacks provide alternative behavior when all retry attempts fail. You can implement fallbacks in multiple ways:&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;@GET&lt;/span&gt;
&lt;span class="nd"&gt;@Path&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/assets"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Retry&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maxRetries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Fallback&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fallbackMethod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"getDefaultAssets"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;AssetData&lt;/span&gt; &lt;span class="nf"&gt;getAssets&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Fallback method must have the same return type and parameters&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;AssetData&lt;/span&gt; &lt;span class="nf"&gt;getDefaultAssets&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;warn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Using fallback method for getAssets"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;AssetData&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentTimeMillis&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"FALLBACK"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&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;
  
  
  Circuit Breaker Pattern
&lt;/h2&gt;

&lt;p&gt;The Circuit Breaker pattern prevents cascade failures in distributed systems. Here's a detailed configuration:&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;@GET&lt;/span&gt;
&lt;span class="nd"&gt;@Path&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/assets"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@CircuitBreaker&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;requestVolumeThreshold&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;// Minimum requests before CB can trip&lt;/span&gt;
    &lt;span class="n"&gt;failureRatio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;               &lt;span class="c1"&gt;// Failure ratio to trip CB (50%)&lt;/span&gt;
    &lt;span class="n"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;                     &lt;span class="c1"&gt;// Time CB stays open before half-open&lt;/span&gt;
    &lt;span class="n"&gt;successThreshold&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;             &lt;span class="c1"&gt;// Successes needed to close CB&lt;/span&gt;
    &lt;span class="n"&gt;failOn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;                        &lt;span class="c1"&gt;// Exceptions counted as failures&lt;/span&gt;
        &lt;span class="nc"&gt;IOException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;TimeoutException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;
    &lt;span class="o"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;skipOn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;                        &lt;span class="c1"&gt;// Exceptions not counted as failures&lt;/span&gt;
        &lt;span class="nc"&gt;BusinessException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Fallback&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fallbackMethod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"getDefaultAssets"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// Combine with fallback&lt;/span&gt;
&lt;span class="nc"&gt;AssetData&lt;/span&gt; &lt;span class="nf"&gt;getAssets&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Circuit Breaker States:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CLOSED&lt;/strong&gt;: Normal operation, calls pass through&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OPEN&lt;/strong&gt;: Calls fail fast without executing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HALF-OPEN&lt;/strong&gt;: Limited calls allowed to test service recovery&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Dynamic Base URL Configuration
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;@Url&lt;/code&gt; annotation provides flexible runtime URL configuration:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Basic Usage:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt; &lt;span class="nd"&gt;@GET&lt;/span&gt;
 &lt;span class="nd"&gt;@Path&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/assets"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
 &lt;span class="nc"&gt;AssetData&lt;/span&gt; &lt;span class="nf"&gt;getAssets&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Url&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
 &lt;span class="c1"&gt;// Usage in code&lt;/span&gt;
 &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAssets&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://alternate-api.example.com/v2"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Combining with Path Parameters:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt; &lt;span class="nd"&gt;@GET&lt;/span&gt;
 &lt;span class="nd"&gt;@Path&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/assets/{id}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
 &lt;span class="nc"&gt;AssetData&lt;/span&gt; &lt;span class="nf"&gt;getAssetById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Url&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;baseUrl&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;@PathParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
 &lt;span class="c1"&gt;// Usage&lt;/span&gt;
 &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAssetById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://api-backup.example.com"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"bitcoin"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;URL Priority:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt; &lt;span class="c1"&gt;// Configuration priority (highest to lowest):&lt;/span&gt;
 &lt;span class="c1"&gt;// 1. @Url parameter&lt;/span&gt;
 &lt;span class="c1"&gt;// 2. Programmatic configuration&lt;/span&gt;
 &lt;span class="c1"&gt;// 3. application.properties&lt;/span&gt;
 &lt;span class="c1"&gt;// 4. Default URL (if specified in @RegisterRestClient)&lt;/span&gt;

 &lt;span class="nd"&gt;@RegisterRestClient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;baseUri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://default.api.example.com"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
 &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;DynamicRestClient&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@GET&lt;/span&gt;
    &lt;span class="nd"&gt;@Path&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/resource"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
     &lt;span class="nc"&gt;Response&lt;/span&gt; &lt;span class="nf"&gt;getResource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Url&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;url&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;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Custom Headers Management
&lt;/h2&gt;

&lt;p&gt;Header management is crucial for authentication, tracking, and protocol compliance:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Static Headers&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@RegisterRestClient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;configKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"api-client"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@ClientHeaderParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"API-Version"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1.0"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@ClientHeaderParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Client-ID"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"${app.client.id}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ApiClient&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
   &lt;span class="nd"&gt;@GET&lt;/span&gt;
   &lt;span class="nd"&gt;@Path&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/data"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
   &lt;span class="nc"&gt;Response&lt;/span&gt; &lt;span class="nf"&gt;getData&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;/li&gt;
&lt;li&gt;&lt;p&gt;Dynamic Headers using Methods:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@RegisterRestClient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;configKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"secure-api"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;SecureApiClient&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@GET&lt;/span&gt;
    &lt;span class="nd"&gt;@Path&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/protected-resource"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@ClientHeaderParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Authorization"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"{generateAuthHeader}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@ClientHeaderParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Request-Time"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"{generateTimestamp}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;Response&lt;/span&gt; &lt;span class="nf"&gt;getProtectedResource&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;generateAuthHeader&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="s"&gt;"Bearer "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;TokenGenerator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generateToken&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;generateTimestamp&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="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valueOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentTimeMillis&lt;/span&gt;&lt;span class="o"&gt;());&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;
  
  
  Real-World Example: Integrating with Freesound API
&lt;/h2&gt;

&lt;p&gt;Let's explore a practical example of building a REST client for the &lt;a href="https://freesound.org/apiv2" rel="noopener noreferrer"&gt;Freesound API&lt;/a&gt;, which demonstrates header-based authentication and parameter handling.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Creating the REST Client Interface&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;   &lt;span class="nd"&gt;@RegisterRestClient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;configKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"free-sound"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
   &lt;span class="nd"&gt;@ClientHeaderParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Authorization"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;={&lt;/span&gt;&lt;span class="n"&gt;getAuthorizationHeader&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="s"&gt;")
   public interface FreeSoundRestClient {

      default String getAuthorizationHeader() {
        Config config = ConfigProvider.getConfig();
        String apiKey = config.getConfigValue("&lt;/span&gt;&lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sound&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="s"&gt;").getValue();
        return "&lt;/span&gt;&lt;span class="nc"&gt;Token&lt;/span&gt; &lt;span class="s"&gt;" + apiKey;
    }

    @GET
    @Path("&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="o"&gt;/{&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="s"&gt;")
    UserResponse getUsers(@PathParam("&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;username&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;/li&gt;
&lt;li&gt;
&lt;p&gt;Configuration Setup&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt; &lt;span class="c"&gt;# Base URL configuration
&lt;/span&gt; &lt;span class="py"&gt;quarkus.rest-client.free-sound.url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;https://freesound.org/apiv2&lt;/span&gt;

 &lt;span class="c"&gt;# API Key configuration
&lt;/span&gt; &lt;span class="py"&gt;free.sound.api.key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;${FREESOUND_API_KEY}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Response Data Models&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;UserResponse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;about&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;home_page&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="nc"&gt;Avatar&lt;/span&gt; &lt;span class="n"&gt;avatar&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="nc"&gt;LocalDateTime&lt;/span&gt; &lt;span class="n"&gt;date_joined&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;num_sounds&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;sounds&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;num_packs&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;packs&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;num_posts&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;num_comments&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

 &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Avatar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
  &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;small&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;medium&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;large&lt;/span&gt;
  &lt;span class="o"&gt;)&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;/li&gt;
&lt;li&gt;
&lt;p&gt;Using the Client in a Resource&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Path&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/freesound"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Produces&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MediaType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;APPLICATION_JSON&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FreeSoundResource&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;FreeSoundRestClient&lt;/span&gt; &lt;span class="n"&gt;freeSoundClient&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;FreeSoundResource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@RestClient&lt;/span&gt; &lt;span class="nc"&gt;FreeSoundRestClient&lt;/span&gt; &lt;span class="n"&gt;freeSoundClient&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;freeSoundClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;freeSoundClient&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@GET&lt;/span&gt;
&lt;span class="nd"&gt;@Path&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/users/{username}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;UserResponse&lt;/span&gt; &lt;span class="nf"&gt;getUserProfile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@PathParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;username&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;freeSoundClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUsers&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;);&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;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Quarkus REST Client provides a powerful and flexible way to consume REST services in your microservices architecture. By combining MicroProfile REST Client with Quarkus's fault tolerance features, you can build robust and reliable service communications.&lt;br&gt;
The full source code for this article is available on &lt;a href="https://github.com/iqnev/quarkus-rest-client-demo" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

</description>
      <category>quarkus</category>
      <category>microprofile</category>
      <category>rest</category>
      <category>java</category>
    </item>
    <item>
      <title>Optimizing Memory Usage in Go: Mastering Data Structure Alignment</title>
      <dc:creator>Ivelin Yanev</dc:creator>
      <pubDate>Sun, 10 Nov 2024 16:18:03 +0000</pubDate>
      <link>https://dev.to/yanev/optimizing-memory-usage-in-go-mastering-data-structure-alignment-4beb</link>
      <guid>https://dev.to/yanev/optimizing-memory-usage-in-go-mastering-data-structure-alignment-4beb</guid>
      <description>&lt;p&gt;Memory optimization is crucial for writing performant software systems. When a software has a finite amount of memory to work with, many issues can arise when that memory isn't used efficiently. That's why memory optimization is critical for better overall performance.&lt;/p&gt;

&lt;p&gt;Go inherits many of C's advantageous features, but what I notice is that a large part of people who use it do not know the full power of this language. One of the reasons may be a lack of knowledge about how it works at a low level, or a lack of experience with languages like C or C++. I mention C and C++ because the foundations of Go are pretty much built on the wonderful features of C/C++. It's no coincidence that I will quote an interview of Ken Thompson at Google I/O 2012:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;For me, the reason I was enthusiastic about Go is because just about the same time that we were starting on Go, I read (or tried to read) the C++0x proposed standard, and that was a convincer for me.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Today, we're going to talk about how we can optimize our Go program, and more specifically, how it would be good to use structs in Go. Let's first say what a structure is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A struct is a user-defined data type that groups related variables of different types under a single name.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To fully understand where the problem lies, we will mention that modern processors do not read 1 byte at a time from the memory. How the CPU fetches the data or instructions which are stored in the memory?&lt;/p&gt;

&lt;p&gt;In computer architecture, a word is a unit of data that a processor can handle in a single operation - generally the smallest addressable unit of memory. It's a fixed-size group of bits (binary digits). The word size of a processor determines its ability to handle data efficiently. Common word sizes include 8, 16, 32, and 64 bits. Some computer processor architectures support a half word, which is half the number of bits in a word, and a double word, which is two contiguous words.&lt;/p&gt;

&lt;p&gt;In nowday the most common architectures is 32 bit and 64 bit. If you have 32 bit processor then it means it can access 4 bytes at a time which means word size is 4 bytes. If you have 64 bit processor the it can access 8 bytes at time which means word size is 8 bytes.&lt;/p&gt;

&lt;p&gt;When we store the data in memory, each 32-bit data word has a unique address, as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fm7u37vl9m4nytrzuo6p1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fm7u37vl9m4nytrzuo6p1.jpg" alt="Word-Addressable Memory" width="800" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure. 1 ‑ Word-Addressable Memory&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We can read the data in memory and load it to one register using the load word (lw) instruction.&lt;/p&gt;

&lt;p&gt;After know the above theoria let's see what is the practise. For the descripte the cases with structure data structure, I will demonstrate with C languge. A struct in C is a composite data type that allows you to group multiple variables together and store them in the same block of memory. As we said early the CPU access the data depend of the givemn architecture. Every data type in C will have alignment requirements.&lt;/p&gt;

&lt;p&gt;So let's  we have the following as simple structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// structure 1&lt;/span&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;example_1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;short&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;struct1_t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="c1"&gt;// structure 2&lt;/span&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;example_2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;struct2_t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now try to calculate the size of the following structures:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Size of Structure 1 = Size of (char + short int) = 1 + 2 = 3&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Size of Structure 2 = Size of (double + int + char) = 8 + 4 + 1= 13&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The real sizes using a C program might surprise you.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;

&lt;span class="c1"&gt;// structure 1&lt;/span&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;example_1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;short&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;struct1_t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// structure 2&lt;/span&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;example_2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;struct2_t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;int&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="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"sizeof(struct1_t) = %lu&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;struct1_t&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"sizeof(struct2_t) = %lu&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;struct2_t&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sizeof&lt;span class="o"&gt;(&lt;/span&gt;struct1_t&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 4
sizeof&lt;span class="o"&gt;(&lt;/span&gt;struct2_t&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 16
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see, the size of the structures is different from those we calculated.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the reason for that?
&lt;/h2&gt;

&lt;p&gt;C and Go employ a technique known as "struct padding" to ensure data is appropriately aligned in memory, which can significantly affect performance due to hardware and architectural constraints. Data padding and alignment conform to the requirements of the system's architecture, mainly to optimize CPU access times by ensuring data boundaries align with word sizes.&lt;/p&gt;

&lt;p&gt;Let's go through an example to illustrate how Go handles padding and alignment, consider the following struct:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Employee&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;IsAdmin&lt;/span&gt;  &lt;span class="kt"&gt;bool&lt;/span&gt;
  &lt;span class="n"&gt;Id&lt;/span&gt;       &lt;span class="kt"&gt;int64&lt;/span&gt;
  &lt;span class="n"&gt;Age&lt;/span&gt;      &lt;span class="kt"&gt;int32&lt;/span&gt;
  &lt;span class="n"&gt;Salary&lt;/span&gt;   &lt;span class="kt"&gt;float32&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A bool is 1 byte, &lt;code&gt;int64&lt;/code&gt; is 8 bytes, &lt;code&gt;int32&lt;/code&gt; is 4 bytes and &lt;code&gt;float32&lt;/code&gt; is 4 bytes = 17 bytes(total).&lt;/p&gt;

&lt;p&gt;Let's validate the struct size by examining the compiled Go program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"unsafe"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Employee&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;IsAdmin&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="n"&gt;Id&lt;/span&gt;      &lt;span class="kt"&gt;int64&lt;/span&gt;
    &lt;span class="n"&gt;Age&lt;/span&gt;     &lt;span class="kt"&gt;int32&lt;/span&gt;
    &lt;span class="n"&gt;Salary&lt;/span&gt;  &lt;span class="kt"&gt;float32&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;emp&lt;/span&gt; &lt;span class="n"&gt;Employee&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Size of Employee: %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;emp&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;&lt;strong&gt;Output&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Size of Employee: 24
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reported size is 24 bytes, not 17. This discrepancy is due to memory alignment. To understand how alignment works, we need to inspect the structure and visualize the memory which it ocupate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fj2p49vwccda9jrwsy4x5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fj2p49vwccda9jrwsy4x5.jpg" alt="Unoptimized Memory Layout" width="800" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 2 - Unoptimized Memory Layout&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The struct Employee will consume 8*3 = 24 bytes. Yo see the problem now, there are a lot of empty holes in the layout of &lt;code&gt;Employee&lt;/code&gt; (those gaps created by the alignment rules are called “padding”).&lt;/p&gt;

&lt;h2&gt;
  
  
  Padding Optimization and Performance Impact
&lt;/h2&gt;

&lt;p&gt;Understanding how memory alignment and padding can affect the performance of an application is crucial. Specifically, data alignment impacts the number of CPU cycles required to access fields within a struct. This influence arises mostly from CPU cache effects, rather than raw clock cycles themselves, as cache behavior depends heavily on data locality and alignment within memory blocks.&lt;/p&gt;

&lt;p&gt;Modern CPUs fetch data from memory into a faster intermediary called cache, organized in fixed-size blocks (commonly 64 bytes). When data is well-aligned and localized within the same or fewer cache lines, the CPU can access it more quickly due to reduced cache loading operations.&lt;/p&gt;

&lt;p&gt;Consider the following Go structures to illustrate poor versus optimal alignment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Poorly aligned struct&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Misaligned&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Age&lt;/span&gt;        &lt;span class="kt"&gt;uint8&lt;/span&gt;  &lt;span class="c"&gt;// Uses 1 byte, followed by 7 bytes of padding to align the next field&lt;/span&gt;
    &lt;span class="n"&gt;PassportId&lt;/span&gt; &lt;span class="kt"&gt;uint64&lt;/span&gt; &lt;span class="c"&gt;// 8-byte aligned uint64 for the passport ID&lt;/span&gt;
    &lt;span class="n"&gt;Children&lt;/span&gt;   &lt;span class="kt"&gt;uint16&lt;/span&gt; &lt;span class="c"&gt;//2-byte aligned uint16&lt;/span&gt;

&lt;span class="c"&gt;// Well-aligned struct&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Aligned&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Age&lt;/span&gt;        &lt;span class="kt"&gt;uint8&lt;/span&gt;  &lt;span class="c"&gt;// Starting with 1 byte&lt;/span&gt;
    &lt;span class="n"&gt;Children&lt;/span&gt;   &lt;span class="kt"&gt;uint16&lt;/span&gt; &lt;span class="c"&gt;// Next, 2 bytes; all these combine into a 3-byte sequence&lt;/span&gt;
    &lt;span class="n"&gt;PassportId&lt;/span&gt; &lt;span class="kt"&gt;uint64&lt;/span&gt; &lt;span class="c"&gt;// Finally, an 8-byte aligned uint64 without needing additional padding&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How Alignment Affects Performance
&lt;/h2&gt;

&lt;p&gt;CPU reads data in word-size instead of byte-size. As I described in the begining a word in a 64-bit system is 8 bytes, while a word in a 32-bit system is 4 bytes. In short, CPU reads address in the multiple of its word size. To fetch the variable passportId, our CPU takes two cycles to access the data instead of one. The first cycle will fetch memory 0 to 7 and the subsequent cycle will fetch the rest. And this is inefficient- we need of data structure alignment.By simply aligning the data, computers ensure that the &lt;code&gt;var passportId&lt;/code&gt; can be retrieved in &lt;strong&gt;ONE CPU&lt;/strong&gt; cycle.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fv9ylp4lagc6fyuw82y38.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fv9ylp4lagc6fyuw82y38.jpg" alt="Comparing Memory Access Efficiency" width="800" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 3 - Comparing Memory Access Efficiency&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Padding is the key to achieving data alignment. Padding occurs because modern CPUs are optimized to read data from memory at aligned addresses. This alignment allows the CPU to read the data in a single operation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ftg94bk160iarq1c0bt8o.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ftg94bk160iarq1c0bt8o.jpg" alt="Simply aligning the data" width="800" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 4 - Simply aligning the data&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Without padding, data may be misaligned, leading to multiple memory accesses and slower performance. Therefore, while padding might waste some memory, it ensures that your program runs efficiently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Padding Optimization Strategies
&lt;/h2&gt;

&lt;p&gt;Aligned struct consumes lesser memory simply because it possesses a better struct fields order compared to Misaligned. Because of padding, two 13 bytes data structures turn out to be 16 bytes and 24 bytes respectively. Hence, you save up extra memory by simply reordering your struct fields.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F189cza90dbwnjp8e3e8y.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F189cza90dbwnjp8e3e8y.jpg" alt="Optimizing Field Order" width="800" height="187"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 5 - Optimizing Field Order&lt;/p&gt;

&lt;p&gt;Improperly aligned data can slow performance as the CPU might need multiple cycles to access misaligned fields. Conversely, correctly aligned data minimizes cache line loads, which is crucial for performance, especially in systems where memory speed is a bottleneck.&lt;/p&gt;

&lt;p&gt;Let’s do a simple benchmark to prove it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;AlignedArr&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;Aligned&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;MisalignedArr&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;Misaligned&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;sampleSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1000&lt;/span&gt;
    &lt;span class="n"&gt;AlignedArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="n"&gt;Aligned&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sampleSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;MisalignedArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="n"&gt;Misaligned&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sampleSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;sampleSize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;AlignedArr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Aligned&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Age&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;uint8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="m"&gt;256&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Siblings&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;uint16&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Children&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;uint64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
        &lt;span class="n"&gt;MisalignedArr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Misaligned&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Age&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;uint8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="m"&gt;256&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;PassportId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;uint64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Children&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;uint16&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&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="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;traverseAligned&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;uint16&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;arbitraryNum&lt;/span&gt; &lt;span class="kt"&gt;uint16&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;AlignedArr&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;arbitraryNum&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Siblings&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;arbitraryNum&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;traverseMisaligned&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;uint16&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;arbitraryNum&lt;/span&gt; &lt;span class="kt"&gt;uint16&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;MisalignedArr&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;arbitraryNum&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Children&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;arbitraryNum&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;BenchmarkTraverseAligned&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;traverseAligned&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="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;BenchmarkTraverseMisaligned&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;traverseMisaligned&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;&lt;strong&gt;Output&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-bench&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
goos: linux
goarch: amd64
pkg: test-project
cpu: 11th Gen Intel&lt;span class="o"&gt;(&lt;/span&gt;R&lt;span class="o"&gt;)&lt;/span&gt; Core&lt;span class="o"&gt;(&lt;/span&gt;TM&lt;span class="o"&gt;)&lt;/span&gt; i9-11950H @ 2.60GHz
BenchmarkTraverseAligned-16              3022234               403.7 ns/op
BenchmarkTraverseMisaligned-16           4300167               299.1 ns/op
PASS
ok      test-project    3.195s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see the traversing the Aligned indeed takes lesser time than its counterpart.&lt;/p&gt;

&lt;p&gt;Padding’s added to make sure each struct field lines up properly in memory based on its needs, like we saw earlier. But while it enables efficient access, padding can also waste space if the fields ain’t ordered well.&lt;/p&gt;

&lt;p&gt;Understanding how to properly align struct fields to minimize memory waste due to padding is important for efficient memory usage, especially in performance-critical applications. Below, I will provide an example with a poorly aligned structure and then show an optimized version of the same structure.&lt;/p&gt;

&lt;p&gt;In a poorly aligned struct, fields are ordered without considering their sizes and alignment requirements, which can lead to added padding and increased memory usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Badly aligned structure&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Active&lt;/span&gt;   &lt;span class="kt"&gt;bool&lt;/span&gt;      &lt;span class="c"&gt;// 1 byte + 7 bytes padding&lt;/span&gt;
    &lt;span class="n"&gt;Salary&lt;/span&gt;   &lt;span class="kt"&gt;float64&lt;/span&gt;   &lt;span class="c"&gt;// 8 bytes&lt;/span&gt;
    &lt;span class="n"&gt;Age&lt;/span&gt;      &lt;span class="kt"&gt;int32&lt;/span&gt;     &lt;span class="c"&gt;// 4 bytes + 4 bytes padding&lt;/span&gt;
    &lt;span class="n"&gt;Nickname&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;    &lt;span class="c"&gt;// 16 bytes (string is typically 16 bytes on a 64-bit system)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The total memory could hence be 1 (&lt;code&gt;bool&lt;/code&gt;) + 7 (padding) + 8 (&lt;code&gt;float64&lt;/code&gt;) + 4 (&lt;code&gt;int32&lt;/code&gt;) + 4 (&lt;code&gt;padding&lt;/code&gt;) + 16 (&lt;code&gt;string&lt;/code&gt;) = 40 bytes.&lt;/p&gt;

&lt;p&gt;An optimized structure arranges fields from largest to smallest size, significantly reducing or eliminating the need for additional padding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Well-aligned structure&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Salary&lt;/span&gt;   &lt;span class="kt"&gt;float64&lt;/span&gt;   &lt;span class="c"&gt;// 8 bytes&lt;/span&gt;
    &lt;span class="n"&gt;Nickname&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;    &lt;span class="c"&gt;// 16 bytes&lt;/span&gt;
    &lt;span class="n"&gt;Age&lt;/span&gt;      &lt;span class="kt"&gt;int32&lt;/span&gt;     &lt;span class="c"&gt;// 4 bytes&lt;/span&gt;
    &lt;span class="n"&gt;Active&lt;/span&gt;   &lt;span class="kt"&gt;bool&lt;/span&gt;      &lt;span class="c"&gt;// 1 byte + 3 bytes padding&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The total memory would then neatly comprise 8 (&lt;code&gt;float64&lt;/code&gt;) + 16 (&lt;code&gt;string&lt;/code&gt;) + 4 (&lt;code&gt;int32&lt;/code&gt;) + 1 (&lt;code&gt;bool&lt;/code&gt;) + 3 (&lt;code&gt;padding&lt;/code&gt;) = 32 bytes.&lt;/p&gt;

&lt;p&gt;Let's proof the above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"unsafe"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;PoorlyAlignedPerson&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Active&lt;/span&gt;   &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="n"&gt;Salary&lt;/span&gt;   &lt;span class="kt"&gt;float64&lt;/span&gt;
    &lt;span class="n"&gt;Age&lt;/span&gt;      &lt;span class="kt"&gt;int32&lt;/span&gt;
    &lt;span class="n"&gt;Nickname&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;WellAlignedPerson&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Salary&lt;/span&gt;   &lt;span class="kt"&gt;float64&lt;/span&gt;
    &lt;span class="n"&gt;Nickname&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Age&lt;/span&gt;      &lt;span class="kt"&gt;int32&lt;/span&gt;
    &lt;span class="n"&gt;Active&lt;/span&gt;   &lt;span class="kt"&gt;bool&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;poorlyAligned&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;PoorlyAlignedPerson&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;wellAligned&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;WellAlignedPerson&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Size of PoorlyAlignedPerson: %d bytes&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;poorlyAligned&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Size of WellAlignedPerson: %d bytes&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wellAligned&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;&lt;strong&gt;Output&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Size of PoorlyAlignedPerson: 40 bytes
Size of WellAlignedPerson: 32 bytes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reducing the structure size from 40 bytes to 32 bytes means a 20% reduction in memory usage per instance of Person. This can lead to considerable savings in applications where many such instances are created or stored, improving cache efficiency and potentially reducing the number of cache misses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Data alignment is a pivotal factor in optimizing memory utilization and enhancing system performance. By arranging struct data correctly, memory usage becomes not only more  efficient but also faster in terms of CPU read times, contributing significantly to overall system efficiency.&lt;/p&gt;

</description>
      <category>go</category>
      <category>programming</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>Effective Project Structuring for Microservices with Quarkus</title>
      <dc:creator>Ivelin Yanev</dc:creator>
      <pubDate>Wed, 18 Sep 2024 18:12:31 +0000</pubDate>
      <link>https://dev.to/yanev/effective-project-structuring-for-microservices-with-quarkus-1lf0</link>
      <guid>https://dev.to/yanev/effective-project-structuring-for-microservices-with-quarkus-1lf0</guid>
      <description>&lt;p&gt;In the ever-evolving landscape of software development, the adoption of microservices architecture is rapidly gaining traction due to its scalability, flexibility, and maintainability. Quarkus, as a Java-Native Kubernetes stack tailored for &lt;strong&gt;GraalVM&lt;/strong&gt; and &lt;strong&gt;HotSpot&lt;/strong&gt;, optimizes Java specifically for containers and enables it to become an effective platform for serverless, cloud, and Kubernetes environments.&lt;/p&gt;

&lt;p&gt;Key to leveraging Quarkus effectively is understanding how to structure your project correctly. Proper project structuring not only enhances the manageability of the code but also plays a crucial role in the success of deploying microservices architecture.&lt;/p&gt;

&lt;p&gt;Microservices architecture distinguishes itself by several defining characteristics that Quarkus enhances:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Small and Focused&lt;/strong&gt; - each service in a microservices architecture is designed to perform a single, well-defined task, promoting simplicity and focus. Quarkus supports this by facilitating lightweight, bootable jars and native compilations, which are ideal for specific tasks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Independent&lt;/strong&gt;- independence allows services to be developed, deployed, and even scaled without reliance on other services. Quarkus's container-first philosophy ensures that each microservice can run in its isolated environment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Loosely Coupled&lt;/strong&gt;- services communicate via well-defined APIs, reducing the dependency on internal implementations. Quarkus encourages decoupling through standards like &lt;code&gt;MicroProfile&lt;/code&gt; and &lt;code&gt;JAX-RS&lt;/code&gt;, making services interaction seamless and efficient.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scalable&lt;/strong&gt;- efficiently managing increasing workloads is crucial. Quarkus's reactive programming capabilities enable services to be responsive and scalable under varying loads.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flexible&lt;/strong&gt;- the ability to adapt to changing conditions is facilitated by the dynamic scaling and resilience features of Quarkus, supporting on-the-fly adjustments in a cloud-native environment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resilient&lt;/strong&gt;- Quarkus enhances the robustness of microservices with built-in fault tolerance and health-check capabilities, ensuring the services are resistant to failures and recover swiftly from interruptions.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Adopting Maven multi-module project structures has proven effective in managing large-scale Java applications, and Quarkus fully supports this modality. Let's detail the Maven multi-module structure:&lt;/p&gt;

&lt;p&gt;A Maven multi-module project consists of an aggregator &lt;code&gt;POM&lt;/code&gt; that orchestrates several submodules. This structure is beneficial for dividing a large application into manageable, independently deployable units that can be maintained and updated with ease. Each module typically has a focused responsibility and can be deployed independently from others.&lt;/p&gt;

&lt;p&gt;Here’s a simplified layout based on a real-world application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;parent &lt;span class="o"&gt;(&lt;/span&gt;aggregator pom.xml&lt;span class="o"&gt;)&lt;/span&gt;
├── api &lt;span class="o"&gt;(&lt;/span&gt;API interfaces and DTOs&lt;span class="o"&gt;)&lt;/span&gt;
│   ├── pom.xml
│   └── src
├── core &lt;span class="o"&gt;(&lt;/span&gt;Business logic&lt;span class="o"&gt;)&lt;/span&gt;
│   ├── pom.xml
│   └── src
├── data-access &lt;span class="o"&gt;(&lt;/span&gt;Data layer integration&lt;span class="o"&gt;)&lt;/span&gt;
│   ├── pom.xml
│   └── src
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've tailored an optimized project structure specifically for Quarkus that enhances scalability, maintainability, and coherence across diverse development teams. The design, which I originally developed in 2018, has seen several refinements to better suit evolving technological trends. Initially, the structure wasn't specifically crafted with Quarkus in mind; however, throughout its application, it has proven exceptionally compatible with Quarkus's philosophy and coding practices. Let us examine this structure as implemented in an IDE like IntelliJ IDEA - though it could be effectively adapted to any other modern IDE. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F0et8rgaae8elwpvqgdd2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F0et8rgaae8elwpvqgdd2.png" alt="Microservices Project Structure" width="674" height="648"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find the full project structure in the &lt;a href="https://github.com/iqnev/quarkus-ms-template" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Starting from the top-level, the project is divided into several modules, each with a specific role:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;api-dtos&lt;/strong&gt;- this module is crucial for de-coupling the internal representations of data from what is exposed externally through APIs. By separating Data Transfer Objects (DTOs) from domain models, the module ensures that any changes- be they in database schema or business logic- do not directly affect the clients who consume these APIs. This separation enhances API stability and versioning.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;commons&lt;/strong&gt;- this utility module acts as a repository for shared logic, constants, and helpers that are used across multiple other modules in the project. Centralizing common functionalities in this way reduces duplication and fosters consistency throughout the application. It’s particularly helpful for storing utilities like data format converters, standard validators, or common business rules.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;configuration&lt;/strong&gt;- configuration management is streamlined in this module, which consolidates all configuration settings for the entire application in one place, simplifying access and management. This central repository of configurations ensures that settings are consistently applied and managed, simplifying environment shifts (such as from development to production) and minimizing the potential for errors due to misconfiguration. Beyond simple configuration files, this module is also the ideal location for defining custom managed beans that are essential across the application, such as &lt;code&gt;ObjectMapper&lt;/code&gt; for JSON serializing and deserializing, custom deserializers, and other specialized beans.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;db-entities&lt;/strong&gt;- dedicated exclusively to database interactions, this module encapsulates all ORM classes or database schemas, ensuring they are separated from the business logic and API layers. Segregating entities in this manner helps maintain clean architecture principles by decoupling data access mechanisms from business rules processing, hence promoting a cleaner and more traceable codebase.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;services&lt;/strong&gt;- here lies the core business logic, encapsulated in service classes that operate on domain models and use &lt;code&gt;db-entities&lt;/code&gt; for data persistence. Each service focuses on a specific business task, enhancing modularity and reusability. This separation also aids in isolating business operations from direct client interactions, which are handled by controller classes in other modules, thus adhering to the single responsibility principle.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;resources&lt;/strong&gt;- amid some debate, this module was named to reflect its alignment with &lt;a href="https://jakarta.ee/specifications/restful-ws/3.0/jakarta-restful-ws-spec-3.0#resource-classes" rel="noopener noreferrer"&gt;JAX-RS&lt;/a&gt;, where classes annotated with &lt;code&gt;JAX-RS&lt;/code&gt; are referred to as resources. This module handles the creation of REST endpoints, acting as the communication layer that interfaces with external clients. The name 'resources' was chosen over alternatives like 'rest' or 'controllers' to emphasize standardization and adherence to established RESTful principles as described in the Red Hat resource for building REST APIs with Quarkus. By aligning with standard terminology, the project aims to be intuitive for developers familiar with &lt;code&gt;JAX-RS&lt;/code&gt; and REST conventions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;application&lt;/strong&gt;- serves as an umbrella module that brings all the pieces together, ensuring they are correctly wired and ready to deploy.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each of these modules plays a strategic role tailored to foster ease of maintenance, scalability, and robustness in a Cloud-Native microservice environment using Quarkus.&lt;/p&gt;

&lt;p&gt;The above structure is based on the following Architecture layers which is mentioned in the &lt;a href="https://developers.redhat.com/articles/2022/02/03/build-rest-api-ground-quarkus-20#architecture_layers__resource__service__and_repository" rel="noopener noreferrer"&gt;RedHat resources&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fmovz4ekkz0f6w8my8vtk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fmovz4ekkz0f6w8my8vtk.png" alt="Architecture layers: Resource, service and repository" width="800" height="276"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Much Abstraction is Too Much
&lt;/h2&gt;

&lt;p&gt;When discussing project structures, a common question arises about the need for the layered approach I previously described. Here, I evoke the words of David J. Wheeler:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;All problems in computer science can be solved by another level of indirection, except for the problem of too many layers of indirection.&lt;/em&gt; - [David J. Wheeler from The C++ Programming Language 4th edition.]&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>java</category>
      <category>quarkus</category>
      <category>microservices</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Mastering Data Routing in Apache Camel: Leveraging the Splitter Pattern</title>
      <dc:creator>Ivelin Yanev</dc:creator>
      <pubDate>Sun, 15 Sep 2024 07:05:23 +0000</pubDate>
      <link>https://dev.to/yanev/mastering-data-routing-in-apache-camel-leveraging-the-splitter-pattern-3g5</link>
      <guid>https://dev.to/yanev/mastering-data-routing-in-apache-camel-leveraging-the-splitter-pattern-3g5</guid>
      <description>&lt;p&gt;Hello again! In my upcoming articles, I plan to explore several key patterns provided by Apache Camel that are invaluable for your ETL processes. This current article focuses on the Splitter Enterprise Integration Pattern (EIP).&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;Messages passed to integration applications often arrive in a format that is less than ideal for immediate processing. Frequently, these are composite messages containing multiple elements, each requiring individual processing. This is where the Splitter pattern proves beneficial by dividing incoming messages into a sequence of more manageable messages.&lt;/p&gt;

&lt;p&gt;The diagram below (&lt;strong&gt;Figure 1&lt;/strong&gt;) illustrates the simplicity of the Splitter pattern- it takes a single message and splits it into multiple distinct messages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fcsb8cpp4p0hg0mvg084h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fcsb8cpp4p0hg0mvg084h.png" alt="Splitter pattern" width="514" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 1 – Splitter Pattern (enterpriseintegrationpatterns.com)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Splitter in Apache Camel
&lt;/h2&gt;

&lt;p&gt;Implementing the Splitter pattern in Apache Camel is straightforward. Incorporate the split method in the route definition. This method requires an expression to dictate how the message should be split.&lt;/p&gt;

&lt;p&gt;Commonly, you might need to split a &lt;strong&gt;list&lt;/strong&gt;, &lt;strong&gt;set&lt;/strong&gt;, &lt;strong&gt;map&lt;/strong&gt;, &lt;strong&gt;array&lt;/strong&gt;, or any other &lt;strong&gt;collection&lt;/strong&gt;. For such cases, use the body method to retrieve the message body before splitting.&lt;/p&gt;

&lt;p&gt;The Splitter behaves akin to a comprehensive iterator that processes each entry consecutively. The sequence diagram in (&lt;strong&gt;Figure 2&lt;/strong&gt;) offers detailed insights into this iterator's operation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fdhdxrn9vglna1yzwy0ll.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fdhdxrn9vglna1yzwy0ll.png" alt="A sequence diagram" width="390" height="915"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 2 – A sequence diagram&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Upon receiving a message, the Splitter evaluates an Expression which returns the message body. This result is then utilized to create a &lt;code&gt;java.util.Iterator&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;By default, the split method divides the message body based on its value type, as illustrated below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;java.util.Collection&lt;/code&gt;: Splits each element from the collection.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;java.util.Map&lt;/code&gt;: Splits each map entry.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Object[]&lt;/code&gt;: Splits each array element.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Iterator&lt;/code&gt;: Splits each iteration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Iterable&lt;/code&gt;: Splits each iterable component.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;String&lt;/code&gt;: Splits each string character.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Splitter then utilizes the iterator till all data is processed. Each resultant message is a copy of the original with its body replaced by the portion from the iterator.&lt;/p&gt;

&lt;p&gt;Let's explore how to employ the Splitter pattern in Apache Camel with practical examples.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 1:&lt;/strong&gt; Splitting an &lt;code&gt;ArrayList&lt;/code&gt; of &lt;code&gt;Strings&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Consider a route that splits an &lt;code&gt;ArrayList&lt;/code&gt; of &lt;code&gt;String&lt;/code&gt; and logs each element. Here's how you define this route:&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;@ApplicationScoped&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SplitterRoute&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;RouteBuilder&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&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;configure&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;from&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:split_start_1"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Before Split line ${body}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;split&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Split line ${body}"&lt;/span&gt;&lt;span class="o"&gt;);&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;Call the above route by passing an &lt;code&gt;ArrayList&lt;/code&gt; of &lt;code&gt;Strings&lt;/code&gt; as the message body:&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="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"A"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"B"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;producerTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendBody&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:split_start_1"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running the above code yields the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;2023-07-14 20:10:03,389 INFO  Before Split line &lt;span class="o"&gt;[&lt;/span&gt;A, B, C]
2023-07-14 20:10:03,391 INFO  Split line A
2023-07-14 20:10:03,392 INFO  Split line B
2023-07-14 20:10:03,392 INFO  Split line C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example 2:&lt;/strong&gt; Splitting a &lt;code&gt;String&lt;/code&gt; by Custom Delimiter&lt;/p&gt;

&lt;p&gt;In this example, we split a String using a custom delimiter &lt;code&gt;#&lt;/code&gt;:&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;@ApplicationScoped&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SplitterRoute&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;RouteBuilder&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&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;configure&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;from&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:split_start_2"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Before Split line ${body}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;split&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Split line ${body}"&lt;/span&gt;&lt;span class="o"&gt;);&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;To call the route and pass the &lt;code&gt;String&lt;/code&gt; as a message body:&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="n"&gt;producerTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendBody&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:split_start_2"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"A#B#C"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running this code, you see the following in the log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;2024-07-14 20:19:19,229 INFO  Before Split line A#B#C
2024-07-14 20:19:19,229 INFO  Split line A
2024-07-14 20:19:19,229 INFO  Split line B
2024-07-14 20:19:19,230 INFO  Split line C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These examples demonstrate the versatility of the Splitter pattern in handling various types of message formats. &lt;/p&gt;

&lt;p&gt;As you can see, the Splitter pattern is very useful when you need to split a message into multiple messages. But let's see another example where we are going to split an &lt;code&gt;Object&lt;/code&gt; by its fields. For the demo purpose, we are going to  provide the &lt;code&gt;User&lt;/code&gt; object with the &lt;code&gt;List&lt;/code&gt; of &lt;code&gt;Address&lt;/code&gt; objects.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;User&lt;/code&gt; class is:&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="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;UserDetails&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Address&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;addresses&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;and the &lt;code&gt;Address&lt;/code&gt; class is:&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="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Address&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;addressId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;address&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;The route definition is:&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;@ApplicationScoped&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SplitterRoute&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;RouteBuilder&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="nd"&gt;@Override&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;configure&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;from&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:userDetails"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"User Id: ${body.userId}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;split&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UserService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Split line ${body}"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Address&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getDetails&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UserDetails&lt;/span&gt; &lt;span class="n"&gt;userDetails&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;userDetails&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addresses&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&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;and to call the above route as pass the &lt;code&gt;User&lt;/code&gt; object as a message body:&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="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;UserDetails&lt;/span&gt; &lt;span class="n"&gt;userDetails&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;UserDetails&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"user-1"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Address&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Address 1"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Address&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Address 2"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;producerTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendBody&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:userDetails"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userDetails&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you run the above code, you will see the following output in the log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;2024-07-14 21:09:02,225 INFO  &lt;span class="o"&gt;[&lt;/span&gt;route36] &lt;span class="o"&gt;(&lt;/span&gt;Quarkus Main Thread&lt;span class="o"&gt;)&lt;/span&gt; User Id: user-1
2024-07-14 21:09:02,226 INFO  &lt;span class="o"&gt;[&lt;/span&gt;route36] &lt;span class="o"&gt;(&lt;/span&gt;Quarkus Main Thread&lt;span class="o"&gt;)&lt;/span&gt; Split line Address[addressId&lt;span class="o"&gt;=&lt;/span&gt;1, &lt;span class="nv"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Address 1]
2024-07-14 21:09:02,226 INFO  &lt;span class="o"&gt;[&lt;/span&gt;route36] &lt;span class="o"&gt;(&lt;/span&gt;Quarkus Main Thread&lt;span class="o"&gt;)&lt;/span&gt; Split line Address[addressId&lt;span class="o"&gt;=&lt;/span&gt;2, &lt;span class="nv"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Address 2]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The method component in Apache Camel is a versatile and powerful tool that allows routes to directly invoke methods on beans. This capability is particularly useful in enterprise applications where business logic needs to be cleanly encapsulated within service classes, yet seamlessly integrated within Camel routes for orchestration of data flows.&lt;/p&gt;

&lt;p&gt;The route invokes a method from the &lt;code&gt;UserService&lt;/code&gt; class. Apache Camel looks for this method in the &lt;code&gt;UserService&lt;/code&gt; class to handle how the message should be split. The method should be designed to accept the incoming message body and return a collection, such as a &lt;code&gt;List&lt;/code&gt; or &lt;code&gt;Array&lt;/code&gt;, which Camel then iterates over. Each element of the array or list becomes a new exchange in Camel, which is processed independently for the remainder of the route.&lt;/p&gt;

&lt;p&gt;By integrating dynamic splitting with conditional routing using &lt;code&gt;choice()&lt;/code&gt; and &lt;code&gt;when()&lt;/code&gt; constructs, Apache Camel provides a robust framework for bespoke data processing workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding &lt;code&gt;choice()&lt;/code&gt; and &lt;code&gt;when()&lt;/code&gt; in Apache Camel
&lt;/h2&gt;

&lt;p&gt;In Apache Camel, &lt;code&gt;choice()&lt;/code&gt; and when are powerful constructs that enable content-based routing. This paradigm mimics the &lt;code&gt;if-else&lt;/code&gt; or &lt;code&gt;switch-case&lt;/code&gt;constructs familiar in many programming languages, allowing routes to make decisions based on the content of messages.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;choice()&lt;/code&gt; construct serves as a container for one or more &lt;code&gt;when()&lt;/code&gt; clauses. Each &lt;code&gt;when()&lt;/code&gt; clause specifies a condition. When a condition evaluates to true, Apache Camel routes the message to the processing logic defined within that &lt;code&gt;when()&lt;/code&gt; block. If none of the conditions in any of the &lt;code&gt;when()&lt;/code&gt; clauses match, an optional &lt;code&gt;otherwise()&lt;/code&gt; clause can be executed, akin to an else statement in traditional programming.&lt;/p&gt;

&lt;p&gt;Detailed Example with &lt;code&gt;choice()&lt;/code&gt; and &lt;code&gt;when()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Imagine a scenario where an application processes orders and sends them to different processing streams based on their category, such as "books", "electronics", or "clothing". This setup allows for highly specialized processing for different categories of items.&lt;/p&gt;

&lt;p&gt;Here's how you might set up such a route in Apache Camel:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Route Configuration:&lt;/strong&gt; Define a route that starts from an endpoint (for example, &lt;code&gt;direct:startOrderRoute&lt;/code&gt;). This route will examine the type of order and route the message accordingly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Using &lt;code&gt;choice()&lt;/code&gt; &lt;code&gt;and when()&lt;/code&gt;:&lt;/strong&gt; Inside the route, a &lt;code&gt;choice()&lt;/code&gt; component examines the message. Based on the content, it routes the message to different endpoints using &lt;code&gt;when()&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Logging and Processing:&lt;/strong&gt; Each category has a dedicated log that records the action taken, ensuring traceability.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's a sample implementation:&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderRouteBuilder&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;RouteBuilder&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&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;configure&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;from&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:start"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;choice&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"books"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Routing to Books processing: ${body}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:books"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"electronics"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Routing to Electronics processing: ${body}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:electronics"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"clothing"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Routing to Clothing processing: ${body}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:clothing"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;otherwise&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unknown order type: ${body}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;end&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:books"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processing Books Order: ${body}"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:electronics"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processing Electronics Order: ${body}"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:clothing"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processing Clothing Order: ${body}"&lt;/span&gt;&lt;span class="o"&gt;);&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;Now you can run the route by sending different order types to the &lt;code&gt;direct:start&lt;/code&gt; endpoint:&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="n"&gt;producerTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendBody&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:startOrderRoute"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"An order for books"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and you will see the following output in the log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;2024-07-16 19:16:12,357 INFO  &lt;span class="o"&gt;[&lt;/span&gt;route5] &lt;span class="o"&gt;(&lt;/span&gt;Quarkus Main Thread&lt;span class="o"&gt;)&lt;/span&gt; Received Order: An order &lt;span class="k"&gt;for &lt;/span&gt;books
2024-07-16 19:16:12,357 INFO  &lt;span class="o"&gt;[&lt;/span&gt;route5] &lt;span class="o"&gt;(&lt;/span&gt;Quarkus Main Thread&lt;span class="o"&gt;)&lt;/span&gt; Routing to Books processing: An order &lt;span class="k"&gt;for &lt;/span&gt;books
2024-07-16 19:16:12,358 INFO  &lt;span class="o"&gt;[&lt;/span&gt;route6] &lt;span class="o"&gt;(&lt;/span&gt;Quarkus Main Thread&lt;span class="o"&gt;)&lt;/span&gt; Processing Books Order: An order &lt;span class="k"&gt;for &lt;/span&gt;books
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the message is routed to the &lt;code&gt;books&lt;/code&gt; endpoint and processed accordingly. You can test the other categories in a similar manner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Usage and Tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complex Conditions:&lt;/strong&gt; &lt;code&gt;when()&lt;/code&gt; can handle complex expressions combining multiple conditions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Using &lt;code&gt;.endChoice()&lt;/code&gt;:&lt;/strong&gt; For readability and to prevent misrouting, especially in a route with nested &lt;code&gt;.choice()&lt;/code&gt; constructs, use &lt;code&gt;.endChoice()&lt;/code&gt; to clearly indicate the end of a choice block.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flexibility:&lt;/strong&gt; This approach is highly flexible, allowing the addition of new conditions and endpoints as business requirements evolve.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The Splitter pattern stands out as a powerful tool in Apache Camel's arsenal, enabling developers to effectively handle complex, bulky data structures by breaking them down into more manageable pieces. This pattern not only simplifies data processing workflows but also enhances maintainability and scalability within integration solutions.&lt;/p&gt;

&lt;p&gt;In this article, we've explored the practical implementation of the Splitter pattern in a range of contexts - from handling lists and custom delimited strings to operating on more complex structures like Java objects. Each example showcased how Apache Camel facilitates straightforward data manipulations, making seemingly complex integration tasks much simpler.&lt;/p&gt;

&lt;p&gt;Additionally, the integration of &lt;code&gt;choice()&lt;/code&gt; and &lt;code&gt;when()&lt;/code&gt; constructs further refines the data routing capabilities in Apache Camel, offering precise control over message flow based on specific content criteria. This ability to route data conditionally mimics conventional programming logic, bringing a familiar and intuitive approach to route definitions.&lt;/p&gt;

&lt;p&gt;As businesses continue to deal with increasingly diverse and voluminous data, understanding and implementing these patterns will become crucial. The flexibility and power of Apache Camel in managing data flows allow developers to build robust, efficient data ingestion and processing pipelines that are crucial for today's data-driven applications.&lt;/p&gt;

&lt;p&gt;And last but not least, the all above examples are implemented in the Quarkus framework as using the Camel Quarkus extension.&lt;/p&gt;

</description>
      <category>java</category>
      <category>camel</category>
      <category>apache</category>
      <category>etl</category>
    </item>
    <item>
      <title>Exploring Core Features and Components of Apache Camel</title>
      <dc:creator>Ivelin Yanev</dc:creator>
      <pubDate>Sun, 01 Sep 2024 12:11:42 +0000</pubDate>
      <link>https://dev.to/yanev/exploring-core-features-and-components-of-apache-camel-2450</link>
      <guid>https://dev.to/yanev/exploring-core-features-and-components-of-apache-camel-2450</guid>
      <description>&lt;p&gt;Hello friends! In our previous discussion, we delved into the integration of Apache Camel with Quarkus, demonstrating how to craft real-world applications using Apache Camel. As we continue our series, we aim to take a deep dive into the crucial components and the intrinsic details of Apache Camel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enterprise Integration Patterns
&lt;/h2&gt;

&lt;p&gt;At its core, Apache Camel is structured around the concepts introduced in the &lt;em&gt;Enterprise Integration Patterns&lt;/em&gt; (EIP) book by Gregor Hohpe and Bobby Woolf. This book outlines numerous patterns that have become standardizations for designing and documenting robust integration solutions across enterprise applications&lt;br&gt;
or systems. Here's an overview of some pivotal patterns utilised within Apache Camel:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Aggregator&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Aggregator pattern(&lt;strong&gt;Figure 1&lt;/strong&gt;) is essential for collecting and consolidating related messages into a cohesive single message, facilitating comprehensive processing. It acts as a specialized filter, accumulating correlated messages until a complete set of data is received, at which point it publishes an aggregated output &lt;br&gt;
for further processing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fqx4hvazk69c4cra8jr9f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fqx4hvazk69c4cra8jr9f.png" alt="Aggregator pattern" width="456" height="136"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 1 – Aggregator Pattern (enterpriseintegrationpatterns.com)&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Content-Based Router&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This pattern(&lt;strong&gt;Figure 2&lt;/strong&gt;) dynamically routes messages based on their content to appropriate receivers. Routing decisions can depend on various message attributes such as field presence or specific field values.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fffm7f7lh0n6cmy9uj5fv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fffm7f7lh0n6cmy9uj5fv.png" alt="Content-Based Router pattern" width="519" height="136"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 2 – Content-Based Router pattern (enterpriseintegrationpatterns.com)&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dynamic Router&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Dynamic Router(&lt;strong&gt;Figure 3&lt;/strong&gt;) facilitates routing decisions made at runtime, adapting dynamically based on rules defined externally or through user input, supporting modern service-oriented architectures.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fldbwcoxmby54mzgosmxz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fldbwcoxmby54mzgosmxz.png" alt="Dynamic Router pattern" width="521" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 3 – Dynamic Router pattern (enterpriseintegrationpatterns.com)&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Message Filter&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A Message Filter(&lt;strong&gt;Figure 4&lt;/strong&gt;) directs messages to an output channel or discards them based on specified criteria, ensuring that only messages meeting certain conditions are processed further.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F18lrfvbra419mxbjtnui.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F18lrfvbra419mxbjtnui.png" alt="Message Filter pattern" width="584" height="119"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 4 – Message Filter pattern (enterpriseintegrationpatterns.com)&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Process Manager&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This pattern(&lt;strong&gt;Figure 5&lt;/strong&gt;) orchestrates the sequence of steps in a business process, handling both the execution order and any occurring exceptions. It underpins complex workflows where sequential processing and error management are critical.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fga8sg9i2zefmmmfsyo0l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fga8sg9i2zefmmmfsyo0l.png" alt="Process Manager pattern" width="350" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 5 – Process Manager pattern (enterpriseintegrationpatterns.com)&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Normalizer&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Normalizer pattern(&lt;strong&gt;Figure 6&lt;/strong&gt;) is a critical tool in Apache Camel that addresses the challenges of message format discrepancies among different systems. It takes incoming messages in various formats and converts them into a standardized format before further processing, ensuring consistency across the data handling pipeline. This pattern is particularly beneficial in environments where messages originate from diverse sources with varying formats.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fehve7bdpc3fdee0fyy7x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fehve7bdpc3fdee0fyy7x.png" alt="Normalizer pattern" width="645" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 6 – Normalizer pattern (enterpriseintegrationpatterns.com)&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Splitter&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Handling complex messages composed of multiple data items is streamlined by the Splitter pattern(&lt;strong&gt;Figure 7&lt;/strong&gt;). This pattern efficiently divides a compound message into its constituent elements, allowing each element to be processed independently. This is immensely useful in scenarios where different parts of a message need to be routed or processed differently based on their individual characteristics.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F4o1b9ce90xo8yey4ljms.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F4o1b9ce90xo8yey4ljms.png" alt="Splitter pattern" width="491" height="157"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 7 – Splitter pattern (enterpriseintegrationpatterns.com)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I have to mention that these are just a few of the patterns that are used in Apache Camel. There are many more patterns that are used in Apache Camel. But I consider these patterns to be the most important ones.&lt;/p&gt;
&lt;h2&gt;
  
  
  Camel Fundamentals
&lt;/h2&gt;

&lt;p&gt;At its essence, the Apache Camel framework is centered around a powerful routing engine, or more accurately, a routing-engine builder. This engine empowers developers to devise bespoke routing rules, determine which sources to accept messages from, and define how those messages should be processed and dispatched to various destinations. Apache Camel supports the definition of complex routing rules through an integration language similar to those found in intricate business processes.&lt;/p&gt;

&lt;p&gt;One of the cardinal principles of Camel is its data-agnostic nature. This flexibility is crucial as it allows developers to interact with any type of system without the strict requirement of transforming data into a predefined canonical format. The ability to handle diverse data forms seamlessly is what makes Camel a versatile tool in the toolkit of any system integrator.&lt;/p&gt;
&lt;h3&gt;
  
  
  Message
&lt;/h3&gt;

&lt;p&gt;In the realm of Apache Camel, messages are the fundamental entities that facilitate communication between systems via messaging channels. These components are illustrated in (&lt;strong&gt;Figure 8&lt;/strong&gt;). During the course of a route's execution, messages can undergo various transformations—they can be altered, duplicated, &lt;br&gt;
or entirely replaced depending on the specific needs of the process. Messages inherently flow uni-directionally from a sender to a receiver and comprise several components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Body (Payload):&lt;/strong&gt; The main content of the message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Headers:&lt;/strong&gt; Metadata associated with the message which can include keys and their respective values.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Attachments:&lt;/strong&gt; Optional files that can be sent along with the message.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ftd0otf7gv5vt2pmcwjgb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ftd0otf7gv5vt2pmcwjgb.jpg" alt="Message structure" width="800" height="855"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 8 – Apache Camel Message structure&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Messages in Apache Camel are uniquely identified by an identifier of type &lt;code&gt;java.lang.String&lt;/code&gt;. The uniqueness of this identifier is enforced by the message creator and is dependent on the protocol used, though the format itself is not standardized. For protocols lacking a unique message identification scheme, Camel employs its own ID generator.&lt;/p&gt;

&lt;p&gt;Headers in a Camel message serve as key-value pairs containing metadata such as sender identifiers, hints about content encoding, authentication data, and more. Each header name is a unique, case-insensitive string, while the value can be any object (&lt;code&gt;java.lang.Object&lt;/code&gt;), reflecting Camel's flexible handling of header types. All headers are stored within the message as a map.&lt;/p&gt;

&lt;p&gt;Additionally, messages may include optional attachments, commonly utilized in contexts involving web services and email transactions. The body of the message, also of type &lt;code&gt;java.lang.Object&lt;/code&gt;, is versatile, accommodating any form of content. This flexibility mandates that the application designer ensures content comprehensibility across different systems. To aid in this, Camel provides various mechanisms, including automatic type conversion when necessary, to transform data into a compatible format for both sender and receiver, facilitating seamless data integration across diverse environments.&lt;/p&gt;
&lt;h3&gt;
  
  
  Exchange
&lt;/h3&gt;

&lt;p&gt;In Apache Camel, an Exchange is a pivotal message container that navigates data through a Camel route. As illustrated in (&lt;strong&gt;Figure 9&lt;/strong&gt;), it encapsulates a message, supporting its transformation and processing through a series of predefined steps within a Camel route. The Exchange implements the following &lt;code&gt;org.apache.camel.Exchange&lt;/code&gt; interface.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ff0han84m6z57kc5riuf5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ff0han84m6z57kc5riuf5.png" alt="An Apache Camel exchange" width="800" height="709"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 9 – An Apache Camel exchange&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The Exchange is designed to accommodate different styles of messaging, particularly emphasizing the request-reply pattern. It is robust enough to carry information about faults or errors, should exceptions arise during the processing of a message.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Exchange ID:&lt;/strong&gt;  This is a unique identifier for the exchange, automatically generated by Camel to ensure traceability..&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Message Exchange Pattern MEP:&lt;/strong&gt; Pecifies the messaging style, either &lt;code&gt;InOnly&lt;/code&gt; or &lt;code&gt;InOut&lt;/code&gt;. For &lt;code&gt;InOnly&lt;/code&gt;, the transaction involves only the incoming message. For &lt;code&gt;InOut&lt;/code&gt;, an additional outgoing message (Out Message) exists to relay responses back to the initiator.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Exception&lt;/strong&gt; - The Exchange captures exceptions occurring during routing, centralizing error management for easy handling and mitigation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Body:&lt;/strong&gt; Each message (In and Out) contains a payload of type &lt;code&gt;java.lang.Object&lt;/code&gt;, allowing for diverse content types.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Headers:&lt;/strong&gt; Stored as a map, headers include key-value pairs associated with the message, carrying metadata such as routing cues, authentication keys, and other contextual information.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Properties:&lt;/strong&gt; Similar to headers but enduring for the entirety of the exchange, properties hold global-level data pertinent throughout the message processing lifecycle.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;In message:&lt;/strong&gt; The foundational component, this mandatory element encapsulates incoming request data from inbound channels.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Out message:&lt;/strong&gt; An optional component that exists in &lt;code&gt;InOut&lt;/code&gt; exchanges, carrying the response data to an outbound channel.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Apache Camel, an &lt;code&gt;Exchange&lt;/code&gt; is a message container which carries the data through a Camel route. It encapsulates a message and allows it to be transformed and processed across a series of processing steps defined in a Camel route. An &lt;code&gt;Exchange&lt;/code&gt; also facilitates the pattern of request-reply messaging and might carry fault or error information if exceptions occur during message processing.&lt;/p&gt;
&lt;h3&gt;
  
  
  Camel Context
&lt;/h3&gt;

&lt;p&gt;The Apache Camel Context is an essential element within Apache Camel, serving as the core framework that orchestrates the integration framework's functionality. It is where the routing rules, configurations, components, and additional integration elements converge. The Camel Context(&lt;strong&gt;Figure 10&lt;/strong&gt;) initializes, configures, and oversees the lifecycle of all components and routes it contains.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fxc1geo8dnlwdqmpisxsy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fxc1geo8dnlwdqmpisxsy.png" alt="Apache Camel context" width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 10 – Apache Camel context&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Within the Camel Context, the following critical operations are facilitated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Loading Components and Data Formats&lt;/strong&gt;: This involves the initialization and availability management of components and data formats used across various routes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configuring Routes&lt;/strong&gt;:  It provides a mechanism to define the paths that messages follow, including the rules for how messages are processed and mediated across different endpoints.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Starting and Stopping Routes&lt;/strong&gt;: The Camel Context manages the activation and deactivation of routes, ensuring these operations are performed in a thread-safe manner.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Error Handling&lt;/strong&gt;: Implements centralized error-handling mechanisms that can be utilised across all routes within the context.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Managing Resources&lt;/strong&gt;: It ensures efficient management of resources like thread pools or connections, releasing them appropriately when not required anymore.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Camel Context can be configured either programmatically or declaratively. For instance, in a Java-based setup:&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="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.apache.camel.CamelContext&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.apache.camel.impl.DefaultCamelContext&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainApp&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;CamelContext&lt;/span&gt; &lt;span class="n"&gt;camelContext&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;DefaultCamelContext&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Add routes, components, etc.&lt;/span&gt;
            &lt;span class="n"&gt;camelContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sleep&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;printStackTrace&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;camelContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stop&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
               &lt;span class="c1"&gt;// Handle exception&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&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;For environments like Quarkus, the Camel Context is typically retrieved and managed as follows:&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;@Inject&lt;/span&gt; &lt;span class="nc"&gt;CamelContext&lt;/span&gt; &lt;span class="n"&gt;context&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="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isStarted&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getRouteController&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;startRoute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"start_route"&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;When leveraging Quarkus, the Camel Context is automagically provisioned and managed:&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;@ApplicationScoped&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DemoRoute&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;RouteBuilder&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="nd"&gt;@Override&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;configure&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;from&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:start_route"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Starting route: ${routeId}, headers: ${headers}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setHeader&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"header_abc"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;constant&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"header_value"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:route_1"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:route_3"&lt;/span&gt;&lt;span class="o"&gt;);&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;h3&gt;
  
  
  Endpoints
&lt;/h3&gt;

&lt;p&gt;In Apache Camel, endpoints represent the interfaces for connecting the Camel application with external systems or services. They are the points at which routes either begin (consume) or end (produce).&lt;/p&gt;

&lt;p&gt;Some common types of endpoints include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
A Camel file endpoint can be used to read from and write to files in a directory.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// Route to read files from the directory "input" and move &lt;/span&gt;
    &lt;span class="n"&gt;processed&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="s"&gt;"output"&lt;/span&gt;
    &lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file:input?move=processed"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
   &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file:output"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
HTTP endpoints are used for integrating with HTTP services.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// Route to consume data from an HTTP service&lt;/span&gt;
    &lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"timer:foo?period=60000"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
   &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://example.com/api/data"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
   &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"log:result"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
Direct and SEDA
Both &lt;code&gt;direct&lt;/code&gt; and &lt;code&gt;seda&lt;/code&gt; are used for in-memory synchronous and asynchronous message queuing respectively within Camel.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Using direct for synchronous call&lt;/span&gt;
&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:start"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"log:info"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Routes
&lt;/h3&gt;

&lt;p&gt;Routes in Camel define the message flow between endpoints, incorporating a series of processors or transformations. They are crucial for constructing the processing logic within a Camel application.&lt;/p&gt;

&lt;p&gt;Here’s an example demonstrating a series of interconnected routes:&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;@ApplicationScoped&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DemoRoute&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;RouteBuilder&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="nd"&gt;@Override&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;configure&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;from&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:start_route"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Starting route: ${routeId}, headers: ${headers}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setHeader&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"header_abc"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;constant&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"header_value"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:route_1"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:route_3"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:route_1"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Starting route_1: ${routeId}, headers: ${headers}, thread: ${threadName}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;process&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;exchange&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
              &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getIn&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;setHeader&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"header_abc"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"UPDATED_HEADER_VALUE"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;})&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:route_2"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"direct:route_2"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Starting route_2: ${routeId}, headers: ${headers}, thread: ${threadName}"&lt;/span&gt;&lt;span class="o"&gt;);&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;Here the first route starts from the &lt;code&gt;direct:start_route&lt;/code&gt; endpoint, logs the &lt;code&gt;routeId&lt;/code&gt; and &lt;code&gt;headers&lt;/code&gt;, set the new header with key: &lt;code&gt;header_abc&lt;/code&gt;, and then forwards the message to the next route &lt;code&gt;direct:route_1&lt;/code&gt;. The second route logs the &lt;code&gt;routeId&lt;/code&gt;, &lt;code&gt;headers&lt;/code&gt;, and the thread name, and then forwards the message to the next route &lt;code&gt;direct:route_2&lt;/code&gt;. The third route logs the &lt;code&gt;routeId&lt;/code&gt;, &lt;code&gt;headers&lt;/code&gt;, and the thread name.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this detailed exploration of Apache Camel, we have traversed the core concepts and essential components that make it an indispensable tool in the realm of enterprise integration. Beginning with a thorough examination of Enterprise Integration Patterns (EIPs), we understood how Camel utilizes patterns like Aggregators, Splitters, and Normalizers to address common integration challenges effectively.&lt;/p&gt;

&lt;p&gt;Further, we delved into the architectural fundamentals of Camel, highlighting its versatile routing capabilities, flexible message model, and the pivotal role of the Camel Context in managing and orchestrating these elements. We also covered practical aspects, demonstrating how routes are defined and managed, along with a look at various endpoint types that facilitate communication with external systems.&lt;/p&gt;

</description>
      <category>java</category>
      <category>camel</category>
      <category>apache</category>
      <category>etl</category>
    </item>
    <item>
      <title>Practical Guide to Apache Camel with Quarkus: Building an ETL Application</title>
      <dc:creator>Ivelin Yanev</dc:creator>
      <pubDate>Sun, 01 Sep 2024 11:43:20 +0000</pubDate>
      <link>https://dev.to/yanev/practical-guide-to-apache-camel-with-quarkus-building-an-etl-application-2iji</link>
      <guid>https://dev.to/yanev/practical-guide-to-apache-camel-with-quarkus-building-an-etl-application-2iji</guid>
      <description>&lt;p&gt;I am excited to introduce a series of articles about Apache Camel. In this first post, rather than delving deeply into the complexities of Apache Camel, I will present a practical use case to showcase its capabilities. Specifically, you'll learn how to create a simple Extract, Transform, and Load (ETL) application between two databases using Apache Camel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction to Apache Camel - Brief Overview
&lt;/h2&gt;

&lt;p&gt;Before we dive into the practical use case, let's briefly introduce Apache Camel. Apache Camel is an open-source integration framework that leverages Enterprise Integration Patterns (EIP) to facilitate the integration of various systems.&lt;/p&gt;

&lt;p&gt;In today's world, numerous systems of different types coexist. Some may be legacy systems, while others are new. These systems often need to interact and integrate with each other, which can be challenging due to differing implementations and message formats. One solution is to write custom code to bridge these differences, but this can lead to tight coupling and maintenance difficulties.&lt;/p&gt;

&lt;p&gt;Instead, Apache Camel offers an additional layer to mediate the differences between systems, resulting in loose coupling and easier maintenance. Camel uses an API (or declarative Java Domain Specific Language) to configure routing and mediation rules based on EIP.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enterprise Integration Patterns (EIP)
&lt;/h3&gt;

&lt;p&gt;To understand Apache Camel, it's important to grasp "Enterprise Integration Patterns" (EIP). The book "Enterprise Integration Patterns" describes a set of patterns for designing large, component-based systems where components can run in the same process or on different machines. The key idea is that systems should be message-oriented, with components communicating via messages. The patterns provide a toolkit for implementing these communications (&lt;strong&gt;Figure 1&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fvzn1j5e7igvbh68qrjj6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fvzn1j5e7igvbh68qrjj6.jpg" alt="Basic Elements of an Integration Solution" width="800" height="442"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 1 – Basic Elements of an Integration Solution (enterpriseintegrationpatterns.com)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Terminologies in Apache Camel
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;EndPoint:&lt;/strong&gt; An endpoint is a channel through which messages are sent and received. It serves as the interface between a component and the outside world.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Message:&lt;/strong&gt; A message is a data structure used for communication between systems, consisting of a header and a body. The header contains metadata, and the body contains the actual data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Channel:&lt;/strong&gt; A channel connects two endpoints, facilitating the sending and receiving of messages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Router:&lt;/strong&gt; A router directs messages from one endpoint to another, determining the message path.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Translator:&lt;/strong&gt; A translator converts messages from one format to another.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I consider to stop here for now about the introduction to Apache Camel. Now let's show you how to create a simple ETL application between two databases using Apache Camel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem Statement
&lt;/h3&gt;

&lt;p&gt;Let's assume we have a highly loaded system where one critical component is the database. At some point, we need to deal with this data outside of the usual operational cases - training ML models, generating exports, graphs, or we simply need some part of the data. Of course, this would burden our operational database even more, and for this purpose, it would be optimal to have a mechanism with which we can extract the necessary data, transform it into the form we need, and store it in another database - other  than the operational one. With this strategy, we solve the problems of excessive potential overloading of our operational base. Moreover, with such a mechanism, we can perform this operation at a time when our system is not too loaded (e.g., nighttime).&lt;/p&gt;

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

&lt;p&gt;The solution is shown in the diagram below (&lt;strong&gt;Figure 2&lt;/strong&gt;). We will use Apache Camel to create a simple ETL application between two databases. The application will extract data from a source database, transform it, and load it into a target database. We can introduce different strategies to implement this solution, focusing on how to extract the data from the source database. I assume that the criteria for selecting the data will be based on the modification date of the record. This strategy provides an opportunity to extract the data that has been modified, too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ff37n5kjtu5x2rlqoc85q.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ff37n5kjtu5x2rlqoc85q.jpg" alt="Syncing Data Between Two Databases Using Apache Camel" width="800" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 2 – Syncing Data Between Two Databases Using Apache Camel&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Source and target databases will have the following table structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;            &lt;span class="nb"&gt;serial&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt;      &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;password&lt;/span&gt;      &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt;         &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;created_at&lt;/span&gt;    &lt;span class="nb"&gt;timestamp&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()::&lt;/span&gt;&lt;span class="nb"&gt;timestamp&lt;/span&gt; &lt;span class="k"&gt;without&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt; &lt;span class="k"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;last_modified&lt;/span&gt; &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()::&lt;/span&gt;&lt;span class="nb"&gt;timestamp&lt;/span&gt; &lt;span class="k"&gt;without&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt; &lt;span class="k"&gt;zone&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the target database, we'll transform the username to uppercase before inserting it.&lt;/p&gt;

&lt;p&gt;We'll use Camel Quarkus extensions for various Camel components. Specifically, we'll use the Camel SQL component to interact with the databases. The SQL component supports performing SQL queries, inserts, updates, and deletes.&lt;/p&gt;

&lt;p&gt;First, create a class that extends &lt;code&gt;RouteBuilder&lt;/code&gt; and override the &lt;code&gt;configure&lt;/code&gt; method:&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;@ApplicationScoped&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserRoute&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;RouteBuilder&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&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;configure&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="c1"&gt;// your code here&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;The used of &lt;code&gt;@ApplicationScoped&lt;/code&gt; annotation is not mandatory here, but I prefer to indicate that the class is a CDI bean and should be managed by the CDI container.&lt;/p&gt;

&lt;p&gt;As I mentioned above, we will use the Camel SQL component to interact with the databases. We need to configure the Camel SQL component to connect to the source and target databases. We will use the Quarkus Agroal extension to configure the data sources. The Agroal extension provides a connection pool for the data sources. We will configure the data sources in the &lt;code&gt;application.properties&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="c"&gt;#
# Source Database Configuration
&lt;/span&gt;&lt;span class="py"&gt;quarkus.datasource.source_db.db-kind&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;postgresql&lt;/span&gt;
&lt;span class="py"&gt;quarkus.datasource.source_db.jdbc.url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;jdbc:postgresql://localhost:5001/demo&lt;/span&gt;
&lt;span class="py"&gt;quarkus.datasource.source_db.username&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;
&lt;span class="py"&gt;quarkus.datasource.source_db.password&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;password1&lt;/span&gt;
&lt;span class="c"&gt;#
#
# Target Database Configuration
&lt;/span&gt;&lt;span class="py"&gt;quarkus.datasource.target_db.db-kind&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;postgresql&lt;/span&gt;
&lt;span class="py"&gt;quarkus.datasource.target_db.jdbc.url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;jdbc:postgresql://localhost:6001/demo&lt;/span&gt;
&lt;span class="py"&gt;quarkus.datasource.target_db.username&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;
&lt;span class="py"&gt;quarkus.datasource.target_db.password&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;password1&lt;/span&gt;
&lt;span class="c"&gt;#
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can configure the Camel SQL component to connect to the source and target databases. We will use the &lt;code&gt;sql&lt;/code&gt; component to create a SQL endpoint for the source and target databases.&lt;/p&gt;

&lt;p&gt;The SQL component uses the following endpoint URI notation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=#&lt;/span&gt; &lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="k"&gt;options&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But we need mechanism to run the operation automatically. We will use the &lt;code&gt;timer&lt;/code&gt; component to trigger the ETL process every seconds. The &lt;code&gt;timer&lt;/code&gt; component is used to generate message exchanges when a timer fires. The timer component uses the following endpoint URI notation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;timer:name[?options]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our route we use configuration as follows:&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="n"&gt;from&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"timer://userSync?delay={{etl.timer.delay}}&amp;amp;period={{etl.timer.period}}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;{{etl.timer.delay}}&lt;/code&gt; and &lt;code&gt;{{etl.timer.period}}&lt;/code&gt; are the configuration values that we will define in the &lt;code&gt;application.properties&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;etl.timer.period&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;10000&lt;/span&gt;
&lt;span class="py"&gt;etl.timer.delay&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;1000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to transform the data before inserting it into the target database, we need to provide our translator:&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="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;process&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exchange&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&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;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getIn&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getBody&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&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;String&lt;/span&gt; &lt;span class="n"&gt;userName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"username"&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;String&lt;/span&gt; &lt;span class="n"&gt;userNameToUpperCase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toUpperCase&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"User name: {} converted to upper case: {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userNameToUpperCase&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userNameToUpperCase&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;The &lt;code&gt;Processor&lt;/code&gt; interface is used to implement consumers of message exchanges or to implement a Message Translator and other use-cases.&lt;/p&gt;

&lt;p&gt;And voila, we have a simple ETL application between two databases using Apache Camel. &lt;/p&gt;

&lt;p&gt;When you run the application, you should see the following output in the logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2024-06-09 13:15:49,257 INFO  [route1] (Camel (camel-1) thread #1 - timer://userSync) Extracting Max last_modified value from source database
2024-06-09 13:15:49,258 INFO  [route1] (Camel (camel-1) thread #1 - timer://userSync) No record found in target database
2024-06-09 13:15:49,258 INFO  [route2] (Camel (camel-1) thread #1 - timer://userSync) The last_modified from source DB: 
2024-06-09 13:15:49,274 INFO  [route2] (Camel (camel-1) thread #1 - timer://userSync) Extracting records from source database
2024-06-09 13:15:49,277 INFO  [org.iqn.cam.rou.UserRoute] (Camel (camel-1) thread #1 - timer://userSync) User name: john_doe converted to upper case: JOHN_DOE
2024-06-09 13:15:49,282 INFO  [org.iqn.cam.rou.UserRoute] (Camel (camel-1) thread #1 - timer://userSync) User name: jane_smith converted to upper case: JANE_SMITH
2024-06-09 13:15:49,283 INFO  [org.iqn.cam.rou.UserRoute] (Camel (camel-1) thread #1 - timer://userSync) User name: alice_miller converted to upper case: ALICE_MILLER

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

&lt;/div&gt;



&lt;p&gt;You can find the full source code of the application in the &lt;a href="https://github.com/iqnev/quarkus-camel-sync-db" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;With this setup, we've created a simple ETL application using Apache Camel that extracts data from a source database, transforms it, and loads it into a target database. This approach helps reduce the load on the operational database and allows us to perform data extraction during off-peak times.&lt;/p&gt;

</description>
      <category>java</category>
      <category>camel</category>
      <category>apache</category>
      <category>etl</category>
    </item>
  </channel>
</rss>
