<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Tristan Mahinay's Blog]]></title><description><![CDATA[Technical blog by Tristan Mahinay]]></description><link>https://blog.rjtmahinay.com</link><generator>RSS for Node</generator><lastBuildDate>Mon, 13 Apr 2026 07:25:06 GMT</lastBuildDate><atom:link href="https://blog.rjtmahinay.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[AI-powered Chat Application using IBM watsonx.ai and Spring AI]]></title><description><![CDATA[Generative Artificial Intelligence (Gen AI) disrupted enterprises with the introduction of GPT-4 foundation model by Open AI in the late 2022 to early 2023 triggering big tech to release their own Gen AI platform and foundation models. Among them are...]]></description><link>https://blog.rjtmahinay.com/ai-powered-chat-application-using-ibm-watsonxai-and-spring-ai</link><guid isPermaLink="true">https://blog.rjtmahinay.com/ai-powered-chat-application-using-ibm-watsonxai-and-spring-ai</guid><category><![CDATA[Java]]></category><category><![CDATA[Spring]]></category><category><![CDATA[spring ai]]></category><category><![CDATA[Hilla]]></category><category><![CDATA[IBM WatsonX]]></category><dc:creator><![CDATA[Tristan Mahinay]]></dc:creator><pubDate>Mon, 30 Dec 2024 10:28:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735554091420/1c948db4-506d-4fbb-937d-b19fc4399328.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Generative Artificial Intelligence (Gen AI) disrupted enterprises with the introduction of GPT-4 foundation model by Open AI in the late 2022 to early 2023 triggering big tech to release their own Gen AI platform and foundation models. Among them are Google, Microsoft, AWS and IBM. In this article, we will deal with the Gen AI platform and model of IBM called watsonx and integrate it with Spring AI to create a custom chat application using the IBM Granite Foundation Model.</p>
<h1 id="heading-what-are-foundation-models">What are foundation models?</h1>
<p>Large-scale machine learning models trained on massive and diversed dataset to perform general-purpose tasks. One of the use-cases of foundation models are natural language processing tasks which augments the daily activities of human such as the ff:</p>
<ul>
<li><p>Summarization</p>
</li>
<li><p>Question and Answer</p>
</li>
<li><p>Translation</p>
</li>
<li><p>Sentiment Analysis</p>
</li>
<li><p>Text Generation</p>
</li>
<li><p>Image Recognition</p>
</li>
</ul>
<p>These activities usually incorporate a specific foundation model to achieve. Below are some scenarios that were considered in Gen AI development.</p>
<ol>
<li><p>Language Models Models that were trained to generate text, classify text, extract meaning of a text, summarize and generate code based on a textual context. These were trained to analyze the human language and give response based on an initial text input.</p>
</li>
<li><p>Image Models Models that were trained to understand, analyze, generate and manipulate visual data to the users. These models accepts images and drawings as an input and generates a response by understanding it.</p>
</li>
<li><p>Multi-modal Models Incorporates the capabilities of language and image models. It is trained to different modalities and perform a combination of it. The data that this model can handle can span to text, audio, video and images.</p>
</li>
</ol>
<p>In this article, we will focus on Language Models and Chat applications. Resurfacing again this excellent playlist explaining large language models and chatbots by IBM Technology.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtube.com/playlist?list=PLOspHqNVtKAAsiohuZj1Bt4XpA3_bkS3c&amp;si=VxMxXObxwAgD9hCS">https://youtube.com/playlist?list=PLOspHqNVtKAAsiohuZj1Bt4XpA3_bkS3c&amp;si=VxMxXObxwAgD9hCS</a></div>
<p> </p>
<h1 id="heading-ibm-watsonxaihttpwatsonxai">IBM <a target="_blank" href="http://watsonx.ai">watsonx.ai</a></h1>
<p>The flagship AI and machine learning platform by IBM. It is designed to empower business to build, deploy, scale AI models effectively. This technology is not the foundation model of IBM rather a platform that incorporates multiple foundation models plus the IBM's flagship model called IBM Granite.</p>
<p>To see the table of all supported foundation models, you can check it out <a target="_blank" href="https://www.ibm.com/products/watsonx-ai/foundation-modelshttp://">here</a>.</p>
<h2 id="heading-pricing">Pricing</h2>
<p>If you're an organization interested in trying IBM <a target="_blank" href="http://watsonx.ai">watsonx.ai</a>, you can check-out its <a target="_blank" href="https://www.ibm.com/products/watsonx-ai/pricing">pricing table</a></p>
<h1 id="heading-ibm-granite-models">IBM Granite Models</h1>
<p>IBM Granite is the IBM's flagship family of foundation models developed for Generative AI. It is part of the IBM <a target="_blank" href="http://watsonx.ai">watsonx.ai</a> platform and focuses in giving solutions to enterprises. One of the advantage of using Granite models is that it is optimized for business users, making enterprise organizations competitive using the platform.</p>
<p>Articles related to the capabilities of IBM Granite can be read below:</p>
<ul>
<li><p><a target="_blank" href="https://newsroom.ibm.com/2024-10-21-ibm-introduces-granite-3-0-high-performing-ai-models-built-for-business">IBM Introduces Granite 3.0: High Performing AI Models Built for Business</a></p>
</li>
<li><p><a target="_blank" href="https://developer.nvidia.com/blog/ibms-new-granite-3-0-generative-ai-models-are-small-yet-highly-accurate-and-efficient/">IBM’s New Granite 3.0 Generative AI Models Are Small, Yet Highly Accurate and Efficient</a></p>
</li>
</ul>
<p>The platform will be used to integrate a IBM Granite Model with Spring AI. For this demonstration we will be using a language model for chat applications using <a target="_blank" href="https://www.ibm.com/docs/en/watsonx/w-and-w/2.1.x?topic=models-granite-13b-chat-v2-model-card">IBM granite-13b-chat-v2</a></p>
<h1 id="heading-what-is-spring-ai">What is Spring AI?</h1>
<p>Streamlines the creation of generative artificial intelligence in a Java application without unnecessary complexities. The project main focus is to connect your enteprise data and APIs to foundation models.</p>
<p>The Spring AI API provides abstractions that have multiple implementations for easy development and minimal code changes.</p>
<p>The API provids various functionalities that spans from a simple application to a complex one. These functionalities can be combined to build an enterprise-grade full-stack application.</p>
<ul>
<li><p>AI Models (Chat, Image, Audio, Moderation and Embeddings)</p>
</li>
<li><p>Vector Databases</p>
</li>
<li><p>Retrieval-Augmented Generation</p>
</li>
<li><p>Observability</p>
</li>
<li><p>Prompting</p>
</li>
</ul>
<p>Additional functionalities that Spring AI supports which is significant for AI customizations</p>
<ul>
<li><p>Function Calling</p>
</li>
<li><p>Structured Output</p>
</li>
<li><p>Multi-modality</p>
</li>
<li><p>ETL Pipelines</p>
</li>
<li><p>Model Context Protocol</p>
</li>
</ul>
<p>In this demonstration, we will not deal in-depth of these concepts. We will show only the features that IBM <a target="_blank" href="http://watsonx.ai">watsonx.ai</a> API supports on how quickly we can create a simple chat application.</p>
<h2 id="heading-ibm-watsonxaihttpwatsonxai-1">IBM <a target="_blank" href="http://watsonx.ai">watsonx.ai</a></h2>
<p>The IBM <a target="_blank" href="http://watsonx.ai">watsonx.ai</a> API supports chat and embedding models in Spring AI context. For chat it supports <em>WatsonxAiChatModel</em> which is both a text generation and text stream generation.</p>
<p>To generate embeddings, the platform supports <em>WatsonxAiEmbeddingModel</em>.</p>
<p><img src="https://foojay.io/wp-content/uploads/2024/12/watsonx-springai-uml.png" alt /></p>
<p>The image above is the UML Diagram of WatsonxAi API. The chat model implements the provided abstraction of Spring AI for basic chat and streaming chat. To provide implementations of these methods, the WatsonxAiChatModel needs to call the corresponding <a target="_blank" href="http://watsonx.ai">watsonx.ai</a> platform API via REST and HTTP protocol.</p>
<h2 id="heading-creating-ibm-watsonxaihttpwatsonxai-chat-based-application">Creating IBM <a target="_blank" href="http://watsonx.ai">watsonx.ai</a> Chat-based Application</h2>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>The code that will be demonstrated is already available in <a target="_blank" href="https://github.com/rjtmahinay/watsonx-spring-ai-hilla">watsonx-spring-ai-hilla</a> project. If you're interested to run the demo project, you may fork and run it locally.</p>
<p>Spring AI is already available as a dependency in Spring Initialzr. To add the <a target="_blank" href="http://watsonx.ai">watsonx.ai</a> Spring Boot starter just specify the following dependency in your build.gradle</p>
<pre><code class="lang-plaintext">implementation 'org.springframework.ai:spring-ai-watsonx-ai-spring-boot-starter'
</code></pre>
<p>See the <a target="_blank" href="https://github.com/rjtmahinay/watsonx-spring-ai-hilla/blob/main/build.gradle">https://github.com/rjtmahinay/watsonx-spring-ai-hilla/blob/main/build.gradle</a> file of the project.</p>
<h3 id="heading-configurations">Configurations</h3>
<p>The watsonx platform needs the following properties to start the Spring AI application.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">spring:</span>
  <span class="hljs-attr">ai:</span>
    <span class="hljs-attr">watsonx:</span>
      <span class="hljs-attr">ai:</span>
        <span class="hljs-string">//</span> <span class="hljs-string">The</span> <span class="hljs-string">project</span> <span class="hljs-string">id</span> <span class="hljs-string">of</span> <span class="hljs-string">your</span> <span class="hljs-string">watsonx</span> <span class="hljs-string">project</span>
        <span class="hljs-attr">project-id:</span> <span class="hljs-string">${PROJECT_ID}</span>
        <span class="hljs-string">//</span> <span class="hljs-string">The</span> <span class="hljs-string">API</span> <span class="hljs-string">key</span> <span class="hljs-string">from</span> <span class="hljs-string">IBM</span> <span class="hljs-string">Cloud</span>
        <span class="hljs-attr">i-a-m-token:</span> <span class="hljs-string">${API_KEY}</span>
        <span class="hljs-string">//</span> <span class="hljs-string">Base</span> <span class="hljs-string">URL</span> <span class="hljs-string">of</span> <span class="hljs-string">the</span> <span class="hljs-string">IBM</span> <span class="hljs-string">Cloud</span> <span class="hljs-string">where</span> <span class="hljs-string">watsonx.ai</span> <span class="hljs-string">is</span> <span class="hljs-string">connected</span>
        <span class="hljs-attr">base-url:</span> <span class="hljs-string">https://us-south.ml.cloud.ibm.com</span>
        <span class="hljs-string">//</span> <span class="hljs-string">The</span> <span class="hljs-string">text</span> <span class="hljs-string">endpoint</span> <span class="hljs-string">of</span> <span class="hljs-string">watsonx.ai</span> <span class="hljs-string">service</span>
        <span class="hljs-attr">text-endpoint:</span> <span class="hljs-string">"/ml/v1/text/generation?version=2024-05-31"</span>
        <span class="hljs-string">//</span> <span class="hljs-string">The</span> <span class="hljs-string">streaming</span> <span class="hljs-string">text</span> <span class="hljs-string">endpoint</span> <span class="hljs-string">of</span> <span class="hljs-string">watsonx.ai</span> <span class="hljs-string">service</span>
        <span class="hljs-attr">stream-endpoint:</span> <span class="hljs-string">"/ml/v1/text/generation_stream?version=2024-05-31"</span>
