<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Buhake Sindi</title>
    <description>The latest articles on Forem by Buhake Sindi (@theelitegentleman).</description>
    <link>https://forem.com/theelitegentleman</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%2F421505%2F13e31809-738a-47ee-aad5-846fbd5cae56.jpg</url>
      <title>Forem: Buhake Sindi</title>
      <link>https://forem.com/theelitegentleman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/theelitegentleman"/>
    <language>en</language>
    <item>
      <title>Bring AI into your Jakarta EE apps with LangChain4J-CDI</title>
      <dc:creator>Buhake Sindi</dc:creator>
      <pubDate>Sat, 24 Jan 2026 19:48:49 +0000</pubDate>
      <link>https://forem.com/theelitegentleman/bring-ai-into-your-jakarta-ee-apps-with-langchain4j-cdi-ib6</link>
      <guid>https://forem.com/theelitegentleman/bring-ai-into-your-jakarta-ee-apps-with-langchain4j-cdi-ib6</guid>
      <description>&lt;p&gt;&lt;strong&gt;Goal&lt;/strong&gt;: This article will demonstrate how to add AI features to a Jakarta EE / MicroProfile application using &lt;strong&gt;LangChain4J‑CDI&lt;/strong&gt;, with simple to implement examples that runs on Payara, WildFly, Open Liberty, Helidon, Quarkus or any CDI 4.x compatible runtime.&lt;br&gt;
&lt;em&gt;Note: This is an updated article to the one published on the &lt;a href="https://javapro.io/2025/10/28/04-2025-java-25-special-edition/" rel="noopener noreferrer"&gt;JAVAPRO's magazine - "04-2025 | Java 25 - Special Edition"&lt;/a&gt;. Since the release of LangChain4J-CDI version 1.0.0, there's been minor changes, but the fundamental architecture and usage of the library is the same.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What is LangChain4J-CDI?
&lt;/h2&gt;

&lt;p&gt;Langchain4J is a Java library that simplifies the integration of AI and LLMs easier, and with their feature of AI services it provides a declarative and type-safe API for developers to define interfaces that represent AI services, abstracting away the complexities of direct LLM communication&lt;/p&gt;

&lt;p&gt;LangChain4J‑CDI is a CDI extension that wires &lt;strong&gt;LangChain4J&lt;/strong&gt; components (chat models, embedding models, memories, retrievers, tools) into your application using familiar Jakarta annotations and &lt;strong&gt;MicroProfile Config&lt;/strong&gt;. You declare an AI service interface and the extension generates and registers a CDI bean that you can inject anywhere (CDI-managed beans, REST resources, EJBs, Schedulers, etc.).&lt;/p&gt;

&lt;p&gt;With these key benefits that LangChain4J-CDI provides, enterprise developers will benefit from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Declarative integration&lt;/strong&gt; using CDI annotations. LangChain4J AI services interface annotated with &lt;code&gt;@RegisterAIService&lt;/code&gt; annotation can be injected as CDI beans.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexible component configuration&lt;/strong&gt;: LangChain4J-CDI config utilizes Microprofile Config to configure various LangChain4J components as config parameters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visibility and observability&lt;/strong&gt;: Observe your LLM input and output AI metrics using observability (Microprofile Telemetry) and service resiliency with Microprofile Fault Tolerance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Portability&lt;/strong&gt;: works across Jakarta EE/Microprofile compliant application servers and frameworks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;Key features&lt;/strong&gt; provided by Langchain4J Microprofile:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Build with &lt;strong&gt;CDI at its core&lt;/strong&gt;. With &lt;code&gt;@RegisterAIService&lt;/code&gt; annotation annotated on a Lanchain4J AI service interface, the AI service proxy becomes CDI discoverable bean ready for injection. LangChain4J-CDI provides 2 CDI service extensions that developers can choose from in order to make their AI service CDI discoverable: CDI portable extension or CDI Build Compatible Extension (introduced in CDI 4.0 and higher).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Langchain4J Microprofile config&lt;/strong&gt;: Developers can benefit from the power of Microprofile Config to build fundamental elements of LangChain4J such as &lt;code&gt;ChatModel&lt;/code&gt;/&lt;code&gt;StreamingChatModel&lt;/code&gt;, &lt;code&gt;ChatMessage&lt;/code&gt;, &lt;code&gt;ChatMemory&lt;/code&gt;, &lt;code&gt;ContentRetriever&lt;/code&gt;, &lt;code&gt;ToolProvider&lt;/code&gt;(useful for Model Context Protocol, MCP), and more, without requiring developers to write builders to generate such elements.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Langchain4J Microprofile Fault Tolerance&lt;/strong&gt;: Leveraging the power of Microprofile Fault Tolerance resilience and policies on your existing Lanchain4J AI services (such as &lt;code&gt;@Retry&lt;/code&gt;, &lt;code&gt;@Timeout&lt;/code&gt;, &lt;code&gt;@RateLimit&lt;/code&gt;, &lt;code&gt;@Fallback&lt;/code&gt;, etc).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Langchain4J Microprofile Telemetry&lt;/strong&gt;: When enabled, developers can observer their LLM metrics (that follows the &lt;a href="https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-metrics/" rel="noopener noreferrer"&gt;Semantic Conventions for GenAI Metrics&lt;/a&gt;), through Open Telemetry.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;**Please note:&lt;/em&gt;* Langchain4J-CDI is a module developed by the Microprofile members, initially called SmallRye-LLM. It has since been donated to Langchain. The SmallRye-LLM repo on GitHub has been retired.*&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting started with LangChain4J-CDI
&lt;/h2&gt;

&lt;p&gt;Langchain4J-CDI provides a &lt;a href="https://github.com/langchain4j/langchain4j-cdi/tree/main/examples" rel="noopener noreferrer"&gt;working example&lt;/a&gt; on building a conversational AI agent for a car booking system. This demonstration is inspired by the insightful &lt;a href="https://youtu.be/BD1MSLbs9KE?si=yBeR8-3IJUYMWd8v" rel="noopener noreferrer"&gt;"Java meets AI" talk from Lize Raes at Devoxx Belgium 2023&lt;/a&gt; (with further contributions from &lt;a href="http://jefrajames.fr/" rel="noopener noreferrer"&gt;Jean-François James&lt;/a&gt;. The original demo is from &lt;a href="https://www.linkedin.com/in/dmytro-liubarskyi/" rel="noopener noreferrer"&gt;Dmytro Liubarskyi&lt;/a&gt;). Developers can view how the same example are implemented on popular Jakarta EE 10 application servers. &lt;/p&gt;

&lt;p&gt;Before we begin, we'll assume that you are familiar with the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java development.&lt;/li&gt;
&lt;li&gt;Basic knowledge of Maven.&lt;/li&gt;
&lt;li&gt;Basic knowledge of LangChain4J. Lize Raes has written a brilliant article on building an hands-on AI agent with Langchain4J &lt;a href="https://javapro.io/2025/04/23/build-ai-apps-and-agents-in-java-hands-on-with-langchain4j/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We're using OpenLiberty as application server of choice (you can browse the &lt;code&gt;examples/liberty-car-booking&lt;/code&gt; example from the example link provided above) but you can use any Jakarta EE / Microprofile compliant application server that you're comfortable with (see the examples of other application servers that runs the Car Booking example).&lt;/p&gt;

&lt;p&gt;Let's start building our own AI service, purely in Java. Please ensure that your project is Mavenized.&lt;/p&gt;

&lt;p&gt;The current release of LangChain4J-CDI, as of the time of writing, is &lt;code&gt;1.0.0&lt;/code&gt; and supports LangChain4J  core version &lt;code&gt;1.10.0&lt;/code&gt;, and the community version of &lt;code&gt;1.10.0-beta18&lt;/code&gt; (the latest at this time of writing).&lt;/p&gt;
&lt;h3&gt;
  
  
  1) Add dependencies (Maven)
&lt;/h3&gt;

&lt;p&gt;We always import the &lt;strong&gt;langchain4j-cdi-core&lt;/strong&gt; library as your &lt;code&gt;dependency&lt;/code&gt;:&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="c"&gt;&amp;lt;!-- Core CDI integration --&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.cdi&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-cdi-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.cdi.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;where &lt;em&gt;${langchain4j.cdi.version}&lt;/em&gt; is the latest LangChain4J CDI version. The LangChain4J-CDI core module automatically depends on the &lt;code&gt;langchain4j-core&lt;/code&gt; module, so you do not need to explicitly add it as a dependency (unless you want to explicitly specify your own langchain4j-core version yourself).&lt;/p&gt;

&lt;p&gt;You also need to import a LangChain4J model provider. For this example we'll use Azure Open AI, thus its LangChain4J Maven artifact ID is &lt;code&gt;langchain4j-azure-open-ai&lt;/code&gt;.&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;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-azure-open-ai&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;${dev.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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where &lt;em&gt;${dev.langchain4j.version}&lt;/em&gt; is the latest Langchain4J main version (in this case &lt;code&gt;1.10.0&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  2) Configure your model(s) with MicroProfile Config
&lt;/h3&gt;

&lt;p&gt;You can leverage Microprofile Config to define and customize Langchain4J AI service components to be used by your application.&lt;/p&gt;

&lt;p&gt;Firstly, we need to add the &lt;code&gt;langchain4j-cdi-config&lt;/code&gt; module on our Maven project.&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;dev.langchain4j.cdi&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-cdi-config&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.cdi.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;where &lt;em&gt;${langchain4j.cdi.version}&lt;/em&gt; is the latest LangChain4J CDI version. This requires that your application server supports Microprofile Config.&lt;/p&gt;

&lt;p&gt;The Langchain4J-CDI &lt;strong&gt;class&lt;/strong&gt; configuration follow this pattern:&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="err"&gt;dev.langchain4j.cdi.plugin.&amp;lt;beanName&amp;gt;.&amp;lt;key&amp;gt;=&amp;lt;value&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;dev.langchain4j.cdi.plugin.&amp;lt;beanName&amp;gt;.class&lt;/code&gt; property is &lt;strong&gt;mandatory&lt;/strong&gt; as it tells CDI which concrete implementation of the LangChain4J AIServices component is to be assigned it to upon CDI registration.&lt;/p&gt;

&lt;p&gt;Optionally, to apply the CDI scope to each of your AI service component, set key as  &lt;strong&gt;scope&lt;/strong&gt; in your configuration. The value is the fully-qualified CDI scope annotation name (one of &lt;code&gt;@RequestScoped&lt;/code&gt;, &lt;code&gt;@ApplicationScoped&lt;/code&gt;, &lt;code&gt;@SessionScoped&lt;/code&gt;, &lt;code&gt;@Dependent&lt;/code&gt;). The default scope is &lt;code&gt;@ApplicationScoped&lt;/code&gt;.&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="err"&gt;dev.langchain4j.cdi.plugin.&amp;lt;beanName&amp;gt;&lt;/span&gt;&lt;span class="py"&gt;.scope&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;jakarta.enterprise.context.ApplicationScoped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the class builder &lt;strong&gt;config&lt;/strong&gt; configuration follow this pattern:&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="err"&gt;dev.langchain4j.cdi.plugin.&amp;lt;beanName&amp;gt;.config.&amp;lt;key&amp;gt;=&amp;lt;value&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every AI service requires (first and foremost) a &lt;code&gt;ChatModel&lt;/code&gt; as this interfaces with your LLM. Each model provider provides an implementation of the LangChain4J &lt;code&gt;ChatModel&lt;/code&gt; interface. For example, LangChain4J Azure Open AI provider provides its implementation to &lt;code&gt;ChatModel&lt;/code&gt;, &lt;code&gt;AzureOpenAiChatModel&lt;/code&gt;. Each model provider provides a &lt;code&gt;Builder&lt;/code&gt;, which is builder pattern to build their corresponding &lt;code&gt;ChatModel&lt;/code&gt; object. For  LangChain4J Azure Open AI, &lt;code&gt;AzureOpenAiChatModel.Builder&lt;/code&gt; build its &lt;code&gt;AzureOpenAiChatModel&lt;/code&gt; and the builder config properties uses its builder, where &lt;code&gt;&amp;lt;key&amp;gt;&lt;/code&gt; is the builder method of the same name, and the &lt;code&gt;&amp;lt;value&amp;gt;&lt;/code&gt; is the corresponding value that is passed to the builder's method. &lt;/p&gt;

&lt;p&gt;In our &lt;code&gt;microprofile-config.properties&lt;/code&gt; we set our &lt;code&gt;ChatModel&lt;/code&gt; as shown below:&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;dev.langchain4j.cdi.plugin.chat-model.class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;dev.langchain4j.model.azure.AzureOpenAiChatModel&lt;/span&gt;
&lt;span class="py"&gt;dev.langchain4j.cdi.plugin.chat-model.config.api-key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;${azure.openai.api.key}&lt;/span&gt;
&lt;span class="py"&gt;dev.langchain4j.cdi.plugin.chat-model.config.endpoint&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;${azure.openai.endpoint}&lt;/span&gt;
&lt;span class="py"&gt;dev.langchain4j.cdi.plugin.chat-model.config.service-version&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;2024-02-15-preview&lt;/span&gt;
&lt;span class="py"&gt;dev.langchain4j.cdi.plugin.chat-model.config.deployment-name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;${azure.openai.deployment.name}&lt;/span&gt;
&lt;span class="py"&gt;dev.langchain4j.cdi.plugin.chat-model.config.temperature&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;0.1&lt;/span&gt;
&lt;span class="py"&gt;dev.langchain4j.cdi.plugin.chat-model.config.topP&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;0.1&lt;/span&gt;
&lt;span class="py"&gt;dev.langchain4j.cdi.plugin.chat-model.config.timeout&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;PT120S&lt;/span&gt;
&lt;span class="py"&gt;dev.langchain4j.cdi.plugin.chat-model.config.max-retries&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;
&lt;span class="py"&gt;dev.langchain4j.cdi.plugin.chat-model.config.logRequestsAndResponses&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;&amp;lt;beanName&amp;gt;&lt;/code&gt; is the CDI bean name that will be assigned to the object &lt;code&gt;class&lt;/code&gt; key &lt;code&gt;dev.langchain4j.cdi.plugin.&amp;lt;beanName&amp;gt;.&amp;lt;key&amp;gt;&lt;/code&gt;. In this example, the bean name for our chat model is &lt;code&gt;chat-model&lt;/code&gt; and it's assigned to the chat model class &lt;code&gt;dev.langchain4j.model.azure.AzureOpenAiChatModel&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;All the properties found within the &lt;code&gt;langchain4j.cdi.plugin.&amp;lt;beanName&amp;gt;.config.&amp;lt;key&amp;gt;&lt;/code&gt; property, LangChain4J CDI will populate the value to its corresponding Langchain4J &lt;code&gt;ChatModel&lt;/code&gt; declared. In this case the &lt;code&gt;dev.langchain4j.model.azure.AzureOpenAiChatModel.Builder&lt;/code&gt; class (this is done for you internally).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;&amp;lt;value&amp;gt;&lt;/code&gt; builder property can follow the lowercase dashed property value that matches the camel case builder property bean.&lt;/p&gt;

&lt;p&gt;For example, should you want to log all chat request you will need to set the &lt;code&gt;logRequests&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; on the Builder. In the config, all uppercase letters can be lowered and prepended with a dash &lt;code&gt;-&lt;/code&gt;.&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;dev.langchain4j.cdi.plugin.chat-model.config.log-requests&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Is equivalent to the config property:&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;dev.langchain4j.cdi.plugin.chat-model.config.logRequests&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The config creator (internally) will identify config values that contains dashes and rework it to its camel-case property and match it to the Builder and then assign the value accordingly.&lt;/p&gt;

&lt;h3&gt;
  
  
  3) Declare an AI Service interface
&lt;/h3&gt;

&lt;p&gt;Using LangChain4J's AiServices, it allows developers the ability to plugin any of the AiServices component much more flexible. Now, we're powering the AI Services with the power of Jakarta EE CDI.&lt;/p&gt;

&lt;h4&gt;
  
  
  3.1) The @RegisterAiService annotation.
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;@RegisterAIService&lt;/code&gt; annotation is the glue that automatically applies LangChain4J AI services components to your AI services. Each annotation attribute correspond to the LangChain4J AI service component by their CDI bean name. If any of the property name is assigned as &lt;code&gt;#default&lt;/code&gt; then CDI container will find the default AI Services component (based on the component class type) that is ready for injection.&lt;/p&gt;

&lt;h4&gt;
  
  
  3.2) Your AI Service agent
&lt;/h4&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;dev.langchain4j.service.UserMessage&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;dev.langchain4j.service.SystemMessage&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;dev.langchain4j.cdi.RegisterAiService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@RegisterAIService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ApplicationScoped&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;chatLanguageModelName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"chat-model"&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;Assistant&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@SystemMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"You are a concise enterprise assistant."&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@UserMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Answer clearly: {{question}}"&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;answer&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;question&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 interface describes what we want: a &lt;code&gt;Assistant&lt;/code&gt; object with one method: &lt;code&gt;answer(String)&lt;/code&gt;. We specify a &lt;code&gt;SystemMessage&lt;/code&gt; (this is optional).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The input is a &lt;code&gt;String&lt;/code&gt;, so LangChain4J will infer that this is the &lt;code&gt;UserMessage&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  The output is a &lt;code&gt;String&lt;/code&gt;, so LangChain4J will automatically infer that this is the model output.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;@RegisterAIService.chatLanguageModelName&lt;/code&gt; property matches the &lt;code&gt;&amp;lt;beanName&amp;gt;&lt;/code&gt; value that we've specified on the config property file.&lt;/p&gt;

&lt;p&gt;The default CDI scope for your AI Service is &lt;code&gt;RequestScoped&lt;/code&gt;. You can apply an alternative CDI scope by overriding the &lt;code&gt;@RegisterAIService.scope&lt;/code&gt; property.&lt;/p&gt;

&lt;h4&gt;
  
  
  3.3) Adding Memory
&lt;/h4&gt;

&lt;p&gt;LLMs are &lt;strong&gt;stateless&lt;/strong&gt;, meaning it doesn't remember your previous conversation and context. One way that LLMs remember the conversation is to pass the previous messages and append the current message &lt;strong&gt;at every  call&lt;/strong&gt;. It's for that reason that LangChain4J provide the &lt;code&gt;ChatMemory&lt;/code&gt; component.&lt;br&gt;
A &lt;code&gt;ChatMemory&lt;/code&gt; is basically a &lt;strong&gt;list of &lt;code&gt;ChatMessages&lt;/code&gt;&lt;/strong&gt; and you can manually add the messages for every &lt;code&gt;UserMessage&lt;/code&gt; you send and every &lt;code&gt;AiMessage&lt;/code&gt; you receive back. But if you &lt;strong&gt;combine &lt;code&gt;ChatMemory&lt;/code&gt; with an &lt;code&gt;AiService&lt;/code&gt;&lt;/strong&gt;, LangChain4J will take care of updating the memory for you.&lt;/p&gt;

&lt;p&gt;Please note that adding memory eats tokens, so please monitor your usage cost. &lt;/p&gt;

&lt;p&gt;You can configure &lt;code&gt;ChatMemory&lt;/code&gt; with Microprofile Config, as follows:&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;dev.langchain4j.cdi.plugin.chat-memory.class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;dev.langchain4j.memory.chat.MessageWindowChatMemory&lt;/span&gt;
&lt;span class="py"&gt;dev.langchain4j.cdi.plugin.chat-memory.scope&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;jakarta.enterprise.context.ApplicationScoped&lt;/span&gt;
&lt;span class="py"&gt;dev.langchain4j.cdi.plugin.chat-memory.config.maxMessages&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which is equivalent to physically write the code as:&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;ChatMemory&lt;/span&gt; &lt;span class="n"&gt;chatMemory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MessageWindowChatMemory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withMaxMessages&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&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 update our existing &lt;code&gt;Assistant&lt;/code&gt; &lt;code&gt;@RegisterAIService&lt;/code&gt; to include &lt;code&gt;ChatMemory&lt;/code&gt; with &lt;code&gt;chatMemoryName&lt;/code&gt; property to bean &lt;code&gt;chat-memory&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;@RegisterAIService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;chatLanguageModelName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"chat-model"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;chatMemoryName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"chat-memory"&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3.4) Adding Tools
&lt;/h4&gt;

&lt;p&gt;There are various ways to add tools for CDI registration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Either add a fully-qualified class name of class(es) that contains the LangChain4J &lt;code&gt;@Tool&lt;/code&gt; annotations on &lt;code&gt;@RegisterAIService.tools&lt;/code&gt; annotation property (the &lt;code&gt;tools&lt;/code&gt; property is type of &lt;code&gt;Class&amp;lt;?&amp;gt;[]&lt;/code&gt;), OR&lt;/li&gt;
&lt;li&gt;Specify a &lt;code&gt;@RegisterAIService.toolProviderName&lt;/code&gt; for a declared LangChain4J &lt;code&gt;ToolProvider&lt;/code&gt;. The &lt;code&gt;ToolProvider&lt;/code&gt; can be declared using the configurable properties approach.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, if you want to connect to an MCP server, LangChain4J provides an integration to any MCP server through their provided &lt;code&gt;McpToolProvider&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  3.5) RAG (Retrieval-Augmented Generation)
&lt;/h4&gt;

&lt;p&gt;LangChain4J provides the interfaces &lt;code&gt;ContentRetriever&lt;/code&gt; that you can implement. It provides 4 implementations out of the box, that you can use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;WebSearchEngineContentRetriever&lt;/strong&gt;: the LLM turns the original prompt into a web search query and a number of search results are used as context&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;SqlContentRetriever&lt;/strong&gt;: the LLM is given the database schema and turns the original prompt into SQL to retrieve information that will be used as context&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Neo4jContentRetriever&lt;/strong&gt;: the LLM is given the schema and turns the original prompt into Cypher (neo4j query) to retrieve information that will be used as context&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;EmbeddingStoreContentRetriever&lt;/strong&gt;: to retrieve relevant fragments from all documents that we provide (text, excel, images, audio, …).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The scope for building easy RAG and advance RAG using LangChain4J is beyond the scope of this article, but for this example we'll include a simple easy RAG using the configurable approach:&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;dev.langchain4j.cdi.plugin.docRagRetriever.class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever&lt;/span&gt;
&lt;span class="py"&gt;dev.langchain4j.cdi.plugin.docRagRetriever.config.embeddingStore&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;lookup:default&lt;/span&gt;
&lt;span class="py"&gt;dev.langchain4j.cdi.plugin.docRagRetriever.config.embeddingModel&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;lookup:default&lt;/span&gt;
&lt;span class="py"&gt;dev.langchain4j.cdi.plugin.docRagRetriever.config.maxResults&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;3&lt;/span&gt;
&lt;span class="py"&gt;dev.langchain4j.cdi.plugin.docRagRetriever.config.minScore&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;0.6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;lookup:default&lt;/code&gt; value will cause CDI to lookup the default &lt;code&gt;EmbeddingStore&lt;/code&gt; or &lt;code&gt;EmbeddingModel&lt;/code&gt; registered in the CDI container. Otherwise, provide a fully-qualified class name of the specified interface class type.&lt;/p&gt;

&lt;p&gt;Our &lt;code&gt;EmbeddingModel&lt;/code&gt; and &lt;code&gt;EmbeddingStore&lt;/code&gt; are CDI produced using CDI producer fields.&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;DocRagIngestor&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// Used by ContentRetriever&lt;/span&gt;
    &lt;span class="nd"&gt;@Produces&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;EmbeddingModel&lt;/span&gt; &lt;span class="n"&gt;embeddingModel&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;AllMiniLmL6V2EmbeddingModel&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Used by ContentRetriever&lt;/span&gt;
    &lt;span class="nd"&gt;@Produces&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;EmbeddingStore&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TextSegment&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;embeddingStore&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;InMemoryEmbeddingStore&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;//Code made short for brevity   &lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we register it to &lt;code&gt;@RegisterAIService&lt;/code&gt; by providing the CDI name of the &lt;code&gt;ContentRetriever&lt;/code&gt; 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;@RegisterAIService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;chatLanguageModelName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"chat-model"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;chatMemoryName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"chat-memory"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;contentRetrieverName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"docRagRetriever"&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4) Inject and use it
&lt;/h3&gt;

&lt;p&gt;Now, you can simply &lt;code&gt;@Inject&lt;/code&gt; your AI &lt;code&gt;Assistant&lt;/code&gt;. &lt;br&gt;
In this example, our &lt;code&gt;ChatResource&lt;/code&gt; RESTful Service (using Jakarta RESTful Web Service) we just inject our &lt;code&gt;Assistant&lt;/code&gt; just we normally do with any Jakarta EE CDI services:&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;jakarta.inject.Inject&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;jakarta.ws.rs.*&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;jakarta.ws.rs.core.MediaType&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.eclipse.microprofile.openapi.annotation.Operation&lt;/span&gt;&lt;span class="o"&gt;;&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;"/assist"&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;AssistantResource&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Inject&lt;/span&gt; &lt;span class="nc"&gt;Assistant&lt;/span&gt; &lt;span class="n"&gt;assistant&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@POST&lt;/span&gt;
    &lt;span class="nd"&gt;@Operation&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Ask your question to our friendly assistant."&lt;/span&gt;&lt;span class="o"&gt;)&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;"/ask"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@Consumes&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="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="nc"&gt;AnswerDto&lt;/span&gt; &lt;span class="nf"&gt;ask&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;QuestionDto&lt;/span&gt; &lt;span class="n"&gt;q&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="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AnswerDto&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;assistant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;answer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getQuestion&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;Your &lt;code&gt;AnswerDto&lt;/code&gt; and   &lt;code&gt;QuestionDto&lt;/code&gt; are standard POJO.&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;QuestionDto&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Serializable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@JsonbProperty&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;question&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;QuestionDto&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="nf"&gt;QuestionDto&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;question&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;question&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;question&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="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getQuestion&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;question&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;setQuestion&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;question&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;question&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;question&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AnswerDto&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Serializable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@JsonbProperty&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;answer&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;AnswerDto&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="nf"&gt;AnswerDto&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;answer&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;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;answer&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="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getAnswer&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;answer&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;setAnswer&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;answer&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;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;answer&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 your application by deploying it to your application server and do an HTTP POST to your RESTful endpoint.&lt;/p&gt;

&lt;h3&gt;
  
  
  4) Observability and resiliency.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  4.1) Fault Tolerance using Microprofile Fault Tolerance.
&lt;/h4&gt;