</code></pre>
<p>All Spring AI properties starts with a prefix of <code>spring.ai.&lt;platform&gt;</code>. Every AI platform has their own specific options. For chat properties, <a target="_blank" href="http://watsonx.ai">watsonx.ai</a> API provides a Chat Options with default values and can be overriden in the properties or yaml file. Below is an example override of the chat options.</p>
<p>Project ID and API key should be stored in a secured vault to prevent security violations.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">spring:</span>
  <span class="hljs-attr">ai:</span>
    <span class="hljs-attr">watsonx:</span>
      <span class="hljs-attr">ai:</span>
        <span class="hljs-attr">chat:</span>
          <span class="hljs-attr">options:</span>
            <span class="hljs-string">//</span> <span class="hljs-string">The</span> <span class="hljs-string">chat</span> <span class="hljs-string">model</span> <span class="hljs-string">to</span> <span class="hljs-string">be</span> <span class="hljs-string">used</span>
            <span class="hljs-attr">model:</span> <span class="hljs-string">"ibm/granite-13b-chat-v2"</span>
            <span class="hljs-string">/*</span>
            <span class="hljs-string">Sets</span> <span class="hljs-string">the</span> <span class="hljs-string">decoding</span> <span class="hljs-string">strategy</span> <span class="hljs-string">either</span> <span class="hljs-string">greedy</span> <span class="hljs-string">or</span> <span class="hljs-string">sampling.</span> <span class="hljs-string">For</span> <span class="hljs-string">this</span> <span class="hljs-string">chat</span> <span class="hljs-string">application,</span> <span class="hljs-string">we</span> <span class="hljs-string">want</span>
            <span class="hljs-string">a</span> <span class="hljs-string">more</span> <span class="hljs-string">factual</span> <span class="hljs-string">result</span> <span class="hljs-string">rather</span> <span class="hljs-string">a</span> <span class="hljs-string">creative</span> <span class="hljs-string">one.</span> <span class="hljs-string">Thus,</span> <span class="hljs-string">we</span> <span class="hljs-string">will</span> <span class="hljs-string">use</span> <span class="hljs-string">greedy</span>
            <span class="hljs-string">*/</span>
            <span class="hljs-attr">decoding-method:</span> <span class="hljs-string">"greedy"</span>
            <span class="hljs-string">/*</span>
            <span class="hljs-string">The</span> <span class="hljs-string">maximum</span> <span class="hljs-string">token</span> <span class="hljs-string">that</span> <span class="hljs-string">the</span> <span class="hljs-string">LLM</span> <span class="hljs-string">will</span> <span class="hljs-string">use.</span> <span class="hljs-string">In</span> <span class="hljs-string">this</span> <span class="hljs-string">case,</span> <span class="hljs-string">the</span> <span class="hljs-string">granite-13b-chat-v2</span> <span class="hljs-string">has</span> <span class="hljs-string">a</span>
            <span class="hljs-string">maximum</span> <span class="hljs-string">of</span> <span class="hljs-number">8192 </span><span class="hljs-string">limit.</span>
            <span class="hljs-string">*/</span>
            <span class="hljs-attr">max-new-tokens:</span> <span class="hljs-number">8191</span>
            <span class="hljs-string">//</span> <span class="hljs-string">Defaults</span> <span class="hljs-string">to</span> <span class="hljs-number">0</span><span class="hljs-string">.</span> <span class="hljs-string">Sets</span> <span class="hljs-string">how</span> <span class="hljs-string">many</span> <span class="hljs-string">token</span> <span class="hljs-string">does</span> <span class="hljs-string">the</span> <span class="hljs-string">LLM</span> <span class="hljs-string">generate</span>
            <span class="hljs-attr">min-new-tokens:</span> <span class="hljs-number">0</span>
            <span class="hljs-string">/*</span>
            <span class="hljs-string">Temperature,</span> <span class="hljs-string">top-p,</span> <span class="hljs-string">and</span> <span class="hljs-string">top-k</span> <span class="hljs-string">are</span> <span class="hljs-string">used</span> <span class="hljs-string">for</span> <span class="hljs-string">Sampling</span> <span class="hljs-string">Decoding</span> <span class="hljs-string">Method.</span> <span class="hljs-string">We</span> <span class="hljs-string">will</span> <span class="hljs-string">not</span> <span class="hljs-string">use</span>
            <span class="hljs-string">this</span> <span class="hljs-string">in</span> <span class="hljs-string">this</span> <span class="hljs-string">demonstration.</span>
            <span class="hljs-string">*/</span>
            <span class="hljs-attr">temperature:</span> <span class="hljs-number">0.0</span>
            <span class="hljs-attr">top-p:</span> <span class="hljs-number">1.0</span>
            <span class="hljs-attr">top-k:</span> <span class="hljs-number">1</span>
            <span class="hljs-string">//</span> <span class="hljs-string">Penalize</span> <span class="hljs-string">the</span> <span class="hljs-string">LLM</span> <span class="hljs-string">for</span> <span class="hljs-string">repetition</span> <span class="hljs-string">of</span> <span class="hljs-string">text.</span> <span class="hljs-string">Defaults</span> <span class="hljs-string">to</span> <span class="hljs-number">1.0</span> <span class="hljs-string">and</span> <span class="hljs-string">has</span> <span class="hljs-string">a</span> <span class="hljs-string">maximum</span> <span class="hljs-string">of</span> <span class="hljs-number">2.0</span>
            <span class="hljs-attr">repetition-penalty:</span> <span class="hljs-number">1.0</span>
</code></pre>
<p>To see the token limits of all available foundation models in <a target="_blank" href="http://watsonx.ai">watsonx.ai</a> platform, please check the <a target="_blank" href="https://dataplatform.cloud.ibm.com/docs/content/wsj/analyze-data/fm-models-details.html?context=wx&amp;locale=en&amp;audience=wdp">documentation</a>.</p>
<h3 id="heading-chatbot">Chatbot</h3>
<p>The user-interface of the application is created via Hilla Framework. Hilla is part of Spring Initialzr dependencies. To learn more about Hilla, check out this <a target="_blank" href="https://vaadin.com/docs/latest/hilla/guides">documentation</a>.</p>
<p>The chat application uses the abstracted client called ChatClient. The ChatClient consumes as a parameter an AI model.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Configuration</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ChatConfiguration</span> </span>{

    <span class="hljs-comment">/**curl
     * This method is used to create a ChatClient bean.
     * <span class="hljs-doctag">@param</span> watsonxAiChatModel The chat model to be used
     * <span class="hljs-doctag">@return</span> The ChatClient bean
     */</span>
    <span class="hljs-meta">@Bean</span>
    <span class="hljs-function">ChatClient <span class="hljs-title">watsonxChatClient</span><span class="hljs-params">(WatsonxAiChatModel watsonxAiChatModel)</span> </span>{
        <span class="hljs-keyword">return</span> ChatClient.builder(watsonxAiChatModel)
                .defaultSystem(<span class="hljs-string">"You are a helpful ai assistant"</span>).build();
    }
}
</code></pre>
<p>I've created a configuration class that creates a ChatClient bean and consumes the WatsonxAiChatModel. I instructed the ChatClient to behave as a helpful AI assistant.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Endpoint</span>
<span class="hljs-meta">@AnonymousAllowed</span>
<span class="hljs-meta">@RequiredArgsConstructor</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ChatEndpoint</span> </span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> ChatClient watsonxChatClient;

    <span class="hljs-comment">/**
     * This method is used to generate a response from the chatbot.
     * <span class="hljs-doctag">@param</span> userInput The user's input to the chatbot
     * <span class="hljs-doctag">@return</span> The chatbot's response
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">generateMessage</span><span class="hljs-params">(String userInput)</span> </span>{
        <span class="hljs-keyword">return</span> watsonxChatClient.prompt().user(userInput).call().content();
    }

    <span class="hljs-comment">/**
     * This method is used to generate a streaming response from the chatbot.
     * <span class="hljs-doctag">@param</span> userInput The user's input to the chatbot
     * <span class="hljs-doctag">@return</span> The chatbot's response as a stream of strings
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Flux&lt;String&gt; <span class="hljs-title">generateStreamingMessage</span><span class="hljs-params">(String userInput)</span> </span>{
        <span class="hljs-keyword">return</span> watsonxChatClient.prompt().user(userInput).stream().content();
    }
}
</code></pre>
<p>Since we're using Hilla, the controller is called an endpoint. These endpoint class will be converted to a TypeScript file upon invocation of bootRun task.</p>
<p>Below is the example conversion to a TypeScript file. The file is called <em>ChatEndpoint.ts</em></p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { EndpointRequestInit <span class="hljs-keyword">as</span> EndpointRequestInit_1, Subscription <span class="hljs-keyword">as</span> Subscription_1 } <span class="hljs-keyword">from</span> <span class="hljs-string">"@vaadin/hilla-frontend"</span>;
<span class="hljs-keyword">import</span> client_1 <span class="hljs-keyword">from</span> <span class="hljs-string">"./connect-client.default.js"</span>;
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">generateMessage_1</span>(<span class="hljs-params">userInput: <span class="hljs-built_in">string</span> | <span class="hljs-literal">undefined</span>, init?: EndpointRequestInit_1</span>): <span class="hljs-title">Promise</span>&lt;<span class="hljs-title">string</span> | <span class="hljs-title">undefined</span>&gt; </span>{ <span class="hljs-keyword">return</span> client_1.call(<span class="hljs-string">"ChatEndpoint"</span>, <span class="hljs-string">"generateMessage"</span>, { userInput }, init); }
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">generateStreamingMessage_1</span>(<span class="hljs-params">userInput: <span class="hljs-built_in">string</span> | <span class="hljs-literal">undefined</span></span>): <span class="hljs-title">Subscription_1</span>&lt;<span class="hljs-title">string</span> | <span class="hljs-title">undefined</span>&gt; </span>{ <span class="hljs-keyword">return</span> client_1.subscribe(<span class="hljs-string">"ChatEndpoint"</span>, <span class="hljs-string">"generateStreamingMessage"</span>, { userInput }); }
<span class="hljs-keyword">export</span> { generateMessage_1 <span class="hljs-keyword">as</span> generateMessage, generateStreamingMessage_1 <span class="hljs-keyword">as</span> generateStreamingMessage };
</code></pre>
<p>If you inspect both generateMessage and generateStreamingMessage and Java methods were converted to a JavaScript method. In this case, we don't need to have a network call via REST since we can now call the method from the TypeScript conversion. Below is the example usage of these methods.</p>
<p><em>ChatView.tsx</em></p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> ChatView = <span class="hljs-function">() =&gt;</span> {

    <span class="hljs-comment">// Remove other logic for brevity.</span>

    <span class="hljs-keyword">const</span> handleSubmit = <span class="hljs-keyword">async</span> (event: CustomEvent) =&gt; {
         <span class="hljs-comment">// Remove other logic for brevity.</span>

        <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> ChatEndpoint.generateMessage(inputMessage);

            <span class="hljs-built_in">console</span>.info(<span class="hljs-string">'AI response:'</span>, response);

            <span class="hljs-keyword">const</span> aiResponse: Message = {
                id: (<span class="hljs-built_in">Date</span>.now() + <span class="hljs-number">1</span>).toString(),
                sender: <span class="hljs-string">'ai'</span>,
                content: response,
            };
            setMessages(<span class="hljs-function">(<span class="hljs-params">prevMessages</span>) =&gt;</span> [...prevMessages, aiResponse]);
        } <span class="hljs-keyword">catch</span> (error) {
            <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error sending message:'</span>, error);
        } <span class="hljs-keyword">finally</span> {
            setIsLoading(<span class="hljs-literal">false</span>);
        }
    };
}
</code></pre>
<p><em>StreamingChatView.tsx</em></p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> StreamingChatView = <span class="hljs-function">() =&gt;</span> {

    <span class="hljs-comment">// Remove other logic for brevity.</span>

    <span class="hljs-keyword">const</span> handleSubmit = <span class="hljs-keyword">async</span> (event: CustomEvent) =&gt; {
       <span class="hljs-comment">// Remove other logic for brevity.</span>

        <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">const</span> response = ChatEndpoint.generateStreamingMessage(inputMessage);

            <span class="hljs-keyword">const</span> aiResponse: Message = {
                id: (<span class="hljs-built_in">Date</span>.now() + <span class="hljs-number">1</span>).toString(),
                sender: <span class="hljs-string">'ai'</span>,
                content: <span class="hljs-string">''</span>,
            };
            setMessages(<span class="hljs-function">(<span class="hljs-params">prevMessages</span>) =&gt;</span> [...prevMessages, aiResponse]);

            response.onNext(<span class="hljs-function">(<span class="hljs-params">chunk: <span class="hljs-built_in">string</span> | <span class="hljs-literal">undefined</span></span>) =&gt;</span> {
                setMessages(<span class="hljs-function">(<span class="hljs-params">prevMessages</span>) =&gt;</span> {
                    <span class="hljs-keyword">const</span> lastMessage = prevMessages[prevMessages.length - <span class="hljs-number">1</span>];
                    <span class="hljs-keyword">return</span> [
                        ...prevMessages.slice(<span class="hljs-number">0</span>, <span class="hljs-number">-1</span>),
                        {
                            ...lastMessage,
                            content: lastMessage.content + chunk
                        }
                    ];
                });
            });
    };
}
</code></pre>
<h2 id="heading-chat-application">Chat Application</h2>
<p>I've showed how quickly it is to create a custom chat application and integrate it to <a target="_blank" href="http://watsonx.ai">watsonx.ai</a> using Spring AI and Hilla.</p>
<h3 id="heading-basic-chat">Basic Chat</h3>
<p>The basic chat waits for the AI platform to fully return the response. Thus, waiting time may be longer.</p>
<p><img src="https://foojay.io/wp-content/uploads/2024/12/watsonx-chat.gif" alt /></p>
<h3 id="heading-streaming-chat">Streaming Chat</h3>
<p>The streaming chat responds by chunks and prevents frustration to the end user.</p>
<p><img src="https://foojay.io/wp-content/uploads/2024/12/watsonx-streaming-chat.gif" alt /></p>
<h1 id="heading-summary">Summary</h1>
<p><a target="_blank" href="http://watsonx.ai">watsonx.ai</a> can seamlessly connected to Spring AI and build a chat application with minimal coding changes. Using this platform, we used the IBM Granite model as the foundation model and generated both a basic and streaming response.</p>
<p>For future demonstrations, <a target="_blank" href="http://watsonx.ai">watsonx.ai</a> can be used for RAG, Function Calling (via MistralAI) and Embeddings.</p>
<h1 id="heading-github">GitHub</h1>
<p>You can access my <a target="_blank" href="http://watsonx.ai">watsonx.ai</a> Chat application <a target="_blank" href="https://github.com/rjtmahinay/watsonx-spring-ai-hilla">here</a></p>
<h1 id="heading-references">References</h1>
<ol>
<li><p><strong>Spring AI Documentation</strong> - <a target="_blank" href="https://docs.spring.io/spring-ai/reference/index.html">https://docs.spring.io/spring-ai/reference/index.html</a></p>
</li>
<li><p><a target="_blank" href="http://watsonx.ai"><strong>watsonx.ai</strong></a> <strong>Documentation</strong> - <a target="_blank" href="https://dataplatform.cloud.ibm.com/docs/content/wsj/getting-started/welcome-main.html?context=wx&amp;locale=en&amp;audience=wdp">https://dataplatform.cloud.ibm.com/docs/content/wsj/getting-started/welcome-main.html?context=wx&amp;locale=en&amp;audience=wdp</a></p>
</li>
<li><p><strong>watsonx Developer Hub</strong> - <a target="_blank" href="https://www.ibm.com/watsonx/developer">https://www.ibm.com/watsonx/developer</a></p>
</li>
</ol>
<hr />
<p><em>For more contents and discussion about Java, Cloud and AI. You can follow me on social media accounts via</em> <a target="_blank" href="https://linktr.ee/rjtmahinay?utm_source=linktree_profile_share&amp;ltsid=5ca39f2a-df41-4afc-8259-eab30dd4dda8"><em>LinkTree</em></a></p>
<p><em>Follow and join the J</em><a target="_blank" href="https://linktr.ee/jugph"><em>ava User Group Philippines</em></a> <em>for monthly meetups and community discussions.</em></p>
]]></content:encoded></item><item><title><![CDATA[The Value of Quarkus]]></title><description><![CDATA[This blog is for my talk presented to ING Hub Philippines about the value of Quarkus in business and development. I've shared my personal experience in using this framework and the value it can give to their organization. As of the time of my talk, t...]]></description><link>https://blog.rjtmahinay.com/the-value-of-quarkus</link><guid isPermaLink="true">https://blog.rjtmahinay.com/the-value-of-quarkus</guid><category><![CDATA[Java]]></category><category><![CDATA[quarkus]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[GraalVM]]></category><category><![CDATA[redhat]]></category><dc:creator><![CDATA[Tristan Mahinay]]></dc:creator><pubDate>Sat, 19 Aug 2023 11:11:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1692432595595/269d80a3-2a39-4531-b140-05ebf9edc8ab.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This blog is for my talk presented to <a target="_blank" href="https://www.ing.com/">ING Hub Philippines</a> about the value of Quarkus in business and development. I've shared my personal experience in using this framework and the value it can give to their organization. As of the time of my talk, the framework version was 3.2.0.Final and this is the first LTS version.</p>
<p>The presentation can be accessed in my GitHub Repository: <a target="_blank" href="https://github.com/rjtmahinay/presentations">The Value of Quarkus</a></p>
<p>I've discussed the framework in the following sections:</p>
<ul>
<li><p>What is Quarkus?</p>
</li>
<li><p>Quarkus' Industry Value</p>
</li>
<li><p>Performance</p>
<ul>
<li><p>Quarkus vs Spring Boot</p>
</li>
<li><p>JIT vs AOT</p>
</li>
<li><p>Metrics</p>
</li>
<li><p>AWS Lambda SnapStart</p>
</li>
</ul>
</li>
<li><p>Spring Framework Support</p>
</li>
<li><p>Sustainability</p>
</li>
</ul>
<h1 id="heading-what-is-quarkus">What is Quarkus?</h1>
<p>The framework is called <em>Supersonic. Subatomic. Java.</em> It can be explained into 5 characteristics: <em>Kube-native</em>, <em>Cloud-native</em>, <em>Imperative and Reactive Code,</em> <em>Developer-centric</em>, and <em>Standards</em>.</p>
<h2 id="heading-kube-native">Kube-native</h2>
<p>Quarkus is designed for Kubernetes-based development. It is a framework to leverage the characteristics of Kubernetes specifically for RedHat OpenShift. When developing applications in Quarkus, you're developing as if you're inside the Kubernetes platform due to the usage of YAML files. You can configure the environment directly in Quarkus. Thus, showing Single-step Deployment and Remote Development.</p>
<p>An example YAML file on how to deploy an application and connect to OpenShift automatically.</p>
<pre><code class="lang-yaml"><span class="hljs-string">"%prod"</span><span class="hljs-string">:</span>
  <span class="hljs-attr">quarkus:</span>
    <span class="hljs-attr">kubernetes-client:</span>
      <span class="hljs-attr">trust-certs:</span> <span class="hljs-literal">true</span>
      <span class="hljs-attr">api-server-url:</span> <span class="hljs-string">${OPENSHIFT_URL}</span>
      <span class="hljs-attr">token:</span> <span class="hljs-string">${QUARKUS_KUBERNETES_CLIENT_TOKEN}</span>
    <span class="hljs-attr">openshift:</span>
      <span class="hljs-attr">route:</span>
        <span class="hljs-attr">expose:</span> <span class="hljs-literal">true</span>
      <span class="hljs-attr">env:</span>
        <span class="hljs-attr">secrets:</span> <span class="hljs-string">mysql</span>
    <span class="hljs-attr">kubernetes:</span>
      <span class="hljs-attr">deploy:</span> <span class="hljs-literal">true</span>
    <span class="hljs-attr">s2i:</span>
      <span class="hljs-attr">base-jvm-image:</span> <span class="hljs-string">registry.access.redhat.com/ubi8/openjdk-17:1.16-1</span>
    <span class="hljs-attr">datasource:</span>
      <span class="hljs-attr">db-kind:</span> <span class="hljs-string">mysql</span>
      <span class="hljs-attr">jdbc:</span>
        <span class="hljs-attr">url:</span> <span class="hljs-string">jdbc:mysql://&lt;SQL</span> <span class="hljs-string">Hostname&gt;:3306/demo</span>
      <span class="hljs-attr">password:</span> <span class="hljs-string">${database-password}</span>
      <span class="hljs-attr">username:</span> <span class="hljs-string">${database-user}</span>
</code></pre>
<h2 id="heading-cloud-native">Cloud-native</h2>
<p>Since it is a Kubernetes Java framework, it is optimized to be used in the cloud. It Shows fast startup times, minimal usage of reflection, and support for GraalVM Native compilation. This characteristic is related to the benefits of being a Greener framework.</p>
<h2 id="heading-imperative-and-reactive-code">Imperative and Reactive Code</h2>
<p>Quarkus supports both imperative and reactive programming whether in microservices, event-driven microservices, or serverless architectures. You can code HTTP Microservices, Reactive APIs, and Functions. Quarkus has all extensions for that.</p>
<p>Below are some examples of API coding in Quarkus.</p>
<p><strong>AWS Lambda code using API Gateway</strong></p>
<pre><code class="lang-java"><span class="hljs-meta">@Named("/lambda1")</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Lambda1</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">RequestHandler</span>&lt;<span class="hljs-title">APIGatewayProxyRequestEvent</span>, <span class="hljs-title">APIGatewayProxyResponseEvent</span>&gt; </span>{

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> APIGatewayProxyResponseEvent <span class="hljs-title">handleRequest</span><span class="hljs-params">(APIGatewayProxyRequestEvent request, Context context)</span> </span>{
        String httpMethod = request.getHttpMethod();
        String result = <span class="hljs-string">""</span>;

        <span class="hljs-keyword">if</span> (<span class="hljs-string">"GET"</span>.equals(httpMethod)) {
            <span class="hljs-comment">// Business logic</span>
        }

        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> APIGatewayProxyResponseEvent().withBody(<span class="hljs-string">"Invoked Lambda"</span>)
                        .withStatusCode(<span class="hljs-number">200</span>);
    }
}
</code></pre>
<p><strong>HTTP Microservices</strong></p>
<pre><code class="lang-java"><span class="hljs-meta">@Path("/employee")</span>
<span class="hljs-meta">@ApplicationScoped</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">EmployeeResource</span> </span>{
    <span class="hljs-meta">@Inject</span>
    EmployeeRepository employeeRepository;

    <span class="hljs-meta">@GET</span>
    <span class="hljs-meta">@Produces(MediaType.APPLICATION_JSON)</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;Employee&gt; <span class="hljs-title">getEmployee</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> employeeRepository.listAll();
    }
}
</code></pre>
<p><strong>Reactive Microservices</strong></p>
<pre><code class="lang-java"><span class="hljs-meta">@Path("/employee")</span>
<span class="hljs-meta">@ApplicationScoped</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">EmployeeResource</span> </span>{
    <span class="hljs-meta">@Inject</span>
    EmployeeRepository employeeRepository;

    <span class="hljs-meta">@GET</span>
    <span class="hljs-meta">@Produces(MediaType.APPLICATION_JSON)</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Multi&lt;Employee&gt; <span class="hljs-title">getEmployee</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> Multi.createFrom().items(employeeRepository.streamAll());
    }
}
</code></pre>
<h2 id="heading-developer-centric">Developer-centric</h2>
<p>Quarkus offers a seamless development experience for developers and users. It offers a variety of tools such as live reloading, remote development, Dev UI/Services, Continuous Testing, and Quarkus Extensions.</p>
<p>Dev UI is a local development website typically accessed via http://localhost:8080. It shows the dependency that you've used in your application and the ability to deploy to a cloud platform like RedHat OpenShift automatically.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692437604435/e80c93f0-a32d-40a9-8692-9c138663b8d7.png" alt class="image--center mx-auto" /></p>
<p>Dev Services is Quarkus' ability to give an on-demand environment via TestContainers for common development tools like Databases, Kafka, RabbitMQ, etc. You can check out the documentation in <a target="_blank" href="https://quarkus.io/guides/dev-services">Dev Services</a></p>
<p><a target="_blank" href="https://quarkus.io/extensions/">Quarkus Extensions</a> are external libraries integrated into Quarkus CDI. These are from the <a target="_blank" href="https://github.com/quarkusio/quarkus-platform">Quarkus Platform</a> and <a target="_blank" href="https://github.com/quarkiverse">Quarkiverse</a></p>
<h2 id="heading-standards">Standards</h2>
<p>The framework is backed by industry standards and specifications. Some of these are Vert.x, Eclipse Microprofile, Micrometer, and Jakarta EE.</p>
<h1 id="heading-quarkus-industry-values">Quarkus Industry Values</h1>
<p>The industry values that it can give are based on cost savings, the reduction of the resources needed to deploy an application, and its environmental impact.</p>
<ul>
<li><p><strong>Cost Savings:</strong> Less memory footprint, fast start-up time, and less disk footprint</p>
</li>
<li><p><strong>Speed and Agility:</strong> faster time to market using Quarkus Extension and crafted from well-known libraries which can be easily learned</p>
</li>
<li><p><strong>Standard and Support:</strong> <a target="_blank" href="https://code.quarkus.redhat.com/">RedHat Build Support for Quarkus</a>, an active community with regular releases in GitHub and based on <a target="_blank" href="https://www.cncf.io/">CNCF technologies</a></p>
</li>
<li><p><strong>Sustainability:</strong> Write Greener applications using Quarkus. Due to the minimal reflection and the small memory footprint of Quarkus, the framework shows characteristics of decarbonization.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692440003010/13ae75a7-6ff2-466c-9ab7-19988d722b44.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-performance-metrics">Performance Metrics</h2>
<p>I've presented a comparison of Quarkus to Spring Boot. I compared it to the following metrics:</p>
<ul>
<li><p>Image Size</p>
<ul>
<li>Spring Boot has a lesser size due to reflection. Quarkus performs build-time compilation causing increased image size.</li>
</ul>
</li>
<li><p>Startup Time</p>
<ul>
<li>Quarkus doesn't need anymore to execute always dynamically the metadata of a program. Thus, improving startup times.</li>
</ul>
</li>
<li><p>Memory Usage</p>
<ul>
<li>Quarkus is optimized to reduce its memory usage consumption. The CDI process of Quarkus uses Ahead of Time compilation to minimize the use of reflection.</li>
</ul>
</li>
</ul>
<h1 id="heading-aws-lambda-snapstart">AWS Lambda SnapStart</h1>
<p>The performance of Quarkus and Spring Boot in response time decreased significantly. Although, Spring Boot was 6x more efficient when integrated with SnapStart. While Quarkus had it 2x more efficient.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692442275248/1d9649d6-1b11-4ea3-aaf3-e10cbfc41a38.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-spring-framework-support">Spring Framework Support</h2>
<p>Quarkus support a number of annotations of Spring inside the Quarkus CDI (Quarkus ArC). The documentation can be accessed by clicking the link for each bullet. These can be listed as:</p>
<ul>
<li><p><a target="_blank" href="https://quarkus.io/guides/spring-boot-properties">Spring Boot Properties</a></p>
</li>
<li><p><a target="_blank" href="https://quarkus.io/guides/spring-cache">Spring Cache</a></p>
</li>
<li><p><a target="_blank" href="https://quarkus.io/guides/spring-cloud-config-client">Spring Cloud</a></p>
</li>
<li><p><a target="_blank" href="https://quarkus.io/guides/spring-data-jpa">Spring Data</a> &amp; <a target="_blank" href="https://quarkus.io/guides/spring-data-rest">Data Rest</a></p>
</li>
<li><p><a target="_blank" href="https://quarkus.io/guides/spring-di">Spring Dependency Injection</a></p>
</li>
<li><p><a target="_blank" href="https://quarkus.io/guides/spring-scheduled">Spring Scheduled</a></p>
</li>
<li><p><a target="_blank" href="https://quarkus.io/guides/spring-security">Spring Security</a></p>
</li>
<li><p><a target="_blank" href="https://quarkus.io/guides/spring-web">Spring Web</a></p>
</li>
</ul>
<h2 id="heading-sustainability">Sustainability</h2>
<p>Quarkus offer writing greener applications as prescribed by <a target="_blank" href="https://www.redhat.com/en/resources/greener-java-applications-detail">RedHat Greener Application Executive Summary</a>. In this summary, they compare Quarkus to the energy consumption of a single light bulb, startup times, and the carbon dioxide equivalent (CO2-eq) respectively.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692442975902/b10241b0-67c1-4507-8daf-7d20192c4e7b.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-final-thoughts">Final Thoughts</h1>
<p>In this presentation, I've discussed what will be the benefit of using Quarkus from a developer's perspective. It's not just a seamless development experience but the impact that a developer can give on their organization and the environment.</p>
<p>With the increased modernization and migration of legacy applications to the cloud. We can expect that they will consider a developer-friendly and sustainable framework that can optimize their applications in the cloud.</p>
]]></content:encoded></item><item><title><![CDATA[Taking Red Hat Certified Specialist in Containers and Kubernetes (EX180)]]></title><description><![CDATA[Introduction
In this post, I'll be sharing my experience in taking the Red Hat certification for Containers and Kubernetes using OpenShift Platform v4.10. The certification is different from other cloud certifications since this contains a series of ...]]></description><link>https://blog.rjtmahinay.com/taking-red-hat-certified-specialist-in-containers-and-kubernetes-ex180</link><guid isPermaLink="true">https://blog.rjtmahinay.com/taking-red-hat-certified-specialist-in-containers-and-kubernetes-ex180</guid><category><![CDATA[Cloud]]></category><category><![CDATA[openshift]]></category><category><![CDATA[redhat]]></category><dc:creator><![CDATA[Tristan Mahinay]]></dc:creator><pubDate>Sun, 12 Feb 2023 16:46:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1676201733308/cd4788a4-a723-449a-967a-24a853e3bdbb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>In this post, I'll be sharing my experience in taking the Red Hat certification for Containers and Kubernetes using OpenShift Platform v4.10. The certification is different from other cloud certifications since this contains a series of hands-on tasks.</p>
<p>Since January of 2023, the exam (EX180) is now retired and will be replaced by Red Hat Certified Specialist in Containers (EX188).</p>
<h2 id="heading-preparation">Preparation</h2>
<p>The most recommended learning path to prepare for this certification is to have a <a target="_blank" href="https://www.redhat.com/en/services/training/learning-subscription">RedHat Learning Subscription</a> but you can take other options like Udemy or A Cloud Guru if a learning path is available. Below is a sample screenshot of the Red Hat Learning Paths.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676216946449/5a5db759-761d-4034-91dd-515b8e1cee27.png" alt class="image--center mx-auto" /></p>
<p>The subscription contains paths spanning from OpenShift, Camel, Kafka, Ansible, Quarkus and many more. A lab environment is given which gives you the freedom to play around using the terminal commands. The learning path for this certification is called <strong>Red Hat OpenShift I: Containers &amp; Kubernetes (DO180)</strong>. The overall effort for this module is 24 hours but it took me 1 month to prepare since I tried different Podman and OpenShift commands.</p>
<p>If you want to take your RedHat exam in the comfort of your home, you should read the remote exam <a target="_blank" href="https://www.redhat.com/en/resources/remote-exams-preparation-ebook">guide</a>. You should have a flash drive available for burning the remote exam environment ISO file.</p>
<h2 id="heading-exam-proper">Exam Proper</h2>
<p>The exam consists of 8 tasks based on the objectives described <a target="_blank" href="https://www.redhat.com/en/services/training/ex180-red-hat-certified-specialist-containers-kubernetes-exam?section=objectives">here</a>. The objectives of the new exam (EX188) can be checked <a target="_blank" href="https://www.redhat.com/en/services/training/ex188-red-hat-certified-specialist-containers-exam?section=objectives">here</a>. The following EX180 objectives are.</p>
<ul>
<li><p>Implement images using Podman</p>
</li>
<li><p>Manage images</p>
</li>
<li><p>Run containers locally using Podman</p>
</li>
<li><p>Basic OpenShift knowledge</p>
</li>
<li><p>Creating applications in OpenShift</p>
</li>
<li><p>Troubleshoot applications in OpenShift</p>
</li>
</ul>
<p>The EX188 objectives are quite similar to EX180.</p>
<ul>
<li><p>Implement images using Podman</p>
</li>
<li><p>Manage images</p>
</li>
<li><p>Run containers locally using Podman</p>
</li>
<li><p>Run multi-container applications with Podman</p>
</li>
<li><p>Troubleshoot containerized applications</p>
</li>
</ul>
<p>Some tasks are dependent on each other like running multi-containers in a pod. Check an example of this <a target="_blank" href="https://www.redhat.com/sysadmin/create-containers-podman-quickly">here</a>. It is expected that you have a basic understanding of Linux commands and how to modify a shell script. Below is a sample procedure on how to put a podman command in a shell script.</p>
<p>Running a container using Podman. Let's name it <strong>start-container.sh</strong></p>
<pre><code class="lang-plaintext">#!bin/bash
# This is a sample shell script

podman run -d --name dbcontainer docker.io/mysql:latest
</code></pre>
<p>Running a shell script should be like this.</p>
<pre><code class="lang-bash">sh ./start-container.sh
</code></pre>
<p>You only have 2 hours to finish the exam. If you decided to take it in your home, be ready to have an external camera, a keyboard and mouse, an external monitor and an optional laptop docker. Every hour of the exam, the proctor will request you to scan your room using your external camera.</p>
<p>Tip: The exam is fond of using scripts so practice using Shell. As much as possible, read the requirements carefully. You don't want to start over again on your configurations.</p>
<h2 id="heading-exam-results">Exam Results</h2>
<p>As mentioned by Red Hat, the results will be given within 3 business days but on my end, it was sent after an hour. They will give you your score based on the percentage of each objective. The passing score is 210 over 300 which is 70%. When I took the exam, I got 249 or 83%.</p>
<p>After a while, Credly will issue you a badge and obtain the title: <strong>RedHat Certified Specialist in Containers and Kubernetes</strong>. For EX188, it will be <strong>RedHat Certified Specialist in Containers</strong>.</p>
<h2 id="heading-final-thoughts">Final Thoughts</h2>
<p>In this exam, you will learn how to use the podman and OpenShift basic commands. You will create applications inside OpenShift and how to troubleshoot. The new exam EX188 I think will be the same as EX180 with some tweaks but overall it will have the same objective of using the podman commands and deploying applications in OpenShift.</p>
]]></content:encoded></item><item><title><![CDATA[Modular Monolithic in Practice]]></title><description><![CDATA[With the usage of microservices in application modernization, we have seen both the advantages and disadvantages of maintaining such software development styles.
When we create applications mostly in enterprise organizations, the first thing that com...]]></description><link>https://blog.rjtmahinay.com/modular-monolithic-in-practice</link><guid isPermaLink="true">https://blog.rjtmahinay.com/modular-monolithic-in-practice</guid><category><![CDATA[Java]]></category><category><![CDATA[gradle]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[Spring]]></category><category><![CDATA[Springboot]]></category><dc:creator><![CDATA[Tristan Mahinay]]></dc:creator><pubDate>Thu, 26 Jan 2023 17:13:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1674752838502/0e8ac3ab-b43c-4810-92e0-d04322eb3ffa.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>With the usage of microservices in application modernization, we have seen both the advantages and disadvantages of maintaining such software development styles.</p>
<p>When we create applications mostly in enterprise organizations, the first thing that comes to our mind now is how to decouple our applications.</p>
<p>But there will be times when creating too many microservices is not the best way and may cost you time and money.</p>
<p>Because of that, one alternative is to leverage the use of modules.</p>
<h2 id="heading-modules">Modules</h2>
<p>Modularity is a concept that is used to build applications to separate logical units through modules, giving you <em>highly cohesive</em> code.</p>
<p>These modules are analogous to a compartment where you put a specific feature of your application.</p>
<p>Creating modules has different benefits during software development, whether ground-up or maintenance.</p>
<h2 id="heading-modular-monolithic">Modular Monolithic</h2>
<p>Modular Monolithic is an architectural style where your code is structured on the concept of modules.</p>
<p>It separates your functions into different logical units but still in a single application.</p>
<p>You can describe this as a composition of directories and those inner directories contain your working code.</p>
<p>In practice, this style is used when you don't want to manage different applications as seen in microservice development. Below are some reasons why to use Modular Monolithic.</p>
<ul>
<li><p>Single deployment - your code can be deployed to the cloud without configuring and maintaining too many applications. These can be seen in batch and some microservice applications.</p>
</li>
<li><p>Issues of third-party dependency - imagine you have more than 5 applications with library violations using GitLab or JFrog Xray for example, these can be a big pain for the developers.</p>
</li>
<li><p>Greenfield Development - when starting a new application we wouldn't want to build our applications immediately in microservice. This may cause over-engineering and high maintenance costs for no reason.</p>
</li>
<li><p>Cost of developers - Too many services are costly to an organization. This can be seen when the organization is in the stage of budgeting and has few developers in place.</p>
</li>
</ul>
<h2 id="heading-architecture">Architecture</h2>
<p>The architecture of the Modular Monolithic is quite simple. It's in a single project with different components separated into a well-defined logical directory. The modules or projects (for multi-module) define their way to prevent leaking of their implementation. The multi-module can define what to expose via the custom configuration of Gradle while Spring Modulith leverages the use of <em>internal</em> modules.</p>
<p>This can be deployed to the cloud using a single Dockerfile or a Multi-container approach using Docker Compose or Kubernetes-based technology. The application used in this demonstration is Spring and Gradle and a new module under Spring Framework called <a target="_blank" href="https://spring.io/projects/spring-modulith">Spring Modulith</a><em>.</em></p>
<h3 id="heading-multi-module">Multi-Module</h3>
<p><img src="https://foojay.io/wp-content/uploads/2023/01/modular-monolithic-gradle-700x455.png" alt="Gradle Multi-module" /></p>
<p>If you want to create and deploy a modular monolithic application, you can use a common approach used by developers called multi-module approach. This can be done using the build management tools like Maven or Gradle. In this post, we will be dealing with Gradle.</p>
<p>In the architecture above we can see that the application consists of 3 different projects inside a main project called <em>modular-monolithic-gradle</em>. The 3 projects are called sub-projects and can define what to expose to other projects.</p>
<p>The <em>common</em> project also called <em>shared</em> project which contains global or redundant codes that can be seen when you have too many service modules.</p>
<p>The <em>service</em> project may contain codes for a specific domain. In this case, its sole responsibility is to manage the functionality regarding Employee. You can have many services based on your use case.</p>
<p>The <em>application</em> project is your main project that will invoke your services and behaves like a <em>Service Locator</em>. See a simple introduction to this pattern <a target="_blank" href="https://www.geeksforgeeks.org/service-locator-pattern/">here</a>. In Spring, the call for different services can be done using <em>@Qualifier</em> annotations and extending a base service.</p>
<p>Sub-modules themselves can have their Gradle lifecycle which is controlled by their build file. In there, you can define what to expose or not.</p>
<h3 id="heading-spring-modulith">Spring Modulith</h3>
<p><img src="https://foojay.io/wp-content/uploads/2023/01/modular-monolithic-modulith-700x341.png" alt="Spring Modulith Architecture" /></p>
<p>Spring Modulith is an experimental project by Spring that can be used for modular monolithic applications. Its feature is to have a well-defined modular structure for Spring Beans and have control over what to expose or not.</p>
<p>Here we have the same structure as the multi-module above but using different packages and a main project (main package) only. We can hide some functionalities like the code for repositories or the model classes. Thus, controlling how you will expose your beans. You can expose many services here too and hide their respective persistence and view layer via a package called <em>internal</em>.</p>
<p>For scenarios where you want to create another service, you can just create another one under the com.rjtmahinay (main package) and can be called to other services (other service packages).</p>
<p>Although under the hood, Spring Modulith uses the multi-module approach too in its respective sub-functionalities. This technology can help us improve the way we create modules, especially in Spring.</p>
<h3 id="heading-cloud-deployment">Cloud Deployment</h3>
<p><img src="https://foojay.io/wp-content/uploads/2023/01/modular-monolithic-deployment.png" alt="Modular Monolithic Cloud Deployment" /></p>
<p>So far I've discussed the approaches to create a modular monolithic application using the common and a new approach. This time the architecture above shows the <em>single deployment</em> benefit of modular monolithic.</p>
<p>To deploy your application to the cloud, you can do the single Dockerfile deployment which contains a single image of your application or deploy it in a multi-container style which can be done by a single image (single jar) or multi-image (multiple jars). The multi-module approach can deploy the sub-projects as a multi-container deployment since it can have its image (jar file). For Spring Modulith, since internally it can be a multi-module, the modulith application can still be deployed in single or multiple deployments.</p>
<h2 id="heading-final-thoughts">Final Thoughts</h2>
<p>Understandably, developers will opt for microservices since it gives the flexibility of technology to be used, style of deployment and decoupling of functionalities.</p>
<p>But we need to remember that all software requirements don't need to be created in a microservice fashion.</p>
<p>Problems arise when microservices become a Distributed Monolithic, which defeats its purpose.</p>
<p>In this post, I've presented an option called Modular Monolithic which is an alternative for the complexity seen in microservices and how modularity can be integrated into your software requirements.</p>
<h2 id="heading-further-reading">Further Reading</h2>
<ul>
<li><p><a target="_blank" href="https://docs.spring.io/spring-modulith/docs/current/reference/html/">Spring Modulith Reference Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://www.jrebel.com/blog/what-is-a-modular-monolith#when-to-use-modular-monoliths">Modular Monolithic by JRebel</a></p>
</li>
<li><p><a target="_blank" href="https://docs.gradle.org/current/userguide/multi_project_builds.html">Gradle Multi-module</a></p>
</li>
</ul>
<p><em>Originally published on</em> <a target="_blank" href="https://foojay.io/today/modular-monolithic-in-practice/"><em>Foojay.io</em></a></p>
]]></content:encoded></item><item><title><![CDATA[Micronaut: Yet Another Java  Framework]]></title><description><![CDATA[Introduction
With the rise of application modernization in the cloud, Java position itself by having different frameworks that can produce lightweight applications in the cloud to minimize memory consumption and quick application start-up.
In this po...]]></description><link>https://blog.rjtmahinay.com/micronaut-java-framework</link><guid isPermaLink="true">https://blog.rjtmahinay.com/micronaut-java-framework</guid><category><![CDATA[Java]]></category><category><![CDATA[Micronaut]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[Microservices]]></category><dc:creator><![CDATA[Tristan Mahinay]]></dc:creator><pubDate>Wed, 11 Jan 2023 20:22:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1673523724496/ef662e77-e09a-4669-9ece-17d3bb04d1d9.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>With the rise of application modernization in the cloud, Java position itself by having different frameworks that can produce lightweight applications in the cloud to minimize memory consumption and quick application start-up.</p>
<p>In this post, I'm gonna explain the codes presented in my demonstration:</p>
<p><a target="_blank" href="https://github.com/rjtmahinay/micronaut-java">Micronaut Demo</a></p>
<h3 id="heading-what-is-micronaut">What is Micronaut?</h3>
<p>Micronaut is a full-stack framework for building microservice and serverless applications. It leverages the use of compile-time inversion of control that results in quick start-up and low memory footprint.</p>
<p>Significant features of this framework to others like Spring Boot:</p>
<ul>
<li><p>Reduced Memory Footprint</p>
</li>
<li><p>Quick startup time</p>
</li>
<li><p>Minimal use of runtime reflection and proxies</p>
</li>
<li><p>Leverages AOT (Ahead of Time) compilation</p>
</li>
<li><p>Doesn't depend any more to the size of the codebase</p>
</li>
</ul>
<p>As of the writing, the version of Micronaut is 3.8.0. Also, Micronaut's annotation design is very similar to Spring Boot. Thus, a minimal learning curve for Spring Developers 😁</p>
<h2 id="heading-create-your-application">👨🏻‍💻 Create your application!</h2>
<p>To create a Micronaut application, you can create it via CLI or the Launcher site.</p>
<h3 id="heading-cli"><strong>CLI</strong></h3>
<p>You can start by downloading Micronaut CLI <a target="_blank" href="https://micronaut.io/download/">here</a>. After installing you can create your app using the command below:</p>
<pre><code class="lang-bash">mn create-app  example-app --features &lt;additional dependencies&gt;
</code></pre>
<p>the <em>--features</em> option lets you add dependencies other than the Micronaut native features. After creating the app a micronaut-cli.yml file is created where it shows the information about the project you've created. Below is an example of the contents of the YAML file.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">applicationType:</span> <span class="hljs-string">default</span>
<span class="hljs-attr">defaultPackage:</span> <span class="hljs-string">com.rjtmahinay</span>
<span class="hljs-attr">testFramework:</span> <span class="hljs-string">junit</span>
<span class="hljs-attr">sourceLanguage:</span> <span class="hljs-string">java</span>
<span class="hljs-attr">buildTool:</span> <span class="hljs-string">gradle</span>
<span class="hljs-attr">features:</span> [<span class="hljs-string">annotation-api</span>, <span class="hljs-string">app-name</span>, <span class="hljs-string">data</span>, <span class="hljs-string">data-jpa</span>, <span class="hljs-string">gradle</span>, <span class="hljs-string">h2</span>, <span class="hljs-string">http-client</span>, <span class="hljs-string">jackson-databind</span>, <span class="hljs-string">java</span>, <span class="hljs-string">java-application</span>, <span class="hljs-string">jdbc-hikari</span>, <span class="hljs-string">junit</span>, <span class="hljs-string">logback</span>, <span class="hljs-string">micronaut-build</span>, <span class="hljs-string">netty-server</span>, <span class="hljs-string">openapi</span>, <span class="hljs-string">readme</span>, <span class="hljs-string">shade</span>, <span class="hljs-string">swagger-ui</span>, <span class="hljs-string">yaml</span>]
</code></pre>
<h3 id="heading-micronaut-launcher"><strong>Micronaut Launcher</strong></h3>
<p>In this approach, you will be shown a user interface to create your Micronaut application with ease. The launcher can be found <a target="_blank" href="https://micronaut.io/launch">here</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673463870586/e0fb006b-8ef4-4b5e-b950-739839cfb1a2.png" alt class="image--center mx-auto" /></p>
<p>As you can see the launcher design used is familiar to us and is also similar to Spring Initialzr's website. You can see that it has a feature button where you can add your project's dependencies. A preview is also shown for you to have a glimpse of what files are created. When generating your project either you can download the file or push it to a GitHub repository.</p>
<h2 id="heading-lets-start-coding">👨🏻‍💻 Let's start coding!</h2>
<p>The main entry application of Micronaut will be a class that invokes the Micronaut class. Below is a simple entry code to run the application.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Application</span> </span>{

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Micronaut.run(Application.class, args);
    }
}
</code></pre>
<p>If you want to access the different arguments that you can pass to Micronaut's application context. You can use the builder approach.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Application</span> </span>{

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Micronaut.build(args)
                .mainClass(Application.class)
                .eagerInitSingletons(<span class="hljs-keyword">true</span>)
                .start();

    }
}
</code></pre>
<h3 id="heading-creating-a-bean">Creating a Bean</h3>
<p>In Micronaut you can create your beans inside a configuration called Factory. This factory class will load your specified beans. It is the counterpart of <strong>Configuration</strong> in Spring. Below are some used annotations for bean creation.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Factory</span> <span class="hljs-comment">// The configuration annotation to create your beans</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ApplicationConfiguration</span> </span>{

    <span class="hljs-meta">@Singleton</span> <span class="hljs-comment">// Create a single instance of a bean</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> EmployeeBean <span class="hljs-title">singletonBean</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> EmployeeBean();
    }

    <span class="hljs-meta">@Bean</span> <span class="hljs-comment">// Create a copy of bean for every invocation</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> EmployeeBean <span class="hljs-title">bean</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> EmployeeBean();
    }

    <span class="hljs-meta">@Prototype</span> <span class="hljs-comment">// Similar to @Bean</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> EmployeeBean <span class="hljs-title">prototypeBean</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> EmployeeBean();
    }

    <span class="hljs-meta">@Context</span> <span class="hljs-comment">// Create a bean upon start of ApplicationContext</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> EmployeeBean <span class="hljs-title">contextBean</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> EmployeeBean();
    } 
}
</code></pre>
<h3 id="heading-autowire-a-bean">Autowire a bean</h3>
<p>In Spring we use the Autowired annotation but in Micronaut it leverages the use of <strong>Inject</strong> of <em>jakarta</em> annotations library.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Inject</span> <span class="hljs-comment">// Autowires your bean in the ApplicationContext</span>
<span class="hljs-keyword">private</span> EmployeeBean singletonBean;
</code></pre>
<h3 id="heading-creating-properties">Creating Properties</h3>
<p>Just like in Spring Boot, we want to configure our custom property class. It uses the same syntax in Spring called <strong>ConfigurationProperties</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// The value of the annotation is the name of your property</span>
<span class="hljs-meta">@ConfigurationProperties("example")</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">EmployeeProperties</span> </span>{
    <span class="hljs-keyword">private</span> String value;
}
</code></pre>
<p>You can also get the value directly</p>
<pre><code class="lang-java"><span class="hljs-comment">// Using an expression language, you can get the value of a property</span>
<span class="hljs-meta">@Value("${example.value}")</span>
<span class="hljs-keyword">private</span> String value;
</code></pre>
<h3 id="heading-define-your-dto">Define your DTO</h3>
<p>You can use a DTO to map your JSON request and pass it to persistence layer model. Here we encounter the annotations <strong>Serdeable</strong> and <strong>Introspected.</strong></p>
<p>In Java 17, you can now use records as your request/response model. This removes the use of <a target="_blank" href="https://projectlombok.org/">Lombok</a> library for most cases.</p>
<p>Other annotations like <strong>NotEmpty</strong> and <strong>DecimalMin</strong> are part of <em>javax</em> validations.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Serdeable</span> <span class="hljs-comment">// Used for JSON serialization</span>
<span class="hljs-meta">@Introspected</span> <span class="hljs-comment">// Used for introspecting your beans in compile-time</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> record <span class="hljs-title">EmployeeDto</span><span class="hljs-params">(<span class="hljs-meta">@JsonProperty</span> <span class="hljs-meta">@NotEmpty</span> String name, <span class="hljs-meta">@JsonProperty</span> String address, <span class="hljs-meta">@JsonProperty</span> String position, <span class="hljs-meta">@JsonProperty</span> <span class="hljs-meta">@DecimalMin("1.0")</span> BigDecimal salary)</span> </span>{
}
</code></pre>
<h3 id="heading-the-persistence-layer">The Persistence Layer</h3>
<p>The persistence layer is composed of the repository and its entity. The library used is the Micronaut Data JPA</p>
<h4 id="heading-define-your-entity">Define your entity</h4>
<p>Defining your entity is similar to using the basic JPA format where you initialize it using <strong>Entity</strong> and <strong>Table.</strong> The difference here is you must annotate your class using <strong>Serdeable</strong> for compile-time serialization.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Serdeable</span> <span class="hljs-comment">// Used for compile-time serialization</span>
<span class="hljs-meta">@Setter</span>
<span class="hljs-meta">@Getter</span>
<span class="hljs-meta">@Entity</span> <span class="hljs-comment">// Defines your class as a database entity</span>
<span class="hljs-meta">@Table(name = "EMPLOYEE")</span> <span class="hljs-comment">// Annotation to map the class as your table</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Employee</span> </span>{
    <span class="hljs-meta">@Id</span>
    <span class="hljs-meta">@GeneratedValue(strategy = GenerationType.AUTO)</span>
    <span class="hljs-meta">@Column(name = "ID", nullable = false, insertable = false, updatable = false)</span>
    <span class="hljs-keyword">private</span> Long id;

    <span class="hljs-meta">@Column(name = "NAME")</span>
    <span class="hljs-keyword">private</span> String name;

    <span class="hljs-comment">// Removed other attributes for brevity   </span>
}
</code></pre>
<p>Define your repository</p>
<p>Micronaut supports Synchronous and Reactive repositories. These can be extended by the following interfaces. The annotation is similar to Spring's repository.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Repository</span> <span class="hljs-comment">// Used for defining the class as repository</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">SynchronousEmployeeRepository</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">JpaRepository</span>&lt;<span class="hljs-title">Employee</span>, <span class="hljs-title">Long</span>&gt; </span>{ 

     <span class="hljs-meta">@Query("SELECT e FROM Employee e")</span> <span class="hljs-comment">// Use to define your own query</span>
     <span class="hljs-function">List&lt;Employee&gt; <span class="hljs-title">findAllEmployee</span><span class="hljs-params">()</span></span>;
}
</code></pre>
<p>Below can return a type of Reactor's Flux (for list and streams) or Mono (single object).</p>
<pre><code class="lang-java"><span class="hljs-meta">@Repository</span> <span class="hljs-comment">// Used for defining the class as repository</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">ReactiveEmployeeRepository</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ReactorCrudRepository</span>&lt;<span class="hljs-title">Employee</span>, <span class="hljs-title">Long</span>&gt; </span>{

    <span class="hljs-meta">@Query("SELECT e FROM Employee e")</span> <span class="hljs-comment">// Use to define your own query</span>
    <span class="hljs-function">Flux&lt;Employee&gt; <span class="hljs-title">findAllEmployee</span><span class="hljs-params">()</span></span>;
}
</code></pre>
<h3 id="heading-the-service-layer">The Service Layer</h3>
<p>The concept of the service layer is mostly used in the time of Monolithic Architecture which uses the MVC Design Pattern. Although there is no <strong>Service</strong> annotation in Micronaut, you can use the existing <strong>Singleton</strong> to create your service. After all, services are used as beans.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">SynchronousEmployeeService</span> </span>{
    <span class="hljs-function">Optional&lt;Employee&gt; <span class="hljs-title">getEmployee</span><span class="hljs-params">(Long id)</span></span>;

    <span class="hljs-comment">// Removed other functions for brevity</span>
}
</code></pre>
<pre><code class="lang-java"><span class="hljs-meta">@Singleton</span> <span class="hljs-comment">// Make your service as a bean</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SynchronousEmployeeServiceImpl</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">SynchronousEmployeeService</span> </span>{
    <span class="hljs-meta">@Inject</span>
    <span class="hljs-keyword">private</span> SynchronousEmployeeRepository synchronousEmployeeRepository;

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Optional&lt;Employee&gt; <span class="hljs-title">getEmployee</span><span class="hljs-params">(Long id)</span> </span>{
        <span class="hljs-keyword">return</span> synchronousEmployeeRepository.findById(id);
    }

    <span class="hljs-comment">// Removed other logic for brevity</span>
}
</code></pre>
<h3 id="heading-the-controller-layer">The Controller Layer</h3>
<p>This consists of your API definitions in Micronaut. It is similar to Spring's <strong>Controller</strong> but the difference is you need an additional <strong>RestController</strong> for your return type to be serialized. In Micronaut, it is already done by one annotation.</p>
<pre><code class="lang-java"><span class="hljs-comment">// Used for making the API managed by Micronaut threading</span>
<span class="hljs-meta">@ExecuteOn(TaskExecutors.IO)</span>
<span class="hljs-comment">// The controller annotation with the define root URI</span>
<span class="hljs-meta">@Controller("/v1/synchronous/employee")</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SynchronousEmployeeController</span> </span>{
    <span class="hljs-comment">// Removed logic for brevity</span>
}
</code></pre>
<h4 id="heading-get">GET</h4>
<p>This will return a serialized response and may be used using a Query Parameter or Path Parameter. Notice that you don't need an extra annotation for defining a Path Parameter, Micronaut already handles it.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Get(uri = "/{id}", produces = MediaType.APPLICATION_JSON)</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> Optional&lt;Employee&gt; <span class="hljs-title">getEmployee</span><span class="hljs-params">(Long id)</span> </span>{
    <span class="hljs-keyword">return</span> employeeService.getEmployee(id);
}
</code></pre>
<h4 id="heading-post">POST</h4>
<p>This will invoke an add operation to your persistence layer and custom response. The additional <strong>Body</strong> annotation can be optionally removed since Micronaut knows that it is your request body. The <strong>Valid</strong> annotation asserts that your request body should be validated.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Post(uri = "/add", consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON)</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> Employee <span class="hljs-title">createEmployee</span><span class="hljs-params">(<span class="hljs-meta">@Body</span> <span class="hljs-meta">@Valid</span> EmployeeDto employeeDto)</span> </span>{
    <span class="hljs-keyword">return</span> employeeService.addEmployee(employeeDto);
}
</code></pre>
<h4 id="heading-put">PUT</h4>
<p>This will invoke an update to your data. In the case of combining a Path Parameter and Request Body. You can define it using <strong>PathVariable</strong> (similar to Spring) and <strong>Body</strong>.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Put(uri = "/update/{id}", consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON)</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> Employee <span class="hljs-title">updateEmployee</span><span class="hljs-params">(<span class="hljs-meta">@PathVariable</span> Long id, <span class="hljs-meta">@Body</span> <span class="hljs-meta">@Valid</span> EmployeeDto employeeDto)</span> </span>{
    <span class="hljs-keyword">return</span> employeeService.updateEmployee(id, employeeDto);
}
</code></pre>
<h4 id="heading-delete">DELETE</h4>
<p>This will invoke a deletion of your data.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Delete(uri = "/delete/{id}", consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON)</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">deleteEmployee</span><span class="hljs-params">(Long id)</span> </span>{
    employeeService.deleteEmployee(id);
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Successfully deleted"</span>;
}
</code></pre>
<h3 id="heading-caching">Caching</h3>
<p>Sometimes you want to put a cache for method calls in your API. This is usually applied to your API methods. This can be done in Micronaut using the annotations below.</p>
<pre><code class="lang-java"><span class="hljs-comment">// Stores the data in the specified cache name</span>
<span class="hljs-meta">@CachePut("synchronous-employee")</span>

<span class="hljs-comment">// Invalidates all the stored cache by name</span>
<span class="hljs-meta">@CacheInvalidate("synchronous-employee")</span>
</code></pre>
<h3 id="heading-exceptions">Exceptions</h3>
<p>Handling exceptions in Micronaut can be done using the <strong>Error</strong> annotation or the custom one. Below is a method defined in a controller.</p>
<pre><code class="lang-bash">@Error
public HttpResponse&lt;JsonError&gt; error(HttpRequest&lt;?&gt; request, Throwable e) {
    JsonError error = new JsonError(<span class="hljs-string">"Exception in Synchronous Controller: "</span> + e.getMessage())
            .link(Link.SELF, Link.of(request.getUri()));

    <span class="hljs-built_in">return</span> HttpResponse.&lt;JsonError&gt;serverError()
            .body(error);
}
</code></pre>
<p>If you want it to be used in all controllers, just set a value of <em>global=true</em> in the annotation.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Error(global = true)</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> HttpResponse&lt;JsonError&gt; <span class="hljs-title">error</span><span class="hljs-params">(HttpRequest&lt;?&gt; request, Throwable e)</span> </span>{
    <span class="hljs-comment">// your logic</span>
}
</code></pre>
<p>You can also create your custom exceptions. Here it states that it requires an EmployeeException to invoke.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Singleton</span>
<span class="hljs-comment">// Equivalent annotation of @ConditionalOn*** in Spring</span>
<span class="hljs-meta">@Requires(classes = EmployeeException.class)</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">EmployeeExceptionHandler</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ExceptionHandler</span>&lt;<span class="hljs-title">EmployeeException</span>, <span class="hljs-title">HttpResponse</span>&lt;?&gt;&gt; </span>{

    <span class="hljs-meta">@Inject</span>
    <span class="hljs-keyword">private</span> ErrorResponseProcessor&lt;?&gt; errorResponseProcessor;

    <span class="hljs-meta">@Override</span>
    <span class="hljs-keyword">public</span> HttpResponse&lt;?&gt; handle(HttpRequest request, EmployeeException exception) {
        <span class="hljs-keyword">return</span> errorResponseProcessor.processResponse(
                ErrorContext.builder(request)
                        .cause(exception)
                        .errorMessage(<span class="hljs-string">"Handled by custom handler"</span>).build(),
                HttpResponse.badRequest());
    }
}
</code></pre>
<p>For this to work, you must disable the HTTP Client Exception property.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">micronaut:</span>
    <span class="hljs-attr">http:</span>
      <span class="hljs-attr">client:</span>
        <span class="hljs-attr">exception-on-error-status:</span> <span class="hljs-literal">true</span>
</code></pre>
<h2 id="heading-running-the-application">👨🏻‍💻 Running the application</h2>
<p>You can run the application using the build management tool. For this demo, I've used Gradle as my build management tool. You can run your newly created application via the command below:</p>
<pre><code class="lang-bash">./gradlew run
</code></pre>
<p>After running you can see that the startup time of Micronaut is as twice low as Spring Boot. This is the power of Ahead of Time compilation.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673467859535/0aba03f7-c650-4fcf-b69c-aa498c268c95.png" alt class="image--center mx-auto" /></p>
<p>Micronaut supports docker build images in Gradle Plugin which you can use</p>
<p>For standard docker image</p>
<pre><code class="lang-bash">./gradlew dockerBuild
</code></pre>
<p>For GraalVM Native Image</p>
<pre><code class="lang-bash">./gradlew dockerBuildNative
</code></pre>
<h2 id="heading-final-thoughts">💭 Final Thoughts</h2>
<p>Micronaut is a promising microservice and serverless framework in the Java space. It leverages the use of compile-time inversion of control with very minimal reflection. We want a lightweight and quick startup time application when deploying to the cloud. If you're creating a new service in your organization, Micronaut will be one of the good choices.</p>
<h2 id="heading-further-reading">📝Further Reading</h2>
<p>Check out the Micronaut's documentation for more information</p>
<ul>
<li><p><a target="_blank" href="https://docs.micronaut.io/latest/guide/">Micronaut Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://docs.micronaut.io/3.8.0/guide/configurationreference.html">Micronaut Configuration References</a></p>
</li>
<li><p><a target="_blank" href="https://micronaut.io/blog/">Official Micronaut Blogs</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[AWS Lambda SnapStart using Micronaut]]></title><description><![CDATA[Recently AWS announced in re:Invent 2022 the AWS Lambda SnapStart feature. This feature improves the cold startup performance of Java applications which can be done by supported cloud-native frameworks like Spring Boot, Quarkus and Micronaut.
In this...]]></description><link>https://blog.rjtmahinay.com/aws-lambda-snapstart-using-micronaut</link><guid isPermaLink="true">https://blog.rjtmahinay.com/aws-lambda-snapstart-using-micronaut</guid><category><![CDATA[Micronaut]]></category><category><![CDATA[AWS]]></category><category><![CDATA[aws lambda]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[Cloud Computing]]></category><dc:creator><![CDATA[Tristan Mahinay]]></dc:creator><pubDate>Sun, 04 Dec 2022 14:35:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1670164535213/cHIU1WbMw.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Recently AWS announced in re:Invent 2022 the AWS Lambda SnapStart feature. This feature improves the cold startup performance of Java applications which can be done by supported cloud-native frameworks like Spring Boot, Quarkus and Micronaut.</p>
<p>In this post, we'll see how it performs using Micronaut and the JDK runtime version used is Java 11 (Amazon Corretto).</p>
<h2 id="heading-a-simple-architecture">A simple architecture</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1670159955042/S9dBH08Ga.jpg" alt /></p>
<p>The architecture above shows that we will invoke a POST request via the API Gateway and it will be processed by our Lambda function using Micronaut. This function will be invoked a thousand times and with the help of AWS CloudWatch Logs and Insights, we can create a conclusion on SnapStart's performance.</p>
<h2 id="heading-how-to-enable-lambda-snapstart">How to enable Lambda SnapStart?</h2>
<p>Initially, when we create a function, SnapStart is disabled. This is a function called On-Demand.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1670160580267/BPUvdpKiU.png" alt /></p>
<p>SnapStart will work in two things, you should <strong>Enable SnapStart</strong> and <strong>publish a new version</strong> of it. You can create an alias to be used as a new target of your API Gateway.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1670160863346/e_w_gsXds.png" alt /></p>
<p>An example alias pointing to the new version.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1670160911853/pSsdWditI.png" alt /></p>
<h2 id="heading-request-invocation">Request Invocation</h2>
<p>I've created a simple POST request which has a query parameter, name.</p>
<p><code>?name=Tristan</code></p>
<p>The response to this request will be a JSON body with string transformation (concatenate the name with Hi).</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"message"</span>: <span class="hljs-string">"Hi Tristan"</span>
}
</code></pre>
<h3 id="heading-micronaut-code">Micronaut Code</h3>
<p>The string transformation will be handled by a simple Micronaut Lambda code as seen below.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Slf4j</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FunctionRequestHandler</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">MicronautRequestHandler</span>&lt;<span class="hljs-title">APIGatewayProxyRequestEvent</span>, <span class="hljs-title">APIGatewayProxyResponseEvent</span>&gt; </span>{
    <span class="hljs-meta">@Inject</span>
    ObjectMapper objectMapper;

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> APIGatewayProxyResponseEvent <span class="hljs-title">execute</span><span class="hljs-params">(APIGatewayProxyRequestEvent input)</span> </span>{
        Map&lt;String, String&gt; inputParam = input.getQueryStringParameters();
        APIGatewayProxyResponseEvent response = <span class="hljs-keyword">new</span> APIGatewayProxyResponseEvent();
        <span class="hljs-keyword">try</span> {
            String json = objectMapper.writeValueAsString(
                    Collections.singletonMap(<span class="hljs-string">"message"</span>, <span class="hljs-string">"Hi "</span> + inputParam.get(<span class="hljs-string">"name"</span>)));
            response.setStatusCode(<span class="hljs-number">200</span>);
            response.setBody(json);
        } <span class="hljs-keyword">catch</span> (JsonProcessingException e) {
            response.setStatusCode(<span class="hljs-number">500</span>);
        }
        <span class="hljs-keyword">return</span> response;
    }
}
</code></pre>
<p>The function will accept an APIGatewayProxyRequestEvent which holds the query parameter object as a Map. We will retrieve the value via the name key. The response will be the name and the appended Hi word.</p>
<h2 id="heading-load-testing-using-apache-jmeter">Load Testing using Apache JMeter</h2>
<p>To test the performance of this new feature. I've used JMeter as my load testing tool to invoke a concurrent request of 50 threads and 1000 loops which spans around ~5-10mins. Both the SnapStart and On-demand invocation of Lambda was tested by these constraints.</p>
<h2 id="heading-insights">Insights</h2>
<p>Using CloudWatch logs and insights, I've performed some monitoring metrics for durations as prescribed in <a target="_blank" href="https://docs.aws.amazon.com/lambda/latest/dg/snapstart-monitoring.html">SnapStart Monitoring</a> and got the different percentiles for each configuration.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Configuration</td><td>50th percentile</td><td>99.9th percentile</td></tr>
</thead>
<tbody>
<tr>
<td>Standard (On-demand)</td><td>3077.39ms</td><td>3278.32ms</td></tr>
<tr>
<td>SnapStart - Enabled</td><td>482.11ms</td><td>678.03ms</td></tr>
</tbody>
</table>
</div><h2 id="heading-final-thoughts">Final Thoughts</h2>
<p>This blog post shows the results of a simple Micronaut Function Application for Serverless by comparing the Lambda configuration with or without SnapStart enabled. We can see the app's latency improved due to ahead-of-time initialization optimization.</p>
<h2 id="heading-further-reading">Further Reading</h2>
<p>For more information about Lambda SnapStart you can check out the ff. links</p>
<ul>
<li><p><a target="_blank" href="https://docs.aws.amazon.com/lambda/latest/dg/snapstart.html">Improving startup performance with Lambda SnapStart</a></p>
</li>
<li><p><a target="_blank" href="https://aws.amazon.com/blogs/compute/starting-up-faster-with-aws-lambda-snapstart/">Starting up faster with AWS Lambda SnapStart</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[AWS Solutions Architect Associate (SAA-C03) 2022: Passing the exam]]></title><description><![CDATA[Introduction
I recently cleared SAA-CO3 which was updated by AWS last Aug 30, 2022. The exam update comprises of increased enterprise demand for optimizations in fast-changing areas such as security, resiliency, data volume, cost optimization, and th...]]></description><link>https://blog.rjtmahinay.com/aws-solutions-architect-associate</link><guid isPermaLink="true">https://blog.rjtmahinay.com/aws-solutions-architect-associate</guid><category><![CDATA[AWS]]></category><category><![CDATA[AWS Certified Solutions Architect Associate]]></category><dc:creator><![CDATA[Tristan Mahinay]]></dc:creator><pubDate>Thu, 24 Nov 2022 13:23:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1669308708710/wV44keNlF.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>I recently cleared SAA-CO3 which was updated by AWS last Aug 30, 2022. The exam update comprises of increased enterprise demand for optimizations in fast-changing areas such as security, resiliency, data volume, cost optimization, and the design of high-performance systems by <a target="_blank" href="https://aws.amazon.com/blogs/training-and-certification/aws-certified-solutions-architect-associate-exam-updated-to-align-with-latest-trends-and-innovations/">AWS Certification and Training</a></p>
<p>The exam still consist of 65 questions with 15 unknown unscored questions to be used by AWS for performance evaluation and as a future question, in short 50 questions is the total scored questions. Target takers of this exam may be a developer or architect interested in using AWS services.</p>
<h2 id="heading-preparation">Preparation</h2>
<p>To prepare for this challenging certification, I highly recommend to take the course of Stephane Maarek below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1669292052823/OLT6PueRk.png" alt="image.png" /></p>
<p>This course primarily focuses in the certification questions. He also showed different diagrams that can help you familiarize different AWS architectures (combination of AWS services and how they work). If you want a full practice exam to maximize your chance in passing the exam, you can check out the course below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1669292227092/FiA34tuW-.png" alt="image.png" /></p>
<h4 id="heading-recommendation-style-for-studying-this-course">Recommendation style for studying this course</h4>
<p>This exam is a challenging one and you need time for you to have a better grasp of different AWS services and how they connect to each other. I finished studying the course in a month also spent reading twice the course material for better understanding. To do this I did the following:</p>
<ul>
<li>Spent ~1-2 hours of studying each day</li>
<li>Go back to a specific chapter where you have confusion with</li>
<li>Give yourself a break to absorb the knowledge of each chapter</li>
<li>Don't forget to have a good sleep before studying!</li>
</ul>
<h2 id="heading-exam-proper-experience">Exam Proper Experience</h2>
<p>The exam last for 2 hours 10 minutes but you can extend for another 30 minutes if you are a Non-English native speaker by applying ESL in the AWS certification website. The content of the exam showed on my end focuses mostly in the following topics.</p>
<ul>
<li>IAM and Security Groups</li>
<li>AWS KMS, AWS Server-side Encryption and Server-side Encryption - Customer Managed</li>
<li>VPC<ul>
<li>VPC Peering</li>
<li>VPC Endpoints</li>
</ul>
</li>
<li>S3<ul>
<li>Storage Classes</li>
<li>Static Website Hosting</li>
<li>Cross-region/Same-region replication</li>
</ul>
</li>
<li>EC2 Instances<ul>
<li>EC2 Instances Purchasing Options</li>
</ul>
</li>
<li>CloudFront<ul>
<li>S3 Origin Access Identity</li>
</ul>
</li>
<li>Global Accelerator</li>
<li>AWS Rekognition, Comprehend and Comprehend Medical</li>
<li>AWS Lambda with combination of AWS Application-Load Balancer and AWS WAF</li>
<li>AWS Network Load Balancer</li>
<li>API Gateway</li>
<li>AWS Shield Standard and Advanced</li>
<li>CloudWatch, CloudTrail and Amazon Eventbridge</li>
<li>RDS Databases (Mostly MySQL) and DynamoDB</li>
<li>Aurora Database</li>
<li>Elasticache and DynamoDB Accelerator (DAX)</li>
<li>Amazon Elastic Container Service (ECS)</li>
<li>Amazon Kinesis Data streams and Data Firehose</li>
</ul>
<p>The point of the exam is to use the above services with the following domains in this link: <a target="_blank" href="https://d1.awsstatic.com/training-and-certification/docs-sa-assoc/AWS-Certified-Solutions-Architect-Associate_Exam-Guide.pdf">AWS Solutions Architect Exam Guide</a></p>
<ol>
<li>Design Secure Architectures</li>
<li>Design Resilient Architectures</li>
<li>Design High-Performing Architectures</li>
<li>Design Cost-Optimized Architectures </li>
</ol>
<h2 id="heading-final-thoughts">Final thoughts</h2>
<p>The exam needs to have a good preparation for you to pass as this was designed for the candidate to fail. Having a thorough understanding of the services and some practice gives you an edge to pass the exam. Fortunately, AWS preparation courses are available on the internet and gives you a higher chance to pass.</p>
]]></content:encoded></item><item><title><![CDATA[Cloud: Why learn it now?]]></title><description><![CDATA[Let's start!
What is Cloud Computing
According to NIST (National Institute of Standards and Technology)

 a model for enabling ubiquitous, convenient, on-demand network access to a shared
pool of configurable computing resources (e.g., networks, serv...]]></description><link>https://blog.rjtmahinay.com/cloud-why-learn-it-now</link><guid isPermaLink="true">https://blog.rjtmahinay.com/cloud-why-learn-it-now</guid><category><![CDATA[cloudcertifications]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[Cloud Computing]]></category><category><![CDATA[Certification]]></category><category><![CDATA[AWS certification]]></category><dc:creator><![CDATA[Tristan Mahinay]]></dc:creator><pubDate>Sun, 30 Oct 2022 01:48:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/9AqIdzEc9pY/upload/v1667093727842/r2GqM--nW.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-lets-start">Let's start!</h1>
<h2 id="heading-what-is-cloud-computing">What is Cloud Computing</h2>
<p>According to <strong>NIST</strong> (National Institute of Standards and Technology)</p>
<blockquote>
<p> a model for enabling ubiquitous, convenient, on-demand network access to a shared
pool of configurable computing resources (e.g., networks, servers, storage, applications, and services) that
can be rapidly provisioned and released with minimal management effort or service provider interaction.
This cloud model is composed of five essential characteristics, three service models, and four deployment
models</p>
</blockquote>
<h3 id="heading-main-characteristics-of-cloud">Main characteristics of cloud</h3>
<ul>
<li><p><strong>On-demand self-service</strong> - Automatic provisioning of the underlying computing resources without human interaction</p>
</li>
<li><p><strong>Broader network access</strong> - Can be access with multiple platforms</p>
</li>
<li><p><strong>Resource pooling </strong> - Multiple customers are served within the same resources with security and privacy</p>
</li>
<li><p><strong>Rapid Elasticity</strong> - Acquire and dispose resources based on demand</p>
</li>
<li><p><strong>Measure Service</strong> - Bill only the used resources by the customers</p>
</li>
</ul>
<h3 id="heading-service-models">Service Models</h3>
<p>The different models describe who manages the different resources in the cloud. Both the cloud provider and customer shares a responsibility in the platform.</p>
<ul>
<li><p><strong>IaaS</strong> (Infrastructure-as-a-Service)</p>
<ul>
<li>The cloud provider is responsible in provisioning the  underlying <strong>virtualization, servers, storage and networking</strong></li>
<li>The customer is responsible in maintaining <strong>applications, data, runtime, middleware and OS </strong></li>
</ul>
</li>
<li><p><strong>PaaS</strong> (Platform-as-a-Service)</p>
<ul>
<li>The cloud provider is responsible in provisioning the  underlying <strong> runtime, middleware, OS, virtualization, servers, storage and networking</strong></li>
<li>The customer is responsible in maintaining <strong>applications and data</strong></li>
</ul>
</li>
<li><p><strong>SaaS</strong> (Infrastructure-as-a-Service)</p>
<ul>
<li>The cloud provider is responsible in provisioning all the underlying resources</li>
<li>The customer access the application provided by the provider</li>
</ul>
</li>
</ul>
<h2 id="heading-why-deal-with-the-cloud-now">Why deal with the cloud now?</h2>
<p>Cloud is an exciting domain to pursue and compose of different professions (at least in my organization). Dealing with this now is a great investment to your career also it is fun to use a cloud infrastructure. These are the known professions that I've encountered in a pro-cloud organization.</p>
<ul>
<li><p><strong>Cloud Architects</strong> - Obviously, this will be the first role which you will encounter in an organization both big or small. These people handles the tech standards and business side of things. They present the most cost-effective approach using the right Cloud Platform</p>
</li>
<li><p><strong>Cloud Developers</strong> - Develop and maintain applications using cloud technologies</p>
</li>
<li><p><strong>Cloud Administrators</strong> - Configure and maintain the hardware aspects using different cloud services</p>
</li>
<li><p><strong>Cloud Security Engineers</strong> - Builds and maintains security of a cloud platform</p>
</li>
</ul>
<h2 id="heading-application-modernization">Application Modernization</h2>
<p>Modernizing applications from on-premise to cloud is a trend right now and most of the organizations are starting to do it. A <a target="_blank" href="https://www.konveyor.io/modernization-report/">report</a> from Konveyor showing the current state of modernization in different regions. It stated the six modernization strategies used by different organizations.</p>
<ul>
<li><p><strong>Retire </strong>- Decommission applications that are not in used</p>
</li>
<li><p><strong>Retain</strong> - Leave critical applications since it may be refactored</p>
</li>
<li><p><strong>Rehost</strong> - Transfer on-premise applications to cloud with no significant code change</p>
</li>
<li><p><strong>Replatform</strong> - Use cloud migration strategies to enable cloud-specific components in your application</p>
</li>
<li><p><strong>Refactor</strong> - Modify the existing application code to take advantage the Microservice or Serverless architecture</p>
</li>
<li><p><strong>Repurchase</strong> - Use of SaaS (Software-as-a-Service) model</p>
</li>
</ul>
<h1 id="heading-fundamentals-certifications">Fundamentals Certifications</h1>
<p>There are different cloud certifications that you can take and start to learn with. Most of top certifications are from AWS, Azure, Google Cloud and Oracle Cloud. I took most of the certifications and the required trainings to easily pass them all.</p>
<ul>
<li><p>AWS Cloud Practitioner - <a target="_blank" href="https://www.udemy.com/course/aws-certified-cloud-practitioner-new/">AWS CCP Course</a></p>
</li>
<li><p>Microsoft Azure - <a target="_blank" href="https://www.udemy.com/user/scottduffy2/">Azure Fundamentals Courses</a></p>
</li>
<li><p>Google Cloud - <a target="_blank" href="https://www.udemy.com/course/google-cloud-digital-leader-certification/">GCP Digital Leader</a></p>
</li>
<li><p>Oracle Cloud Infrastructure - <a target="_blank" href="https://mylearn.oracle.com/course/oracle-cloud-infrastructure-foundations">OCI Foundations</a></p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667093611158/qm-_mmvIR.png" alt="current_badges.png" /></p>
<h1 id="heading-what-are-you-waiting-for">What are you waiting for?</h1>
<p>Join now the club of developers who enthusiastically learn and contribute in the cloud domain. Cloud computing is a promising field and it will be for the next upcoming years. Start your cloud journey now!</p>
]]></content:encoded></item><item><title><![CDATA[My experience in taking OCP Java SE 11 Developer]]></title><description><![CDATA[Introduction
As an experienced Java Developer, It was an opportunity for me to take the discounted exam (90% off) starting from February 25 to April 25 of 2021. The discounted exam was due to the Java 25th Anniversary. I ended up scoring 76% and it w...]]></description><link>https://blog.rjtmahinay.com/rjtmahinay-java-11-developer</link><guid isPermaLink="true">https://blog.rjtmahinay.com/rjtmahinay-java-11-developer</guid><category><![CDATA[java11]]></category><category><![CDATA[Java]]></category><category><![CDATA[Certification]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[Tristan Mahinay]]></dc:creator><pubDate>Tue, 25 Oct 2022 00:57:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1669308891312/w4wX4wHiL.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction">Introduction</h1>
<p>As an experienced Java Developer, It was an opportunity for me to take the discounted exam (90% off) starting from February 25 to April 25 of 2021. The discounted exam was due to the Java 25th Anniversary. I ended up scoring <strong>76%</strong> and it was a nice experience that made me more understand Java and the new features of version 11.</p>
<h1 id="heading-preparation">Preparation</h1>
<p>I've prepared for the exam about 1.5 months and I used the book of Boyarsky and Selikoff, <a target="_blank" href="https://www.amazon.com/Oracle-Certified-Professional-Developer-Complete/dp/1119619130">OCP 11 Study Guide</a>. This book covers almost all of the topics that you will encounter in the exam. Since some of the chapters of the book was hard to understand, I sometimes re-read again a specific chapter.</p>
<p>Since I've already took an OCA for Java 8. These are the chapters that I've studied for this exam:</p>
<p>Chapter 2
Chapter 11
Chapters 12 - 22
After reading each chapter, I immediately took the review questions so I can assess if I understood the module. Also at the end of the book, you can register and access for the Sybex Online Test Bank which is valid in 1 year upon your registration.</p>
<h1 id="heading-before-the-exam">Before The Exam</h1>
<p>The exam can be taken in Pearson VUE website where you will schedule and pick if you're going to take via online or onsite. After that, you must do a system check if your current device is working properly.</p>
<h1 id="heading-the-exam">The Exam</h1>
<p>OCP Java 11 SE Developer has no exam prerequisites, unlike the previous exams that you must take first the OCA exam. I took the exam online because of COVID-19 restrictions. But I prefer taking exams onsite.</p>
<p>The exam consist of 50 questions under 90 minutes which is different to previous OCP exams that has 85 questions under 150 minutes. Exam objectives that I've encountered are as follows:</p>
<ul>
<li>Concurrency</li>
<li>Functional Programming (Lambda and Stream API)</li>
<li>Java Fundamentals (Operators and Core Java API)</li>
<li>Annotations</li>
<li>JDBC</li>
<li>Security</li>
<li>NIO.2</li>
<li>I/O</li>
<li>Exceptions</li>
<li>Modules</li>
</ul>
<p>The exam was slightly hard since you need to think of the answer for each question under 2 minutes. I mark a question For review when it took me already more than a minute just to answer. The exam proctor is usually strict for unnecessary movements you make during the exam. After answering and reviewing all the answers, you can submit and can see the results immediately.</p>
<h1 id="heading-summary">Summary</h1>
<p>The exam is not easy and you need to prepare for it. Luckily, certification books of Boyarsky and Selikoff exists. Their book contains questions that is already hard and can make you really prepare for the exam. In the end, you must manage and give time in studying for the certification.</p>
]]></content:encoded></item></channel></rss>