&lt;p&gt;Fault Tolerance capability was added to ensure system stability and resilience to your LangChain4J-CDI AI Services applications. With Microprofile Fault Tolerance integration, AI services can apply features like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Circuit Breaker:&lt;/strong&gt; Prevents cascading failures by quickly failing requests to services experiencing issues, allowing them to recover. Use annotation &lt;code&gt;@org.eclipse.microprofile.faulttolerance.CircuitBreaker&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Rate Limiter:&lt;/strong&gt; Controls the rate of requests to a service, preventing overload. &lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Retry:&lt;/strong&gt; Automatically retries failed operations, useful for transient errors. Use annotation &lt;code&gt;@org.eclipse.microprofile.faulttolerance.Retry&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Bulkhead:&lt;/strong&gt; Isolates failing parts of the system to prevent them from affecting others. Use annotation &lt;code&gt;@org.eclipse.microprofile.faulttolerance.Bulkhead&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Time Limiter:&lt;/strong&gt; Enforces a timeout on operations, preventing long-running or hung calls. Use annotation &lt;code&gt;@org.eclipse.microprofile.faulttolerance.Timeout&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fallback:&lt;/strong&gt; Utilize fallback mechanisms to provide alternative responses or default behavior when an AI model or external service is unavailable or returns an error. Use annotation &lt;code&gt;@org.eclipse.microprofile.faulttolerance.Fallback&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Asynchronous&lt;/strong&gt; For asynchronous processing for long-running operations. Use annotation &lt;code&gt;@org.eclipse.microprofile.faulttolerance.Asynchronous&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This example (found on &lt;code&gt;examples/liberty-car-booking&lt;/code&gt;) utilizes Microprofile Fault Tolerance to ensure resiliency.&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="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ApplicationScoped&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;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BookingService&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;chatMemoryName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"chat-ai-service-memory"&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;ChatAiService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@SystemMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""
            You are a customer support agent of a car rental company named 'Miles of Smiles'.
            Before providing information about booking or canceling a booking, you MUST always check:
            booking number, customer name and surname.
            You should not answer to any request not related to car booking or Miles of Smiles company general information.
            When a customer wants to cancel a booking, you must check his name and the Miles of Smiles cancellation policy first.
            Any cancelation request must comply with cancellation policy both for the delay and the duration.
            Today is {{current_date}}.
            """&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@Timeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unit&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;MINUTES&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="mi"&gt;5&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;abortOn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;BookingCannotBeCanceledException&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;BookingAlreadyCanceledException&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;BookingNotFoundException&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;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;"chatFallback"&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="nc"&gt;BookingCannotBeCanceledException&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;BookingAlreadyCanceledException&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;BookingNotFoundException&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;String&lt;/span&gt; &lt;span class="nf"&gt;chat&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;question&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;chatFallback&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;question&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;format&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"Sorry, I am not able to answer your request %s at the moment. Please try again later."&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;question&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;Please note that LangChain4J &lt;code&gt;ChatModel&lt;/code&gt; has a retry policy built inside the &lt;code&gt;ChatModel.chat()&lt;/code&gt; method. Thus, adding a &lt;code&gt;@Retry&lt;/code&gt; to your AI Service will add additional retry &lt;code&gt;maxRetries&lt;/code&gt; to its existing LangChain4J ChatModel &lt;code&gt;maxRetries&lt;/code&gt;. Some LangChain4J AI providers do provide the ability to configure the &lt;code&gt;maxRetries&lt;/code&gt; so we suggest to set the &lt;code&gt;ChatModel.maxRetries = 0&lt;/code&gt; in order to fully rely on Microprofile's Fault Tolerance retry mechanism.&lt;/p&gt;

&lt;p&gt;To apply fault tolerance to our AI services, we need to add the &lt;code&gt;langchain4j-cdi-fault-tolerance&lt;/code&gt; module on our Maven project.&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;dev.langchain4j.cdi.mp&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-cdi-fault-tolerance&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.cdi.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;where &lt;em&gt;${langchain4j.cdi.version}&lt;/em&gt; is the latest LangChain4J CDI version. This requires that your application server supports Microprofile Fault Tolerance.&lt;/p&gt;

&lt;h4&gt;
  
  
  4.2) Observability using Microprofile Telemetry
&lt;/h4&gt;

&lt;p&gt;LangChain4J-CDI Telemetry builds upon the observability features in the Microprofile Telemetry to provide insights into AI-related operations. LangChain4J-CDI Telemetry provides metrics and tracing capabilities for the &lt;code&gt;ChatModel&lt;/code&gt; component, based on the &lt;a href="https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-metrics/" rel="noopener noreferrer"&gt;Semantic Conventions for GenAI Metrics&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;To apply Generative AI telemetry to our AI services, we need to add the &lt;code&gt;langchain4j-cdi-telemetry&lt;/code&gt; module on our Maven project.&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;dev.langchain4j.cdi.mp&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-cdi-telemetry&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.cdi.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;where &lt;em&gt;${langchain4j.cdi.version}&lt;/em&gt; is the latest LangChain4J CDI version. This requires that your application server supports Microprofile Telemetry.&lt;/p&gt;

&lt;p&gt;The LangChain4J-CDI Telemetry provides 2 implementation of the &lt;code&gt;ChatModelListener&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;dev.langchain4j.cdi.telemetry.SpanChatModelListener&lt;/code&gt;: To represent a span for every &lt;code&gt;ChatModelRequest&lt;/code&gt; call to Generative AI model or service and a &lt;code&gt;ChatModelResponse&lt;/code&gt; based on the input prompt.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dev.langchain4j.cdi.telemetry.MetricsChatModelListener&lt;/code&gt;: To represent generative AI metrics for every &lt;code&gt;ChatModelRequest&lt;/code&gt; to the LLM, along with its &lt;code&gt;ChatModelResponse&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using the configurable properties method, we can apply the following &lt;code&gt;ChatModelListener&lt;/code&gt; to our &lt;code&gt;ChatModel&lt;/code&gt; as follows:&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="err"&gt;dev.langchain4j.cdi.plugin.&amp;lt;beanName&amp;gt;&lt;/span&gt;&lt;span class="py"&gt;.config.listeners&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;@all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The value set to &lt;code&gt;@all&lt;/code&gt; tells CDI to inject all CDI discoverable &lt;code&gt;ChatModelListener&lt;/code&gt; to the &lt;code&gt;ChatModel&lt;/code&gt; that supports listeners. &lt;/p&gt;

&lt;p&gt;Alternatively, you can specify your &lt;code&gt;ChatModel&lt;/code&gt; individually as follows:&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="err"&gt;dev.langchain4j.cdi.plugin.&amp;lt;beanName&amp;gt;&lt;/span&gt;&lt;span class="py"&gt;.config.listeners&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;dev.langchain4j.cdi.telemetry.SpanChatModelListener,dev.langchain4j.cdi.telemetry.MetricsChatModelListener&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The value are comma separated, fully qualified class name. The class must implement the &lt;code&gt;ChatModelListener&lt;/code&gt; interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Summary
&lt;/h2&gt;

&lt;p&gt;LangChain4J-CDI simplifies the process of integrating LangChain4J components into AI services. Its strong CDI integration and pluggability to MicroProfile, LangChain4J-CDI makes it an attractive choice for Jakarta EE and Microprofile developers who want to add LangChain4J AI capabilities without the usual overhead and boilerplate code. Thus, LangChain4J-CDI lets you focus on the value that generative AI can bring to your business logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Important Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;LangChain4J-CDI GitHub Repo: &lt;a href="https://github.com/langchain4j/langchain4j-cdi/" rel="noopener noreferrer"&gt;https://github.com/langchain4j/langchain4j-cdi/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;LangChain4J-CDI Examples GitHub Repo: &lt;a href="https://github.com/langchain4j/langchain4j-cdi/tree/main/examples" rel="noopener noreferrer"&gt;https://github.com/langchain4j/langchain4j-cdi/tree/main/examples&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;"Build AI Apps and Agents in Java: Hands-On with LangChain4" by Lize Raes: &lt;a href="https://javapro.io/2025/04/23/build-ai-apps-and-agents-in-java-hands-on-with-langchain4j/" rel="noopener noreferrer"&gt;https://javapro.io/2025/04/23/build-ai-apps-and-agents-in-java-hands-on-with-langchain4j/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You are welcome to contribute too. Please follow our &lt;a href="https://github.com/langchain4j/langchain4j-cdi/blob/main/CONTRIBUTING.md" rel="noopener noreferrer"&gt;contribution guidelines&lt;/a&gt; should you find bugs that you want to raise as an issue or if you have anything worth contributing to the project.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LangChain4J-CDI is a project built and maintained by the Jakarta EE/MicroProfile Working Group, under the LangChain4J umbrella.&lt;/li&gt;
&lt;li&gt;Thank you to the Microprofile AI team: Emily Jiang, Emmanuel Hugonnet, Yann Blazart, Ed Burns, Arjav Desai, Phil Chung, Luis Neto, John Clingan, Clement Escoffer, Buhake Sindi, Don Bourne, and other contributors for their immense contribution to the LangChain4J-CDI project.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>java</category>
      <category>programming</category>
    </item>
    <item>
      <title>Introducing SmallRye LLM - Injecting Langchain4J AI Service for Java developers.</title>
      <dc:creator>Buhake Sindi</dc:creator>
      <pubDate>Sat, 12 Apr 2025 06:17:02 +0000</pubDate>
      <link>https://forem.com/theelitegentleman/introducing-smallrye-llm-injecting-langchain4j-ai-service-for-jakarta-ee-and-microprofile-337d</link>
      <guid>https://forem.com/theelitegentleman/introducing-smallrye-llm-injecting-langchain4j-ai-service-for-jakarta-ee-and-microprofile-337d</guid>
      <description>&lt;p&gt;If you're a Java developer wanting to build AI agents or interface with various Large Language Models (LLM) in Java you will be familiar with &lt;a href="https://docs.langchain4j.dev/" rel="noopener noreferrer"&gt;Langchain4J&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Langchain4J (simplified)?
&lt;/h2&gt;

&lt;p&gt;LangChain4J is essentially a toolbox for Java developers that makes it easier to add advanced language AI capabilities (like chatbots or text generators) to their applications, without having to deal with a ton of complicated details.&lt;/p&gt;

&lt;p&gt;Imagine you want to build a smart app that can answer questions, generate content, or chat like a human. Normally, to talk to an artificial intelligence model (such as ChatGPT or similar), you have to learn different interfaces and deal with lots of technical stuff. LangChain4J simplifies all of that by providing a set of ready-made tools and a standard way (a unified API) to interact with various AI providers and related services—all within Java.&lt;/p&gt;

&lt;p&gt;Here’s a breakdown in simple terms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unified Interface:&lt;/strong&gt; Instead of figuring out how each AI provider works, LangChain4J gives you one common interface to work with. This means if you want to switch from one AI service to another, you usually don’t have to rewrite your entire code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Built-in Tools:&lt;/strong&gt; It comes with many handy features. For example, it can manage conversation history (so your chatbot “remembers” what was said earlier), help format and manage prompts that are sent to the AI, and even assist with tasks like searching and storing text in a way that makes it easy for the AI to work with.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Easier Integration:&lt;/strong&gt; Think of it like a connector or an adapter that plugs the powerful capabilities of modern AI models into your Java application without you needing to worry about the low-level details.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ready-to-Use Examples:&lt;/strong&gt; LangChain4J offers examples and patterns so you can quickly see how to use these AI features, whether you’re building a customer support chatbot, an educational tool, or a sophisticated search engine.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, if you’re a Java developer wanting to build an AI-powered app, LangChain4J gives you a smoother, simpler way to tap into the power of large language models without starting from scratch or getting tangled in the complex details of each individual AI service.&lt;/p&gt;

&lt;h2&gt;
  
  
  Langchain4J Ai service
&lt;/h2&gt;

&lt;p&gt;Langchain4J introduced &lt;a href="https://docs.langchain4j.dev/tutorials/ai-services/" rel="noopener noreferrer"&gt;AI services&lt;/a&gt;, a high‑level API that abstracts and automates the many steps required to integrate large language models (LLMs) into a Java application. Instead of manually constructing prompts, handling context (or chat memory), formatting outputs, and managing tools or external data retrieval, you simply define a plain Java interface that represents the “service” you want to build. The framework then creates a proxy implementation of that interface, which automatically takes care of converting your method calls into the underlying low‑level operations needed to communicate with the LLM.&lt;/p&gt;

&lt;p&gt;LangChain4J AI Services lets you sidestep all this complexity. You simply create an interface like this:&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;interface&lt;/span&gt; &lt;span class="nc"&gt;Assistant&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;@UserMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Answer this question: {{it}}"&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;chat&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;userMessage&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;Then, by calling a builder method from AI Services, you receive an object that implements this interface. When you invoke the &lt;code&gt;chat&lt;/code&gt; method, the framework automatically:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Converts your plain string into the proper LLM input (often wrapping it as a “user message”).&lt;/li&gt;
&lt;li&gt; Attaches any preset system instructions you may have provided (using annotations like &lt;code&gt;@SystemMessage&lt;/code&gt;). &lt;/li&gt;
&lt;li&gt; Optionally manages and appends the conversation history if you have configured chat memory.&lt;/li&gt;
&lt;li&gt; Sends the composed prompt to the LLM.&lt;/li&gt;
&lt;li&gt; Parses and converts the output back into a Java type (in this case, a &lt;code&gt;String&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Langchain4J in enterprise Java
&lt;/h2&gt;

&lt;p&gt;For enterprise Java developers, the idea of creating modular and loosely-coupled applications and having component frameworks to injecting interfaces based on business requirements is what makes building enterprise-ready applications in Java beautiful. &lt;/p&gt;

&lt;p&gt;There are various enterprise Java frameworks that have Langchain4J integration to build AI‑powered applications (such as chatbots and content summarizers) with minimal configuration and boilerplate code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.langchain4j.dev/tutorials/spring-boot-integration/" rel="noopener noreferrer"&gt;&lt;strong&gt;Langchain4J Spring&lt;/strong&gt;&lt;/a&gt;: integration of LangChain4J framework with the Spring ecosystem - typically Spring Boot.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.quarkiverse.io/quarkus-langchain4j/dev/index.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Quarkus Langchain4J&lt;/strong&gt;&lt;/a&gt;: integration of LangChain4J with the Quarkus framework&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These above-mentioned frameworks leverages on the their respective framework capabilites and benefits by abstracting away the complexity of LLM interactions, thus ensuring that developers write robust, clean and module AI Services.&lt;/p&gt;

&lt;p&gt;But what about Jakarta EE? If you're familiar with Jakarta  EE, it provides various frameworks where interfaces are declared and used for injection, with minimal configuration while abstracting the complexities of the framework (Jakarta Persistence, JPA comes to mind).&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Langchain4J Microprofile with SmallRye-LLM.
&lt;/h2&gt;

&lt;p&gt;Langchain4J Microprofile (currently known as &lt;a href="https://github.com/smallrye/smallrye-llm" rel="noopener noreferrer"&gt;SmallRye LLM&lt;/a&gt;, an Eclipse Microprofile Project) is a lightweight Java library that brings Langchain4J AI services capabilities into the Jakarta EE, MicroProfile and Quarkus ecosystems. This means that it leverages familiar dependency injection (CDI), configuration via MicroProfile Config, and other MicroProfile standards.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Key features&lt;/strong&gt; provided by Langchain4J Microprofile:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build with &lt;strong&gt;CDI at its core&lt;/strong&gt;. With &lt;code&gt;@RegisterAIService&lt;/code&gt; annotation annotated on a Lanchain4J AI service interface, the  AI service proxy becomes CDI discoverable bean ready for injection. There are 2 CDI service extensions provided that  developers can select to make their AI service CDI discoverable: CDI portable extension or CDI Build Compatible Extension (introduced in CDI 4.0 and higher).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Langchain4J Microprofile config&lt;/strong&gt;: Developers can benefit from the power of Microprofile Config to build fundamental elements of Langchain4J such as &lt;code&gt;ChatLanguageModel&lt;/code&gt;, &lt;code&gt;ChatMessage&lt;/code&gt;, &lt;code&gt;ChatMemory&lt;/code&gt;, &lt;code&gt;ContentRetriever&lt;/code&gt;, &lt;code&gt;ToolProvider&lt;/code&gt;(useful for Model Context Protocol, MCP), and more, without requiring developers to write builders to generate  such elements.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Langchain4J Microprofile Fault Tolerance&lt;/strong&gt;: Leveraging the power of Microprofile Fault Tolerance on your existing Lanchain4J AI services (such as &lt;code&gt;@Retry&lt;/code&gt;, &lt;code&gt;@Timeout&lt;/code&gt;, &lt;code&gt;@RateLimit&lt;/code&gt;, &lt;code&gt;Fallback&lt;/code&gt;, etc).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Langchain4J Microprofile Telemetry&lt;/strong&gt;: When enabled, developers can observer their LLM metrics (that follows the &lt;a href="https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-metrics/" rel="noopener noreferrer"&gt;Semantic Conventions for GenAI Metrics&lt;/a&gt;), through Open Telemetry.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Langchain4J Microprofile examples.
&lt;/h2&gt;

&lt;p&gt;There are &lt;a href="https://github.com/smallrye/smallrye-llm/tree/main/examples" rel="noopener noreferrer"&gt;existing examples&lt;/a&gt; provided that showcase the power of Langchain4J Microprofile feature set. These examples is based on a simplified car booking application inspired from the &lt;a href="https://www.youtube.com/watch?v=BD1MSLbs9KE" rel="noopener noreferrer"&gt;Java meets AI&lt;/a&gt; talk from &lt;a href="https://www.linkedin.com/in/lize-raes-a8a34110/" rel="noopener noreferrer"&gt;Lize Raes&lt;/a&gt; at Devoxx Belgium 2023 with additional work from &lt;a href="http://jefrajames.fr/" rel="noopener noreferrer"&gt;Jean-François James&lt;/a&gt;. The original demo is from &lt;a href="https://www.linkedin.com/in/dmytro-liubarskyi/" rel="noopener noreferrer"&gt;Dmytro Liubarskyi&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The Car Booking examples run on the following environments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GlassFish&lt;/li&gt;
&lt;li&gt;Payara&lt;/li&gt;
&lt;li&gt;Helidon (both with CDI Build Compatible Extension and CDI Portable Extension)&lt;/li&gt;
&lt;li&gt;Open Liberty&lt;/li&gt;
&lt;li&gt;Wildfly&lt;/li&gt;
&lt;li&gt;Quarkus&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Building your own Langchain4J AI Service.
&lt;/h2&gt;

&lt;p&gt;In this example, we'll build our own &lt;code&gt;Assistant&lt;/code&gt; AI Service (see code above) using Langchain4J Microprofile. Please ensure that your project is Mavenized.&lt;/p&gt;

&lt;p&gt;The current release (as of the time of writing is &lt;code&gt;0.0.4&lt;/code&gt; and supports Langchain4J version 1.0.0-beta2 (the latest at this time of writing).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Import SmallRye-LLM Portable Extension to your project. This will enable your AI service(s) to be registered for CDI injection.
&lt;/li&gt;
&lt;/ol&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.smallrye.llm&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;smallrye-llm-langchain4j-portable-extension&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;0.0.4&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;ol&gt;
&lt;li&gt;Import SmallRye-LLM Microprofile Config. This will allow us to create Langchain4J features using the power of Microprofile Config specification:
&lt;/li&gt;
&lt;/ol&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.smallrye.llm&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;smallrye-llm-langchain4j-config-mpconfig&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;0.0.4&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;ol&gt;
&lt;li&gt;Annotate your Langchain4J AI service with &lt;code&gt;@RegisterAIService&lt;/code&gt; and provide a name for your &lt;code&gt;ChatLanguageModel&lt;/code&gt; (this name will be used by CDI container, more about it later).
&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;@RegisterAIService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chatLanguageModelName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"chat-model-openai"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Assistant&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;@UserMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Answer this question: {{it}}"&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;chat&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;userMessage&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;ol&gt;
&lt;li&gt;Configure your &lt;code&gt;ChatLanguageModel&lt;/code&gt; object in your &lt;code&gt;microprofile-config.properties&lt;/code&gt; (most application provide this file inside &lt;code&gt;resources\META-INF&lt;/code&gt; folder).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For this example, we'll use the &lt;code&gt;AzureOpenAiChatModel&lt;/code&gt;. When configuring such a model, Langchain4J comes with a &lt;code&gt;Builder&lt;/code&gt; that  allows you to build a reference of &lt;code&gt;ChatLanguageModel&lt;/code&gt;, depending on the LLM that you select.&lt;/p&gt;

&lt;p&gt;A typical way one would create a &lt;code&gt;ChatLanguageModel&lt;/code&gt; programmatically (using Olllama in this case):&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;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;MODEL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"mistral"&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;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"http://localhost:11434"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;ChatLanguageModel&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OllamaChatModel&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;baseUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;BASE_URL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;modelName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&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;temperature&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.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;timeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Microprofile Config enabled, we can provide the same feature as a configuration:&lt;/p&gt;

&lt;p&gt;The configuration format for any feature relies that the Object has a &lt;code&gt;Builder&lt;/code&gt; provided by Langchain4J, otherwise it will break.&lt;/p&gt;

&lt;p&gt;The configuration to build the feature is of the following format:&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="err"&gt;smallrye.llm.plugin.&amp;lt;cdi-model-name&amp;gt;.config.&amp;lt;builder-property-method-name&amp;gt;=&amp;lt;value&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example, to create &lt;code&gt;AzureOpenAiChatModel&lt;/code&gt; using its &lt;code&gt;Builder&lt;/code&gt; internally by CDI, we've configured it as follows:&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;smallrye.llm.plugin.chat-model-openai.class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;dev.langchain4j.model.azure.AzureOpenAiChatModel&lt;/span&gt;
    &lt;span class="py"&gt;smallrye.llm.plugin.chat-model-openai.config.api-key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;${azure.openai.api.key}&lt;/span&gt;
    &lt;span class="py"&gt;smallrye.llm.plugin.chat-model-openai.config.endpoint&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;${azure.openai.endpoint}&lt;/span&gt;
    &lt;span class="py"&gt;smallrye.llm.plugin.chat-model-openai.config.service-version&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;2024-02-15-preview&lt;/span&gt;
    &lt;span class="py"&gt;smallrye.llm.plugin.chat-model-openai.config.deployment-name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;${azure.openai.deployment.name}&lt;/span&gt;
    &lt;span class="py"&gt;smallrye.llm.plugin.chat-model-openai.config.temperature&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;0.1&lt;/span&gt;
    &lt;span class="py"&gt;smallrye.llm.plugin.chat-model-openai.config.topP&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;0.1&lt;/span&gt;
    &lt;span class="py"&gt;smallrye.llm.plugin.chat-model-openai.config.timeout&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;PT120S&lt;/span&gt;
    &lt;span class="py"&gt;smallrye.llm.plugin.chat-model-openai.config.max-retries&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;
    &lt;span class="py"&gt;smallrye.llm.plugin.chat-model-openai.config.logRequestsAndResponses&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The configuration &lt;strong&gt;must&lt;/strong&gt; start with &lt;code&gt;smallrye.llm.plugin&lt;/code&gt; in order for the CDI extension to detect the Langchain4J configuration. Next we, specify a CDI name for our &lt;code&gt;ChatLanguageModel&lt;/code&gt;. In this case it's named &lt;code&gt;chat-model-openai&lt;/code&gt;. That's the same name we provided on the &lt;code&gt;@RegisterAIService&lt;/code&gt; which tells CDI that it must find the &lt;code&gt;chat-ai-openai&lt;/code&gt; &lt;code&gt;ChatLanguageModel&lt;/code&gt;and register it to Langchain4J when building &lt;code&gt;Assistant&lt;/code&gt; AI service.&lt;br&gt;
The &lt;code&gt;builder-property-method-name&lt;/code&gt; is case-sensitive (is named exactly as found on &lt;code&gt;Builder.&amp;lt;builder-property-method-name&amp;gt;(&amp;lt;value&amp;gt;)&lt;/code&gt; structure.&lt;/p&gt;

&lt;p&gt;By default, all objects configured with Microprofile config is &lt;code&gt;@ApplicationScoped&lt;/code&gt;, unless specified otherwise.&lt;/p&gt;

&lt;p&gt;And that's it! 😉&lt;/p&gt;

&lt;p&gt;Now, you can simply &lt;code&gt;@Inject&lt;/code&gt; it in your enterprise business service. Example, our &lt;code&gt;ChatResource&lt;/code&gt; RESTful Service (using Jakarta RESTful Web Service) we just inject our &lt;code&gt;Assistant&lt;/code&gt; just we normally do with any Jakarta EE CDI services:&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;"/chat"&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;ChatResource&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nd"&gt;@Inject&lt;/span&gt;
        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Assistant&lt;/span&gt; &lt;span class="n"&gt;assistant&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;@Operation&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Chat to our friendly assistant."&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;TEXT_PLAIN&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;chat&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;"message"&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;message&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;assistant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;chat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&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;Additional features: If you want to explore your LLM metrics using Microprofile Telemetry (running Open Telemetry), add the following feature to your &lt;code&gt;microprofile-config.properties&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This example enables CDI discovery to find all &lt;code&gt;ChatModelListener&lt;/code&gt; and inject them automatically:&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;smallrye.llm.plugin.chat-model.config.listeners&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;@all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or similarly, if you want to include specific &lt;code&gt;ChatModelListener&lt;/code&gt;:&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;smallrye.llm.plugin.chat-model.config.listeners&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;io.smallrye.llm.langchain4j.telemetry.SpanChatModelListener,io.smallrye.llm.langchain4j.telemetry.MetricsChatModelListener&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please visit the SmallRye-LLM examples to see all the further features that we've included.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Summary
&lt;/h2&gt;

&lt;p&gt;SmallRye LLM simplifies the process of integrating Langchain4J AI services features into your Microprofile applications. Its tight integration with MicroProfile and unified API makes it an attractive choice for Jakarta EE and Microprofile developers who want to add AI capabilities without the usual overhead and boilerplate. Thus, SmallRye LLM lets you focus on the value that generative AI can bring to your business logic.&lt;/p&gt;

</description>
      <category>java</category>
      <category>langchain4j</category>
      <category>microprofile</category>
      <category>jakartaee</category>
    </item>
    <item>
      <title>Exciting news for Java developers</title>
      <dc:creator>Buhake Sindi</dc:creator>
      <pubDate>Wed, 19 Mar 2025 19:23:36 +0000</pubDate>
      <link>https://forem.com/theelitegentleman/exciting-news-for-java-developers-37bo</link>
      <guid>https://forem.com/theelitegentleman/exciting-news-for-java-developers-37bo</guid>
      <description>&lt;p&gt;Today is the day for Java developers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JavaOne'25 has officially started (March 18 - 20, 2025) at &lt;strong&gt;Redwood Shores, CA&lt;/strong&gt;, U.S.A.&lt;/li&gt;
&lt;li&gt;Java 24 is now available. You can view all the JDK 24 features &lt;a href="https://openjdk.org/projects/jdk/24/" rel="noopener noreferrer"&gt;here&lt;/a&gt; and download it &lt;a href="https://jdk.java.net/24/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Oracle has launched &lt;a href="https://learn.java/" rel="noopener noreferrer"&gt;Learn.java&lt;/a&gt;, a place where everyone (from learners, teachers, and enthusiasts) can learn about Java and learn Java.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can watch the &lt;a href="https://www.youtube.com/watch?v=mk_2MIWxLI0" rel="noopener noreferrer"&gt;Java 24 Launch&lt;/a&gt; on the official &lt;a href="https://www.youtube.com/@java" rel="noopener noreferrer"&gt;Java YouTube&lt;/a&gt; channel.&lt;/p&gt;

&lt;p&gt;Time to start updating and happy coding! ☕&lt;/p&gt;

</description>
      <category>java</category>
    </item>
    <item>
      <title>Why Java Developers Should Choose Jakarta EE / Microprofile Framework</title>
      <dc:creator>Buhake Sindi</dc:creator>
      <pubDate>Mon, 10 Mar 2025 02:09:56 +0000</pubDate>
      <link>https://forem.com/theelitegentleman/why-java-developers-should-choose-jakarta-ee-microprofile-framework-2l2d</link>
      <guid>https://forem.com/theelitegentleman/why-java-developers-should-choose-jakarta-ee-microprofile-framework-2l2d</guid>
      <description>&lt;p&gt;Java is 30 years old (at the time of writing this post) and it's still among the &lt;a href="https://www.pluralsight.com/resources/blog/upskilling/top-programming-languages-2025" rel="noopener noreferrer"&gt;top 3 most popular programming language in the world&lt;/a&gt;. It's a language that has been easily adopted worldwide by many enterprises worldwide. This is due to the adoption of its popular ecosystems, one of which is the Enterprise Java ecosystem, Jakarta EE. &lt;/p&gt;

&lt;p&gt;Now, the barrier to entry for Java developers in building enterprise applications has never been easier than ever. With its vast offerings of specifications, stable &amp;amp; modular architecture, seamless integrations between APIs and libraries while taking full advantages of the Java SE platforms, we explore why &lt;strong&gt;Jakarta IS and should be the framework of choice&lt;/strong&gt; for Java developers and how/why it remains the popular enterprise Java framework worldwide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before we begin
&lt;/h2&gt;

&lt;p&gt;Frameworks are not new. Without frameworks, developers would have to worry on integrating with various platforms and infrastructures, apply compliant security standards, make code modular and stable and ensure that it can scale as business requirement demands grows. Ultimately, frameworks exists to let developers focus on building stable business logic while the technical glue of the application are handled within the framework code. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Jakarta EE framework.
&lt;/h2&gt;

&lt;p&gt;Jakarta EE is not new. It started around 1998 as a JPE project but it grew to become &lt;strong&gt;J2EE&lt;/strong&gt; (which introduced Servlet, JSP, EJB, to SOAP Web service, JAX-WS) and later transitioned to &lt;strong&gt;Java EE&lt;/strong&gt; (which introduced EJB 3, JPA, JSF, CDI, Bean validations, JSON-B, etc) to becoming the modern &lt;strong&gt;Jakarta EE&lt;/strong&gt; (after it migrated from Oracle to the Eclipse Foundation in 2017). I did a full presentation about the history of Java EE/Jakarta EE and you can view it &lt;a href="https://www.youtube.com/watch?v=vqRAYeacDVE" rel="noopener noreferrer"&gt;here&lt;/a&gt; (slides &lt;a href="https://www.slideshare.net/slideshow/from-legacy-to-legendary-jakarta-ees-evolution-in-the-modern-era/267184807" rel="noopener noreferrer"&gt;here&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;Thus, Jakarta EE specifies an &lt;strong&gt;open-source&lt;/strong&gt; set of Application Programming Interfaces (APIs) and a runtime environment to develop and run secure, scalable enterprise-level Java applications.&lt;/p&gt;

&lt;p&gt;This has its benefits and advantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Jakarta EE is the de-facto standard&lt;/strong&gt; with a set of specifications for building enterprise Java applications. It is well-understood and widely accepted because of its stability, portability, and backwards compatibility.&lt;/li&gt;
&lt;li&gt;Jakarta EE is &lt;strong&gt;vendor-neutral&lt;/strong&gt;, meaning multiple vendors implement Jakarta EE specifications, allowing developers to choose the best runtime based on your needs without vendor lock-in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stability and Maturity:&lt;/strong&gt; Well-established standard with a long history, ensuring reliability for building mission-critical applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Portability:&lt;/strong&gt; Applications built on Jakarta EE standards can run on different compatible application servers due to the standardized APIs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community-driven&lt;/strong&gt;: The Jakarta EE Working Group (the global community of leading technology organizations and individuals) offers flexible membership options so that organizations at all stages of development can participate. They use an &lt;strong&gt;open process&lt;/strong&gt; to make decisions and generate specifications and is always looking for &lt;strong&gt;community feedback&lt;/strong&gt; and uses it to innovate and evolve the platform.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Jakarta EE relevancy
&lt;/h2&gt;

&lt;p&gt;Jakarta EE relevancy can be seen in the adoption and/or implementation of the Jakarta EE specifications. The &lt;a href="https://jakarta.ee/compatibility/" rel="noopener noreferrer"&gt;Jakarta EE compatible products&lt;/a&gt; ensures that your Jakarta EE application runs as intended, according to its Jakarta EE specification.&lt;/p&gt;

&lt;p&gt;In addition, there are many more products, tools, and frameworks that have adopted and/or implemented some of the individual specifications from Jakarta EE. Prime Faces is a popular frontend UI component library that is built upon Jakarta Faces (previously known as JSF). Spring Framework also relies on Jakarta EE technologies, such as Servlets for their web offerings, Jakarta Persistence (previously known as JPA) as part of their Spring Data offering.&lt;/p&gt;

&lt;h2&gt;
  
  
  Designed with innovations in mind
&lt;/h2&gt;

&lt;p&gt;Jakarta EE introduces features for building modernized, simplified, and lightweight cloud-native Java applications. &lt;a href="https://microprofile.io/" rel="noopener noreferrer"&gt;Eclipse MicroProfile&lt;/a&gt; are a good example of technologies that rely on Jakarta EE for their cloud-native enterprise Java applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Specifications in Jakarta EE
&lt;/h2&gt;

&lt;p&gt;The current Jakarta EE Platform (Jakarta EE 10 Platform at the time of writing) consists of module specifications, some of which are bundled under a specific profile.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Jakarta EE Web Profile defines a profile of the Jakarta EE Platform specifically targeted at web applications. Tomcat is a famous servlet container that implements Jakarta EE Web Profile.&lt;/li&gt;
&lt;li&gt;The Jakarta EE Core Profile is a new profile of the Jakarta EE platform specifically targeted at smaller runtimes. This enables the development of modernized and lightweight Java applications and microservices. Eclipse Microprofile specifies Jakarta EE Core Profile as its dependency.&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%2Fm98rzbgvjboaijfooi2m.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%2Fm98rzbgvjboaijfooi2m.png" alt="The Jakarta EE 10 Specifications" width="800" height="841"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why choose Jakarta EE over other Java enterprise frameworks?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://blog.payara.fish/jakarta-ee-vs.-spring-boot-choosing-the-right-framework-for-your-project" rel="noopener noreferrer"&gt;Payara&lt;/a&gt; have summarized it best:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  You need standardization across a large organization

&lt;ul&gt;
&lt;li&gt;  Long-term stability is a priority&lt;/li&gt;
&lt;li&gt;  You want to avoid vendor lock-in&lt;/li&gt;
&lt;li&gt;  Your team has experience with traditional Java EE&lt;/li&gt;
&lt;li&gt;  You're working in a highly regulated environment&lt;/li&gt;
&lt;li&gt;  You need guaranteed backward compatibility.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Code example:
&lt;/h2&gt;

&lt;p&gt;Here's a simple Hello world RESTful Example, using the Jakarta RESTful Web Service specification. You don't need to add additional dependencies. Just run it using a Jakarta EE compatible product that supports REST.&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%2Fyd78w02gpgggotq5b95v.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%2Fyd78w02gpgggotq5b95v.png" alt="Hello world example with Jakarta RESTful Web Service." width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Most companies develop their enterprise applications in Java and with Jakarta EE platforms providing stability and backward-compatibility, it has become a reliant and relevant framework to use. So, whether you're a novice, intermediate or a senior Java developer and are keen to build an enterprise application, with a stable, robust and matured framework, with optimised runtimes that are Jakarta EE compatible runtimes, look no further than Jakarta EE specifications.&lt;/p&gt;

</description>
      <category>java</category>
      <category>jakartaee</category>
      <category>cloudnative</category>
      <category>microprofile</category>
    </item>
    <item>
      <title>How to run Large Language Models (LLMs) locally.</title>
      <dc:creator>Buhake Sindi</dc:creator>
      <pubDate>Fri, 07 Mar 2025 09:34:36 +0000</pubDate>
      <link>https://forem.com/theelitegentleman/how-to-run-large-language-models-llms-locally-1ngc</link>
      <guid>https://forem.com/theelitegentleman/how-to-run-large-language-models-llms-locally-1ngc</guid>
      <description>&lt;p&gt;Whether you are a developer or an AI enthusiast, you might be glad to know that you can run Large Language Models locally. &lt;/p&gt;

&lt;h2&gt;
  
  
  Benefit of running LLM locally.
&lt;/h2&gt;

&lt;p&gt;There might be various reasons to run LLMs locally:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Privacy:&lt;/strong&gt; Running LLM locally ensures that sensitive data is controlled by the user, which might be a prerequisite requirement by data privacy regulators

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Reduced Latency:&lt;/strong&gt; Since data are not send to LLMs in the cloud, the response time are generally faster (assuming you're running it on good, strong hardware) as the response time are reduced compared to its cloud-based counterpart.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost efficiency:&lt;/strong&gt; Should you have a decent hardware to run LLMs locally the cost of high usage costs are totally reduced.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;This will require a good, capable hardware with enough storage space to run LLM locally.&lt;br&gt;
If you're running it on a normal PC, you will need a GPU acceleration enabled PC to run it efficiently.&lt;/p&gt;

&lt;p&gt;I'll highlight on popular tools that allows you to run LLMs locally. I've specifically chosen tools that allows developers to run the LLM as a local server so that they can code and run their AI agents locally via APIs. They can, then, switch back to cloud-based LLMs later (by changing the endpoint and providing their API keys).&lt;/p&gt;

&lt;p&gt;For each of the tools, we'll download and play with the open-source DeepSeek R1 model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ollama with Chatbox AI client
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://ollama.com/" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt; is a lightweight tool designed to download open-source large language models (LLMs) directly on your computer. It also exposes an API to create, modify and/or provide a REST API for running and managing models too.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://ollama.com/library" rel="noopener noreferrer"&gt;Ollama library&lt;/a&gt; provides a list of models supported by Ollama.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Requirement:&lt;/strong&gt; You should have at least 8 GB of RAM available to run the 7B models, 16 GB to run the 13B models, and 32 GB to run the 33B models.&lt;br&gt;
&lt;strong&gt;Download:&lt;/strong&gt; To download Ollama on your local PC on &lt;a href="https://ollama.com/download/windows" rel="noopener noreferrer"&gt;Windows&lt;/a&gt;, &lt;a href="https://ollama.com/download/mac" rel="noopener noreferrer"&gt;MacOS&lt;/a&gt;, &lt;a href="https://ollama.com/download/linux" rel="noopener noreferrer"&gt;Linux&lt;/a&gt;.&lt;br&gt;
&lt;strong&gt;Source code:&lt;/strong&gt; &lt;a href="https://github.com/ollama/ollama" rel="noopener noreferrer"&gt;Ollama on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting started.
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Download and install the latest release of Ollama on your PC.&lt;/li&gt;
&lt;li&gt;Download and install &lt;a href="https://chatboxai.app/" rel="noopener noreferrer"&gt;Chatbox AI client&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Once Ollama is fully installed, open the &lt;code&gt;console&lt;/code&gt;, &lt;code&gt;command line&lt;/code&gt;, &lt;code&gt;PowerShell&lt;/code&gt; or &lt;code&gt;terminal&lt;/code&gt; (depending on your  operating system of choice). You will notice a white ollama "llama" logo installed on the notification tray if you're running it on Windows.&lt;/li&gt;
&lt;li&gt;Enter the command &lt;code&gt;ollama --help&lt;/code&gt; to see the available ollama commands.&lt;/li&gt;
&lt;li&gt;Go to the &lt;a href="https://ollama.com/library" rel="noopener noreferrer"&gt;Ollama library&lt;/a&gt;. Click on the model version tag (in our case &lt;code&gt;8b&lt;/code&gt;) and copy the any of the command of the model listed and paste it on your console/terminal on local machine:
&amp;gt; ollama run deepseek-r1:8b&lt;/li&gt;
&lt;li&gt;Once the download is complete, the model will be running locally. You will see the message &lt;code&gt;&amp;gt;&amp;gt;&amp;gt; Send a message (/? for help)&lt;/code&gt; showing that the model is running.
&lt;/li&gt;
&lt;li&gt;To prompt the model from the command line/console, enter your message in double quotes. Example:
&amp;gt; &amp;gt;&amp;gt;&amp;gt; "What model are you?" 
&amp;gt; &amp;lt;think&amp;gt;
&amp;gt; 
&amp;gt; &amp;lt;/think&amp;gt;
&amp;gt; 
&amp;gt; Hi! I'm DeepSeek-R1, an AI assistant independently developed by the
&amp;gt; Chinese company DeepSeek Inc. For detailed information about models
&amp;gt; and products, please refer to the official documentation.
&amp;gt; 
&amp;gt; &amp;gt;&amp;gt;&amp;gt; Send a message (/? for help)
&amp;gt; &lt;/li&gt;
&lt;li&gt;To terminate the model session on your command line/terminal, enter &lt;code&gt;/bye&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Once you're running a model locally, open Chatbox AI client.&lt;/li&gt;
&lt;li&gt;On settings (bottom left, select the &lt;code&gt;OLLAMA API&lt;/code&gt; as the "Model Provider" and click "Save". &lt;/li&gt;
&lt;li&gt;Select the &lt;code&gt;deepseek-r1:8b&lt;/code&gt;model next to the blue send button.
&lt;/li&gt;
&lt;li&gt;Now, you can chat away! (where it says "Type your question here...") 😉&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;For developers:&lt;/strong&gt; you can interface your installed LLM using an OpenAI client (base URI: &lt;code&gt;http://localhost:11434&lt;/code&gt; and model &lt;code&gt;deepseek-r1:8b&lt;/code&gt;). &lt;/p&gt;

&lt;h2&gt;
  
  
  Jan.ai 👋
&lt;/h2&gt;

&lt;p&gt;Jan is an open-source AI assistant that runs 100% offline, locally on your computer. It also uses a local API server (Cortex Server) to run an OpenAI-equivalent API locally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Requirement:&lt;/strong&gt; PC with Nvidia GPU support (for better performance).&lt;br&gt;
&lt;strong&gt;Download:&lt;/strong&gt; To download Jan.ai on your local PC on &lt;a href="https://jan.ai/download" rel="noopener noreferrer"&gt;Windows, Linux and MacOS&lt;/a&gt;.&lt;br&gt;
&lt;strong&gt;Source code:&lt;/strong&gt; &lt;a href="https://github.com/janhq/jan" rel="noopener noreferrer"&gt;Jan.ai on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting started.
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Download and install the latest release of Jan.ai on your PC.&lt;/li&gt;
&lt;li&gt;You will need to go to &lt;a href="https://huggingface.co/" rel="noopener noreferrer"&gt;HuggingFace&lt;/a&gt; to select the model GGUF (GPT-Generated Unified Format) link. In this case, we'll use &lt;code&gt;unsloth/DeepSeek-R1-GGUF&lt;/code&gt; link (&lt;a href="https://huggingface.co/unsloth/DeepSeek-R1-Distill-Llama-8B-GGUF" rel="noopener noreferrer"&gt;https://huggingface.co/unsloth/DeepSeek-R1-Distill-Llama-8B-GGUF&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Open Jan, once it is installed. In settings (⚙), select "My Models" and paste the GGUF link on the search (🔍) bar and choose the model you wish to run.&lt;/li&gt;
&lt;li&gt;Once the GGUF model download is complete, select "Thread", and select the downloaded model from the "Select a model" button.&lt;/li&gt;
&lt;li&gt;Now, you can chat away! (where it says "Ask me anything") 😉&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;For developers:&lt;/strong&gt; you can interface your installed LLM using an OpenAI client (base uri: &lt;code&gt;https://localhost:1337&lt;/code&gt;). &lt;/p&gt;

&lt;h2&gt;
  
  
  LM Studio
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://lmstudio.ai/" rel="noopener noreferrer"&gt;LM Studio&lt;/a&gt; is an open-source, free desktop application&lt;/strong&gt; designed to simplify the installation and usage of open-source Large Language Models (LLMs) locally on users' computers. The LM Studio GUI app is not open source. However LM Studio‘s CLI &lt;a href="https://github.com/lmstudio-ai/lms" rel="noopener noreferrer"&gt;&lt;code&gt;lms&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://github.com/lmstudio-ai/lmstudio-js" rel="noopener noreferrer"&gt;Core SDK&lt;/a&gt;, and our &lt;a href="https://github.com/lmstudio-ai/mlx-engine" rel="noopener noreferrer"&gt;MLX inferencing engine&lt;/a&gt; are all MIT licensed and open source. You can run any compatible Large Language Model (LLM) from Hugging Face, both in &lt;code&gt;GGUF&lt;/code&gt; (llama.cpp) format, as well as in the &lt;code&gt;MLX&lt;/code&gt; format (Mac only). You can run &lt;code&gt;GGUF&lt;/code&gt; text embedding models. Some models might not be supported, while others might be too large to run on your machine. Image generation models are not yet supported.&lt;/p&gt;

&lt;p&gt;You can also run an Open-AI like HTTP server on your local machine (localhost).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Requirement:&lt;/strong&gt; if you have 16GB of RAM, you can run the 7B or 8B parameter distilled models. If you have ~192GB+ of RAM, you can run the full 671B parameter model.&lt;br&gt;
&lt;strong&gt;Download:&lt;/strong&gt; You can download LM Studio from &lt;a href="https://lmstudio.ai/download" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting started.
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Download and install the latest release of LM Studio.&lt;/li&gt;
&lt;li&gt;Select the Discover (🔍) on the sidebar and search for &lt;code&gt;DeepSeek-R1&lt;/code&gt; on the search bar. A list of all GGUF files will be displayed (it searches from HuggingFace for you).&lt;/li&gt;
&lt;li&gt;Download the model that suits your PC requirements.&lt;/li&gt;
&lt;li&gt;Once the model is complete, go to chat (💬) icon and select your DeepSeek-R1 model (top of the chat) and start asking away! 😉&lt;/li&gt;
&lt;li&gt;For more details, you can read this blog &lt;a href="https://lmstudio.ai/blog/deepseek-r1" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;For developers:&lt;/strong&gt; you can interface your installed LLM using an OpenAI client (base URI: &lt;code&gt;http://localhost:1234/v1/&lt;/code&gt;). &lt;/p&gt;

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

&lt;p&gt;There hasn't been a better time to start playing and experiencing LLMs without worrying about data privacy and the cost implications of cloud-based LLMs. &lt;/p&gt;

&lt;p&gt;For developers and enthusiasts, using LLM locally can have practical applications, such as building AI agents, and be able to create custom/fine-tune models, all at a reduced cost.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>deepseek</category>
      <category>chatgpt</category>
    </item>
    <item>
      <title>Here's a list of South African Public APIs for all developers and enthusiasts</title>
      <dc:creator>Buhake Sindi</dc:creator>
      <pubDate>Mon, 30 Dec 2024 22:26:26 +0000</pubDate>
      <link>https://forem.com/theelitegentleman/heres-a-list-of-south-african-public-apis-for-all-developers-and-enthusiasts-353a</link>
      <guid>https://forem.com/theelitegentleman/heres-a-list-of-south-african-public-apis-for-all-developers-and-enthusiasts-353a</guid>
      <description>&lt;p&gt;I've decided to create and publish a database list of South African Public APIs for all developers and enthusiasts. Yes, you're welcome to contribute to the list. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/posts/sindi-technologies_weve-published-a-database-list-of-south-activity-7279607729441112064-55tG" rel="noopener noreferrer"&gt;Check it out&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>api</category>
      <category>news</category>
    </item>
    <item>
      <title>Are software engineers actually engineers in South Africa?</title>
      <dc:creator>Buhake Sindi</dc:creator>
      <pubDate>Thu, 01 Dec 2022 01:15:12 +0000</pubDate>
      <link>https://forem.com/theelitegentleman/are-software-engineers-actually-engineers-in-south-africa-5dal</link>
      <guid>https://forem.com/theelitegentleman/are-software-engineers-actually-engineers-in-south-africa-5dal</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: This is also posted on my other &lt;a href="https://deventerpriselog.blogspot.com/2022/10/are-software-engineers-actually.html" rel="noopener noreferrer"&gt;blog site&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There's a recent event that shook the tech industry worldwide. &lt;/p&gt;

&lt;p&gt;From this &lt;a href="https://news.slashdot.org/story/22/10/14/221214/is-a-software-engineer-an-engineer-alberta-regulator-says-no-riling-the-provinces-tech-sector" rel="noopener noreferrer"&gt;SlashDot News&lt;/a&gt;: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Association of Professional Engineers and Geoscientists of Alberta&lt;br&gt;
(APEGA), has asked a court to order one of the province's leading&lt;br&gt;
software companies, Octopusapp, known as Jobber, to stop using the&lt;br&gt;
term "engineer" in job titles and postings unless it gets a permit&lt;br&gt;
from the regulator. That has caused an uproar in Alberta's tech&lt;br&gt;
sector.&lt;/p&gt;

&lt;p&gt;The full article can be found &lt;a href="https://www.theglobeandmail.com/business/technology/article-is-a-software-engineer-an-engineer-alberta-regulator-says-no-riling-2/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To cut the story short, APEGA wants companies and individuals to stop using the titles "software engineer" and "computer engineer", unless individuals are licensed as engineers as "Professional engineers are held to high professional and ethical standards and work in the public interest", they said.&lt;/p&gt;

&lt;p&gt;So, what does this mean in the South African tech industry? Are software engineers actually engineers?&lt;/p&gt;

&lt;p&gt;In South Africa, the statutory body for engineering profession is called &lt;a href="https://www.ecsa.co.za/" rel="noopener noreferrer"&gt;The Engineering Council of South Africa (ECSA)&lt;/a&gt;. As their website states:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Engineering Council of South Africa (ECSA) is a statutory body&lt;br&gt;
established in terms of the Engineering Profession Act (EPA), 46 of&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The ECSA's primary role is the regulation of the engineering profession in terms of this Act.  Its core functions are the
accreditation of engineering programmes, registration of persons as
professionals in specified categories, and the regulation of the
practice of registered persons.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;According to the &lt;a href="https://www.gov.za/sites/default/files/gcis_document/201409/a46-000.pdf" rel="noopener noreferrer"&gt;Engineering Profession Act (EPA), 46 of 2000&lt;/a&gt;,   the focus of ECSA is to ensure that registered professionals in the engineering profession:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;apply their knowledge and skill in the interest of humanity and the environment;&lt;/li&gt;
&lt;li&gt;to execute their work with integrity and sincerity and in accordance with generally accepted norms of professional conduct; and&lt;/li&gt;
&lt;li&gt;respect the interest of their fellow being and honour the standing of the Profession.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are stipulated in the Code of Professional Conduct and this allows that the Registered person allow its conduct and ethics to be made subject to the scrutiny of its peers and the public.&lt;/p&gt;

&lt;p&gt;A Professional Engineer with an accredited Engineering degree(s) - B.Eng or B.Sc(Eng) - that satisfies the educational requirement as a candidate of ECSA can register, and, only accredited from a recognised tertiary university in South Africa, recognised by ECSA can register.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where does Software Engineering fit within the Engineering Profession, as defined by ECSA?
&lt;/h2&gt;

&lt;p&gt;ECSA can consider candidates in the Software Engineering profession if the candidate has completed and obtained an accredited engineering - B.Eng/B.Sc(Eng) - type qualification from a recognised tertiary university in South Africa. Therefore, only those that have completed and obtained an accredited degree in Computer Engineering can be considered as candidate for Professional Engineer by ECSA.&lt;/p&gt;

&lt;p&gt;The guideline for registration for Professional Engineer in Computer Engineering can be found &lt;a href="https://www.ecsa.co.za/ECSADocuments/Shared%20Documents/R-05-COMP-PE%20Discipline-specific%20Training%20Guide%20for%20Registration%20as%20a%20Professional%20Engineer%20in%20Computer%20Engineering.pdf" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Institute of Information Technology Professionals South Africa (IITPSA)
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://www.iitpsa.org.za/" rel="noopener noreferrer"&gt;Institute of Information Technology Professionals South Africa (IITPSA)&lt;/a&gt;, formerly Computer Society of South Africa (CCSA), is a professinal body recognised by the South African Qualifications Authority (SAQA). &lt;/p&gt;

&lt;p&gt;IITPSA's aims are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;to further the study, science and application of Information and Communications Technologies (ICTs);&lt;/li&gt;
&lt;li&gt; maintain and promote Codes of Conduct and Ethics for our members; &lt;/li&gt;
&lt;li&gt;define and promote standards of ICT knowledge; promote the formulation of effective policies on ICT and related matters;&lt;/li&gt;
&lt;li&gt;and extend the knowledge and understanding and usage of ICTs in the community.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thus, adherence to IITPSA’s Code of Conduct and Code of Practice assures others that IITPSA members are committed to ethical and professional behaviour.&lt;/p&gt;

&lt;p&gt;Professional Software Engineers in the ICT (Information and Communications Technology) sector can become a &lt;a href="https://www.iitpsa.org.za/certified-member-cmiitpsa/" rel="noopener noreferrer"&gt;Certified Member IITPSA (CMIITPSA)&lt;/a&gt;. &lt;/p&gt;

&lt;h1&gt;
  
  
  Final thoughts?
&lt;/h1&gt;

&lt;p&gt;Software is an increasingly critical component in many systems, some having huge social and commercial impact.&lt;/p&gt;

&lt;p&gt;However, the question still remains: Should “Software Engineering” become a branch of engineering under the ECSA framework (if we want it to be recognsised as an engineering profession)?&lt;/p&gt;

&lt;p&gt;There has been several efforts to create a curriculum for Software Engineering education. The &lt;a href="https://standards.ieee.org/ieee/610.12/855/" rel="noopener noreferrer"&gt;IEEE Standard of 610.12-1990&lt;/a&gt; (Software Engineering Terminology) was established by the IEEE Computer Society, which defines Software Engineering as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The application of a systematic, disciplined, quantifiable approach to&lt;br&gt;
the development, operation and maintenance of software; that is, the&lt;br&gt;
application of engineering to software.&lt;/p&gt;

&lt;p&gt;They have, even, established a &lt;a href="https://www.computer.org/education/bodies-of-knowledge/software-engineering" rel="noopener noreferrer"&gt;Software Engineering Body of Knowledge&lt;/a&gt; (aka SWEBOK) - currently SWEBOK V3 is available for download - provides 5 objectives,  some which can be considered as engineering principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To promote a consistent view of software engineering worldwide&lt;/li&gt;
&lt;li&gt;To specify the scope of, and clarify the place of software engineering with respect to other disciplines such as computer science, project management, computer engineering, and mathematics&lt;/li&gt;
&lt;li&gt;To characterize the contents of the software engineering discipline&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;If Software Engineering be considered as a true engineering profession in SA, we would require that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Software Engineering is formally listed at ECSA.&lt;/li&gt;
&lt;li&gt;A formal, recognised accreditation, specific to Software Engineering qualification that meets the IEEE Computer Society Standard is taught by accredited tertiary institution.&lt;/li&gt;
&lt;li&gt;Qualified Software Engineers formally register in order to satisfy the requirements to be a Professional Engineer in Software Engineering.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Thus, is software engineering actually an engineering activity? That is left for the reader to decide.&lt;/p&gt;

</description>
      <category>watercooler</category>
    </item>
    <item>
      <title>Microservice: Creating a JPA application using Jakarta Persistence API in Payara Micro</title>
      <dc:creator>Buhake Sindi</dc:creator>
      <pubDate>Fri, 11 Feb 2022 01:51:02 +0000</pubDate>
      <link>https://forem.com/theelitegentleman/microservice-creating-a-jdbc-datasource-in-payara-micro-140</link>
      <guid>https://forem.com/theelitegentleman/microservice-creating-a-jdbc-datasource-in-payara-micro-140</guid>
      <description>&lt;p&gt;In this blog we are going to discuss how your Java microservice application can  connect to and interacts to relational database through the &lt;a href="https://jakarta.ee/specifications/persistence/" rel="noopener noreferrer"&gt;Jakarta Persistence API&lt;/a&gt; (latest version at time of writing is version 3.0). You can configure a data source and a JDBC driver so an application that is running on your Payara Micro server can connect with a relational database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before we begin...
&lt;/h2&gt;

&lt;p&gt;This blog tutorial, we will configure this application with the following in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The microservice application will be Mavenized Java application.&lt;/li&gt;
&lt;li&gt;We will use MySQL DB Server as a relational database.&lt;/li&gt;
&lt;li&gt;The JDBC datasource will be a transactional datasource (&lt;code&gt;XADataSource&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  JDBC Driver library configuration with Maven
&lt;/h2&gt;

&lt;p&gt;In order for your Java application to connect with a relational database, you need a JDBC driver, which is typically provided by the database vendor. Fortunately, most database vendors have released their JDBC drivers to a Maven repository.&lt;/p&gt;

&lt;p&gt;If you use Maven to build your application, you can add your JDBC driver by adding code that is similar to the following example to your &lt;code&gt;pom.xml&lt;/code&gt; file.&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;dependencyManagement&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;dependencies&amp;gt;&lt;/span&gt;
            &lt;span class="c"&gt;&amp;lt;!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --&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;mysql&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;mysql-connector-java&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;8.0.19&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dependencies&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dependencyManagement&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;dependencies&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;mysql&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;mysql-connector-java&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dependencies&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Maven, the JDBC driver file will be copied to the &lt;code&gt;WEB-INF/lib&lt;/code&gt; folder of your application WAR file during the &lt;code&gt;package&lt;/code&gt; build phase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring a Database Datasource
&lt;/h2&gt;

&lt;p&gt;In the &lt;a href="https://blog.payara.fish/setting-up-a-data-source-in-payara-micro" rel="noopener noreferrer"&gt;Payara Blog&lt;/a&gt; a datasource is configured inside the &lt;code&gt;web.xml&lt;/code&gt; file. In this example there is another alternative in creating a datasource configuration. The following example shows the basic pattern to configure a data source in your &lt;code&gt;payara-resource.xml&lt;/code&gt; file inside the &lt;code&gt;src/main/java/webapp/WEB-INF&lt;/code&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;    &lt;span class="cp"&gt;&amp;lt;!DOCTYPE resources  PUBLIC  "-//Payara.fish//DTD Payara Server 4 Resource Definitions//EN"  "https://raw.githubusercontent.com/payara/Payara-Community-Documentation/master/docs/modules/ROOT/pages/schemas/payara-resources_1_6.dtd"&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;resources&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;jdbc-resource&lt;/span&gt; &lt;span class="na"&gt;pool-name=&lt;/span&gt;&lt;span class="s"&gt;"MyAppDS"&lt;/span&gt;
                       &lt;span class="na"&gt;jndi-name=&lt;/span&gt;&lt;span class="s"&gt;"java:app/jdbc/MyApp"&lt;/span&gt;
                       &lt;span class="na"&gt;enable=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;jdbc-connection-pool&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"MySQLPool"&lt;/span&gt;
                              &lt;span class="na"&gt;res-type=&lt;/span&gt;&lt;span class="s"&gt;"javax.sql.XADataSource"&lt;/span&gt;
                              &lt;span class="na"&gt;datasource-classname=&lt;/span&gt;&lt;span class="s"&gt;"com.mysql.cj.jdbc.MysqlXADataSource"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"url"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"jdbc:h2:mem:hibernateExample"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"User"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"testUser"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/property&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Password"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"testPassword"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/property&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"DatabaseName"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"myapp_db"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/property&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"ServerName"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"localhost"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/property&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"PortNumber"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"3306"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/property&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/jdbc-connection-pool&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/resources&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Application configuration for relational database connections
&lt;/h2&gt;

&lt;p&gt;To use a data source that is configured in your &lt;code&gt;payara-resource.xml&lt;/code&gt; file, you can either inject the data source or specify a lookup in your application code. The following examples assume that a &lt;code&gt;jndi-name&lt;/code&gt; value of &lt;code&gt;java:app/jdbc/MyApp&lt;/code&gt; is specified as the &lt;code&gt;jdbc-resource&lt;/code&gt; element attribute in the &lt;code&gt;payara-resource.xml&lt;/code&gt; file.&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;@Resource&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;"java:app/jdbc/MyApp"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 
    &lt;span class="nc"&gt;DataSource&lt;/span&gt; &lt;span class="n"&gt;mySQLDatasource&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Injecting JPA EntityManager to your application
&lt;/h2&gt;

&lt;p&gt;Once your datasource is configured in your &lt;code&gt;payara-resource.xml&lt;/code&gt; file, we need to register your datasource inside the &lt;code&gt;persistence.xml&lt;/code&gt; in your &lt;code&gt;src/main/resources/META-INF/persistence.xml&lt;/code&gt; file. The &lt;code&gt;jta-data-source&lt;/code&gt; is &amp;amp; matches the &lt;code&gt;jndi-name&lt;/code&gt; of the datasource as specified in the &lt;code&gt;payara-resource.xml&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;    &lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;persistence&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;"2.1"&lt;/span&gt;
        &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://xmlns.jcp.org/xml/ns/persistence"&lt;/span&gt; &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;
        &lt;span class="na"&gt;xsi:schemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd "&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;persistence-unit&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"MyAppPU"&lt;/span&gt; &lt;span class="na"&gt;transaction-type=&lt;/span&gt;&lt;span class="s"&gt;"JTA"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;jta-data-source&amp;gt;&lt;/span&gt;java:app/jdbc/MyApp&lt;span class="nt"&gt;&amp;lt;/jta-data-source&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;shared-cache-mode&amp;gt;&lt;/span&gt;ENABLE_SELECTIVE&lt;span class="nt"&gt;&amp;lt;/shared-cache-mode&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;properties&amp;gt;&lt;/span&gt;
                &lt;span class="c"&gt;&amp;lt;!-- JBoss Wildfly's Hibernate 4 specific JPA properties --&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"hibernate.cache.use_second_level_cache"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"hibernate.hbm2ddl.auto"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"validate"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="c"&gt;&amp;lt;!-- NEVER: update --&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"hibernate.show_sql"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"hibernate.format_sql"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"hibernate.use_sql_comments"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"hibernate.enable_lazy_load_no_trans"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="c"&gt;&amp;lt;!--  For Performance monitoring on Hibernate --&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"hibernate.generate_statistics"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"hibernate.cache.use_structured_entries"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

                &lt;span class="c"&gt;&amp;lt;!-- TomEE PluME 1.7.2 and higher with EclipseLink  --&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"eclipselink.logging.logger"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"JavaLogger"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/properties&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/persistence-unit&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/persistence&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can inject your &lt;code&gt;EntityManager&lt;/code&gt; in your Java application code by specifying your persistence unit &lt;code&gt;MyAppPU&lt;/code&gt; in your &lt;code&gt;PersistenceContext&lt;/code&gt; annotation:&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;@PersistenceContext&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unitName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"MyAppPU"&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;EntityManager&lt;/span&gt; &lt;span class="n"&gt;entityManager&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  In conclusion...
&lt;/h2&gt;

&lt;p&gt;Although Payara Micro doesn't ship with an admin console (due to its lightweight platform) compared to Payara Server, it is still possible and simple enough to create JDBC Datasource in Payara Micro that can be used in your enterprise Java microservice application. In fact, with the power of Jakarta Persistent API you can write modern enterprise ORM that interacts with popular relational databases or interact directly once with your relational database by injecting a &lt;code&gt;DataSource&lt;/code&gt;, even via a JNDI lookup too!&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>java</category>
      <category>programming</category>
    </item>
    <item>
      <title>Understanding Jakarta EE 8 - C.D.I. (Part 3) - Defining custom CDI annotations.</title>
      <dc:creator>Buhake Sindi</dc:creator>
      <pubDate>Sun, 18 Jul 2021 00:28:48 +0000</pubDate>
      <link>https://forem.com/theelitegentleman/understanding-jakarta-ee-8-c-d-i-part-3-defining-custom-cdi-annotations-5bl</link>
      <guid>https://forem.com/theelitegentleman/understanding-jakarta-ee-8-c-d-i-part-3-defining-custom-cdi-annotations-5bl</guid>
      <description>&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%2Fjmpb8em4klbi4mof6bd6.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%2Fjmpb8em4klbi4mof6bd6.png" alt="Custom CDI annotations in Jakarta EE 8" width="800" height="450"&gt;&lt;/a&gt;[As we continue with this series, we will refer to some content and examples from the &lt;a href="https://jakarta.ee/specifications/cdi/2.0/cdi-spec-2.0.html" rel="noopener noreferrer"&gt;CDI 2.x specification&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;The CDI specification allows developers the flexibility to create new types that are within the scopes of the bean type declaration.&lt;br&gt;
In this example we will examine and learn how easy it is to create custom CDI annotations for defining:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New qualifier types.&lt;/li&gt;
&lt;li&gt;New Stereotypes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Defining new qualifier types.
&lt;/h2&gt;

&lt;p&gt;A qualifier type is a Java annotation defined as &lt;code&gt;@Retention(RUNTIME)&lt;/code&gt;. Typically a qualifier type is defined as &lt;code&gt;@Target({METHOD, FIELD, PARAMETER, TYPE})&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Defining a qualifier type may be declared by specifying the &lt;code&gt;@javax.inject.Qualifier&lt;/code&gt; meta-annotation.&lt;/p&gt;

&lt;p&gt;In our &lt;a href="https://github.com/TheEliteGentleman/jakartaee8-tuts-cdi/tree/master/src/main/java/za/co/sindi/tuts/jakartaee/cdi/example05" rel="noopener noreferrer"&gt;example&lt;/a&gt;, we've created 2 service-defined qualifier types, &lt;code&gt;@Jabbawockee&lt;/code&gt; and &lt;code&gt;@LesTwins&lt;/code&gt; qualifiers.&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;@Qualifier&lt;/span&gt;
&lt;span class="nd"&gt;@Documented&lt;/span&gt;
&lt;span class="nd"&gt;@Retention&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;RUNTIME&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Target&lt;/span&gt;&lt;span class="o"&gt;({&lt;/span&gt; &lt;span class="no"&gt;TYPE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;FIELD&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;METHOD&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;PARAMETER&lt;/span&gt; &lt;span class="o"&gt;})&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;@interface&lt;/span&gt; &lt;span class="nc"&gt;Jabbawockee&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Qualifier&lt;/span&gt;
&lt;span class="nd"&gt;@Documented&lt;/span&gt;
&lt;span class="nd"&gt;@Retention&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;RUNTIME&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Target&lt;/span&gt;&lt;span class="o"&gt;({&lt;/span&gt; &lt;span class="no"&gt;TYPE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;FIELD&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;METHOD&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;PARAMETER&lt;/span&gt; &lt;span class="o"&gt;})&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;@interface&lt;/span&gt; &lt;span class="nc"&gt;LesTwins&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 a bean is qualified by annotating the bean class or producer method or field with the qualifier type.&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;@Jabbawockee&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;JabbawockeeService&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Service&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;doWork&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;"Jabbawockee doing the work."&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;
  
  
  Stereotypes
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://javaee.github.io/tutorial/cdi-adv008.html" rel="noopener noreferrer"&gt;JavaEE specification&lt;/a&gt; specifies stereotypes as: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A &lt;strong&gt;stereotype&lt;/strong&gt; is a kind of annotation, applied to a bean, that incorporates other annotations. Stereotypes can be particularly useful in large applications in which&lt;br&gt;
you have a number of beans that perform similar functions.&lt;/p&gt;

&lt;p&gt;A well-known stereotypes, known by Enterprise Java Developers, are from Spring Framework: &lt;code&gt;@Component&lt;/code&gt;, &lt;code&gt;@Service&lt;/code&gt; and &lt;code&gt;@Repository&lt;/code&gt; stereotypes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A stereotype is an annotation, annotated &lt;code&gt;@Stereotype&lt;/code&gt;(&lt;code&gt;@javax.enterprise.inject.Stereotype&lt;/code&gt;), that packages several other annotations. For instance, to recreate the 3 stereotypes from Spring Framework into your JavaEE application:&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;@Stereotype&lt;/span&gt;
&lt;span class="nd"&gt;@Target&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;TYPE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Retention&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;RUNTIME&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Documented&lt;/span&gt;
&lt;span class="nd"&gt;@Named&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;@interface&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that our &lt;code&gt;Component&lt;/code&gt; stereotype has been declared with an empty &lt;code&gt;@Named&lt;/code&gt; annotation, which specifies that every bean with the stereotype has a defaulted name when a name is not explicitly specified by the bean. A  &lt;code&gt;@Named&lt;/code&gt;  qualifier declared by a stereotype is not added to the qualifiers of a bean with the stereotype.&lt;/p&gt;

&lt;p&gt;If a stereotype declares a non-empty  &lt;code&gt;@Named&lt;/code&gt;  annotation, the container automatically detects the problem and treats it as a definition error.&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;@Stereotype&lt;/span&gt;
&lt;span class="nd"&gt;@Target&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;TYPE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Retention&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;RUNTIME&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Component&lt;/span&gt; &lt;span class="c1"&gt;//Note that Spring specifies that this annotation is a specialization of Component annotation.&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;@interface&lt;/span&gt; &lt;span class="nc"&gt;Service&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Stereotype&lt;/span&gt;
&lt;span class="nd"&gt;@Target&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;TYPE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Retention&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;RUNTIME&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;@interface&lt;/span&gt; &lt;span class="nc"&gt;Repository&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Stereotype can be specified with interceptor bindings by annotating the stereotype with interceptor binding types. For example, to have a transactional business service, we can annotate our &lt;code&gt;Service&lt;/code&gt; stereotype with &lt;code&gt;@Transactional&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;@Stereotype&lt;/span&gt;
&lt;span class="nd"&gt;@Target&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;TYPE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Retention&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;RUNTIME&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Transactional&lt;/span&gt;
&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;@interface&lt;/span&gt; &lt;span class="nc"&gt;Service&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, the default scope of a stereotype is defined by annotating the stereotype with a scope type. A stereotype may declare at most one scope. If a stereotype declares more than one scope, the container automatically detects the problem and treats it as a definition error.&lt;/p&gt;

&lt;p&gt;For example, in our &lt;code&gt;Controller&lt;/code&gt; stereotype, we may specify to have a default &lt;code&gt;@RequestScoped&lt;/code&gt; scope type:&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;@RequestScoped&lt;/span&gt;
&lt;span class="nd"&gt;@Stereotype&lt;/span&gt;
&lt;span class="nd"&gt;@Target&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;TYPE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Retention&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;RUNTIME&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Documented&lt;/span&gt;
&lt;span class="nd"&gt;@Named&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;@interface&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Built-in stereotype.
&lt;/h3&gt;

&lt;p&gt;The CDI framework provides us with a built-in stereotype &lt;code&gt;@javax.enterprise.inject.Model&lt;/code&gt; which is intended for use with beans that define the &lt;em&gt;model&lt;/em&gt; layer of an MVC web application architecture such as Jakarta Server Faces.&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;@Named&lt;/span&gt;
&lt;span class="nd"&gt;@RequestScoped&lt;/span&gt;
&lt;span class="nd"&gt;@Stereotype&lt;/span&gt;
&lt;span class="nd"&gt;@Target&lt;/span&gt;&lt;span class="o"&gt;({&lt;/span&gt;&lt;span class="no"&gt;TYPE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;METHOD&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;FIELD&lt;/span&gt;&lt;span class="o"&gt;})&lt;/span&gt;
&lt;span class="nd"&gt;@Retention&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;RUNTIME&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;@interface&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the next article, we will examine Producers (producer method and producer field), injecting using &lt;code&gt;@Produces&lt;/code&gt; and Decorators, using the &lt;code&gt;@Decorator&lt;/code&gt; annotation.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>tutorial</category>
      <category>java</category>
      <category>jakartaee</category>
    </item>
    <item>
      <title>Understanding Jakarta EE 8 - C.D.I. (Part 2) - Qualifying your beans (continued…).</title>
      <dc:creator>Buhake Sindi</dc:creator>
      <pubDate>Tue, 29 Dec 2020 23:11:31 +0000</pubDate>
      <link>https://forem.com/theelitegentleman/understanding-jakarta-ee-8-c-d-i-part-2-qualifying-your-beans-cont-d-1pob</link>
      <guid>https://forem.com/theelitegentleman/understanding-jakarta-ee-8-c-d-i-part-2-qualifying-your-beans-cont-d-1pob</guid>
      <description>&lt;p&gt;[As we continue with this series, we will refer to some content and examples from the &lt;a href="https://jakarta.ee/specifications/cdi/2.0/cdi-spec-2.0.html" rel="noopener noreferrer"&gt;CDI 2.x specification&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;Suppose that you have more than one implementation of a bean to certify a service contract or you have more than one version of a bean you use for different purposes, such as an alternative bean (mock) for testing purposes.&lt;/p&gt;

&lt;p&gt;Instead of writing different codes for choice selection of your bean, bean selection choice can be done at deployment time using &lt;strong&gt;alternatives&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining Alternative Beans.
&lt;/h2&gt;

&lt;p&gt;To make the bean available for lookup, injection or for EL resolution, annotate your bean using &lt;code&gt;@Alternative&lt;/code&gt; anntations (FQN: &lt;code&gt;javax.enterprise.inject.Alternative&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;@Alternative&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;MockOrder&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Order&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;By default &lt;code&gt;@Alternative&lt;/code&gt; beans are disabled. They are only activated for a specific bean archive by editing &lt;code&gt;beans.xml&lt;/code&gt;. You can also have several beans that implement the same interface, all annotated &lt;code&gt;@Alternative&lt;/code&gt;. In this case, you must specify in the &lt;code&gt;beans.xml&lt;/code&gt; file which of these alternative beans you want to use. The alternatives that you specify in the &lt;code&gt;beans.xml&lt;/code&gt; file apply only to classes in the same archive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using &lt;code&gt;@Priority&lt;/code&gt; to specify alternatives.
&lt;/h2&gt;

&lt;p&gt;To enable an alternative bean globally for an application, especially when it has multiple modules use the &lt;code&gt;@javax.annotation.Priority&lt;/code&gt; annotation.&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;@Alternative&lt;/span&gt;
&lt;span class="nd"&gt;@Priority&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HighPriorityProcessor&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Processor&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;The alternative with higher priority value is selected if several alternative beans that implement the same interface are annotated with &lt;code&gt;@Priority&lt;/code&gt;. You do not need to specify the alternative in the &lt;code&gt;beans.xml&lt;/code&gt; file when you use the &lt;code&gt;@Priority&lt;/code&gt; annotation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example 03: CDI injection of  &lt;code&gt;@Alternative&lt;/code&gt;  bean (injection on interface, with 2 different implementations)
&lt;/h2&gt;

&lt;p&gt;The tutorial source code can be found &lt;a href="https://github.com/TheEliteGentleman/jakartaee8-tuts-cdi/tree/master/src/main/java/za/co/sindi/tuts/jakartaee/cdi/example03" rel="noopener noreferrer"&gt;here&lt;/a&gt; and the running executable class file can be found &lt;a href="https://github.com/TheEliteGentleman/jakartaee8-tuts-cdi/tree/master/src/test/java/za/co/sindi/tuts/jakartaee/cdi/example03" rel="noopener noreferrer"&gt;here&lt;/a&gt;.  The &lt;code&gt;Service&lt;/code&gt; interface has 2 different implementation: &lt;code&gt;DefaultService&lt;/code&gt; and &lt;code&gt;AlternativeService&lt;/code&gt; (annotated with &lt;code&gt;@Alternative&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;MainController&lt;/code&gt; injects a &lt;code&gt;Service&lt;/code&gt; and without activating the &lt;code&gt;AlternativeService&lt;/code&gt;, the &lt;code&gt;DefaultService&lt;/code&gt; will be injected (as it's implicitly qualified as a &lt;code&gt;@Default&lt;/code&gt; qualifier).&lt;/p&gt;

&lt;p&gt;If we want to ensure that &lt;code&gt;AlternativeService&lt;/code&gt; is injected inside &lt;code&gt;MainController&lt;/code&gt;, we activate it inside &lt;code&gt;beans.xml&lt;/code&gt; (source code can be found &lt;a href="https://github.com/TheEliteGentleman/jakartaee8-tuts-cdi/blob/master/src/main/resources/META-INF/beans.xml" rel="noopener noreferrer"&gt;here&lt;/a&gt;).&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;alternatives&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;class&amp;gt;&lt;/span&gt;za.co.sindi.tuts.jakartaee.cdi.example03.AlternativeService&lt;span class="nt"&gt;&amp;lt;/class&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/alternatives&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running the &lt;code&gt;DefaultCDIMain&lt;/code&gt; class, you will see the output &lt;strong&gt;Alternative Service work.&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In the future tutorial we'll focus on &lt;code&gt;@Stereotypes&lt;/code&gt; and how to apply factory methods in CDI.&lt;/p&gt;

</description>
      <category>java</category>
      <category>tutorial</category>
      <category>programming</category>
      <category>jakartaee</category>
    </item>
    <item>
      <title>Introducing Jakarta EE 9...</title>
      <dc:creator>Buhake Sindi</dc:creator>
      <pubDate>Mon, 21 Dec 2020 00:15:32 +0000</pubDate>
      <link>https://forem.com/theelitegentleman/introducing-jakarta-ee-9-1hj8</link>
      <guid>https://forem.com/theelitegentleman/introducing-jakarta-ee-9-1hj8</guid>
      <description>&lt;p&gt;Since Oracle's announcement that it would submit Java EE to the Eclipse Foundation the Java community has received 2 official Jakarta EE releases, the latest being Jakarta EE 9 (released on 22 November 2020).&lt;/p&gt;

&lt;p&gt;So what can we look forward to with this release?&lt;/p&gt;

&lt;h2&gt;
  
  
  Objectives with Jakarta EE 9
&lt;/h2&gt;

&lt;p&gt;The main objective of Jakarta EE 9 is to deliver a set of specifications functionally similar to Jakarta EE 8 but in the new Jakarta EE 9 namespace &lt;code&gt;jakarta.*&lt;/code&gt;. That's right: the old &lt;code&gt;javax.*&lt;/code&gt; namespace has been replaced by the &lt;code&gt;jakarta.*&lt;/code&gt; namespace. This makes it the very first official Jakarta EE release that is not reliant on the previous Oracle namespace.&lt;/p&gt;

&lt;h2&gt;
  
  
  Changes in Jakarta EE 9
&lt;/h2&gt;

&lt;p&gt;With the shift of the Jakarta EE namespace, developers must be aware of changes and updates on the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every API were transitioned from &lt;code&gt;javax&lt;/code&gt; namespace to &lt;code&gt;jakarta&lt;/code&gt; namesapce. This means that the Jakarta EE specification were changed to reflect the API changes as well as the implementation specification of the API were changed to handle the new APIs.&lt;/li&gt;
&lt;li&gt;Jakarta EE 9 release removes specifications from Jakarta EE 8 that were old, optional, or deprecated in order to reduce the surface area of the APIs. Thus, CORBA implementations no longer exists in Jakarta EE 9. SOAP specifications are deemed stable. There won't be any future plans to work on the technology.&lt;/li&gt;
&lt;li&gt;All specifications included in the Jakarta EE 9 release have been versioned to a new major version of the specification document. For example, JPA 2.x (in Jakarta EE 8) is now JPA 3.0 in Jakarta EE 9&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No backward compatibility&lt;/strong&gt;. Jakarta EE 9 is not backward compatible with Jakarta EE 8 or Java EE 8. It's not recommended to mix Jakarta EE 8 artifacts with Jakarta EE 9 and vice versa.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Migrating to Jakarta EE 9
&lt;/h2&gt;

&lt;p&gt;Migrating to Jakarta EE 9 will require that developers/users must begin transitioning to &lt;a href="https://jakarta.ee/compatibility/#tab-9" rel="noopener noreferrer"&gt;Jakarta EE 9 compatible application servers&lt;/a&gt;. Currently, at the time of writing this post, &lt;a href="https://glassfish.org/download" rel="noopener noreferrer"&gt;Glassfish 6&lt;/a&gt; supports Jakarta EE 9. Until other vendors release Jakarta EE 9 compatible products and applications servers, user migration and transitioning to Jakarta EE 9 might take a while. Note that this might be an expensive exercise to upgrade to Jakarta EE 9 so users must be aware of whether the rich feature set that comes Jakarta EE 9 is worth the upgrade.&lt;/p&gt;

&lt;p&gt;For developers willing to start working with Jakarta EE 9 release, one needs to just update their &lt;code&gt;pom.xml&lt;/code&gt; (if the project is Mavenized), by adding the following dependency:&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;jakarta.platform&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;jakarta.jakartaee-api&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;9.0.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;provided&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And ensuring that they organise their import to change their namespace from &lt;code&gt;javax&lt;/code&gt; to &lt;code&gt;jakarta&lt;/code&gt;. Jakarta EE 9 is compatible with Java SE 8. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Future of Jakarta EE (Jakarta EE 10 and beyond)
&lt;/h2&gt;

&lt;p&gt;The future of Jakarta EE will be a much more exciting release for application developers than Jakarta EE 9 because the Eclipse Foundation encourages developers and the Java community to put their ideas forward so that features and functionality that we can help drive what technology to include (such as cloud-native technology, etc.) to help move Jakarta EE forward.&lt;/p&gt;

&lt;p&gt;The best way is to join the &lt;a href="https://jakarta.ee/connect/mailing-lists/" rel="noopener noreferrer"&gt;Jakarta EE mailing lis&lt;/a&gt;t to start driving the discussion of Jakarta EE 10 forward.&lt;/p&gt;

&lt;p&gt;Have you migrated to Jakarta EE 9 yet or are you planning to migrate to Jakarta EE 9? We look forward to continuing to see how this most recent update to Jakarta EE 9 will impact the Java community.&lt;/p&gt;

</description>
      <category>java</category>
      <category>jakartaee</category>
      <category>programming</category>
      <category>news</category>
    </item>
    <item>
      <title>Understanding Jakarta EE 8 - C.D.I. (Part 2) - Qualifying your beans.</title>
      <dc:creator>Buhake Sindi</dc:creator>
      <pubDate>Sun, 13 Dec 2020 01:41:01 +0000</pubDate>
      <link>https://forem.com/theelitegentleman/understanding-jakarta-ee-8-c-d-i-part-2-qualifying-your-beans-2mi2</link>
      <guid>https://forem.com/theelitegentleman/understanding-jakarta-ee-8-c-d-i-part-2-qualifying-your-beans-2mi2</guid>
      <description>&lt;p&gt;[As we continue with this series, we will refer to some content and examples from the &lt;a href="https://jakarta.ee/specifications/cdi/2.0/cdi-spec-2.0.html" rel="noopener noreferrer"&gt;CDI 2.x specification&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;In order for the CDI container to recognise your bean for injection, your bean needs to be qualified. This can be achieved by associating a bean with a qualifier type. A &lt;em&gt;qualifier type&lt;/em&gt; represents some client-visible semantic associated with a type that is satisfied by some implementations of the type (and not by others). In other words, a qualifier type identifies a bean with a type that can be satisfied to one specific implementation of the same type (else it becomes an &lt;em&gt;unsatisfied dependency&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Let's look at how a bean can be qualified using a bean qualifier types.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bean Qualifier Types
&lt;/h2&gt;

&lt;p&gt;There's 3 standard qualified types that are defined in the &lt;code&gt;javax.enterprise.inject&lt;/code&gt; package:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;@Any&lt;/code&gt;: Every bean has the built-in qualifier &lt;code&gt;@Any&lt;/code&gt;, even if it does not explicitly declare this qualifier, except for the special &lt;code&gt;@New&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@Default&lt;/code&gt;: If a bean does not explicitly declare a qualifier other than &lt;code&gt;@Named&lt;/code&gt;, the bean has the qualifier &lt;code&gt;@Default&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@New&lt;/code&gt;: The &lt;code&gt;@New&lt;/code&gt; qualifier allows the application to obtain a new instance of a bean which is not bound to the declared scope, but has had dependency injection performed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The following declarations are equivalent:&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;@Default&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;Order&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;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;Order&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;Both declarations result in a bean with two qualifiers:  &lt;code&gt;@Any&lt;/code&gt;  and  &lt;code&gt;@Default&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The default qualifier is also assumed for any injection point that does not explicitly declare a qualifier, Thus, the following declarations, in which the use of the  &lt;code&gt;@Inject&lt;/code&gt;  annotation identifies the constructor parameter as an injection point, are equivalent:&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;Order&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Inject&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Default&lt;/span&gt; &lt;span class="nc"&gt;OrderProcessor&lt;/span&gt; &lt;span class="n"&gt;processor&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="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;Order&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Inject&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderProcessor&lt;/span&gt; &lt;span class="n"&gt;processor&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="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In conclusion, the &lt;code&gt;@Any&lt;/code&gt; and the &lt;code&gt;@Default&lt;/code&gt; qualifier are always assumed during bean qualification as well as at injection point when the qualifier hasn't been explicitly declared.&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;@Named&lt;/code&gt; Qualifier
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;@Named&lt;/code&gt; is defined by the package &lt;code&gt;javax.inject&lt;/code&gt;. This qualifier is used to specify the name of a bean. For example, this bean is named  &lt;code&gt;currentOrder&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;@Named&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"currentOrder"&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;Order&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;The above declaration results in a bean with three qualifiers: &lt;code&gt;@Any&lt;/code&gt;, &lt;code&gt;@Default&lt;/code&gt; and &lt;code&gt;@Named("currentOrder")&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;@Named&lt;/code&gt; is declared by the bean with no bean name provided, the default bean name is used, after converting the first character of the class name to lowercase. For example, using the example above, if &lt;code&gt;Order&lt;/code&gt; class was just annotated with &lt;code&gt;@Named&lt;/code&gt;, the default bean name will be &lt;code&gt;order&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For more information, please refer to &lt;a href="https://jakarta.ee/specifications/cdi/2.0/cdi-spec-2.0.html#managed_bean_name" rel="noopener noreferrer"&gt;section 3.1.5 Default bean name for a managed bean&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;@Named&lt;/code&gt; is not declared by the bean, nor by its stereotypes, a bean has no name.&lt;/p&gt;

&lt;p&gt;Now that you have a basic insight on qualifying beans, let's look at various examples of qualifying beans using bean qualifier types. Note that we've set the &lt;a href="https://github.com/TheEliteGentleman/jakartaee8-tuts-cdi/blob/master/src/main/resources/META-INF/beans.xml" rel="noopener noreferrer"&gt;&lt;code&gt;bean-discovery-mode&lt;/code&gt; as &lt;code&gt;all&lt;/code&gt;&lt;/a&gt;, the CDI container successfully recognised our classes as a qualified classes, ready for injection. &lt;/p&gt;

&lt;h2&gt;
  
  
  Example 1: CDI injection of implicit &lt;code&gt;@Default&lt;/code&gt; bean class (with no interfaces)
&lt;/h2&gt;

&lt;p&gt;The tutorial source code can be found &lt;a href="https://github.com/TheEliteGentleman/jakartaee8-tuts-cdi/tree/master/src/main/java/za/co/sindi/tuts/jakartaee/cdi/example01" rel="noopener noreferrer"&gt;here&lt;/a&gt; and the running executable class file can be found &lt;a href="https://github.com/TheEliteGentleman/jakartaee8-tuts-cdi/tree/master/src/test/java/za/co/sindi/tuts/jakartaee/cdi/example01" rel="noopener noreferrer"&gt;here&lt;/a&gt; and it follows the example as mentioned in the previous article. The &lt;code&gt;DefautService&lt;/code&gt; and &lt;code&gt;MainController&lt;/code&gt; classes are simple classes that don't extend nor inherit any other class or interfaces respectively and has not been annotated with any bean qualifiers. This is due to the fact that all qualified bean are implicitly set as &lt;code&gt;@Any&lt;/code&gt; and &lt;code&gt;@Default&lt;/code&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Example 2: CDI injection of implicit &lt;code&gt;@Default&lt;/code&gt; bean class (injection on interface)
&lt;/h2&gt;

&lt;p&gt;This is the extension of Example 1 but, in this case, the &lt;code&gt;DefaultService&lt;/code&gt; implements the &lt;code&gt;Service&lt;/code&gt; interface.&lt;br&gt;
The tutorial source code can be found &lt;a href="https://github.com/TheEliteGentleman/jakartaee8-tuts-cdi/tree/master/src/main/java/za/co/sindi/tuts/jakartaee/cdi/example02" rel="noopener noreferrer"&gt;here&lt;/a&gt; and the running executable class file can be found &lt;a href="https://github.com/TheEliteGentleman/jakartaee8-tuts-cdi/tree/master/src/test/java/za/co/sindi/tuts/jakartaee/cdi/example02" rel="noopener noreferrer"&gt;here&lt;/a&gt;.  On &lt;code&gt;MainController&lt;/code&gt; class we simply inject on the property which links to the &lt;code&gt;Service&lt;/code&gt; interface.&lt;br&gt;
Seeing that there are no annotations on &lt;code&gt;DefaultService&lt;/code&gt;, the CDI container has managed to successfully discovery one implementation of the &lt;code&gt;Service&lt;/code&gt; interface and thus, creating a contextual context around the &lt;code&gt;Service&lt;/code&gt; interface (which in turn will inject &lt;code&gt;DefaultService&lt;/code&gt; when needed).&lt;br&gt;
The &lt;code&gt;DefaultService&lt;/code&gt; implicitly is qualified as a &lt;code&gt;@Any&lt;/code&gt; and &lt;code&gt;@Default&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's pause on here. In the next tutorial we'll look on how to tackle injections of classes / interfaces that can produce more than 1 dependency injections using &lt;code&gt;@Alternative&lt;/code&gt; as well as defining our own custom qualifier type.&lt;/p&gt;

</description>
      <category>java</category>
      <category>jakartaee</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
