<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://www.thecodinganalyst.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.thecodinganalyst.com/" rel="alternate" type="text/html" /><updated>2026-05-10T01:56:45+00:00</updated><id>https://www.thecodinganalyst.com/feed.xml</id><title type="html">TheCodingAnalyst</title><subtitle>This is my technical blog where I log all the learnings so that I  can refer to when I need them, because who can remember everything? </subtitle><author><name>Dennis Cai</name></author><entry><title type="html">Interviewing Software Engineers</title><link href="https://www.thecodinganalyst.com/blog/Interviewing-software-engineer/" rel="alternate" type="text/html" title="Interviewing Software Engineers" /><published>2026-01-10T00:00:00+00:00</published><updated>2026-01-10T00:00:00+00:00</updated><id>https://www.thecodinganalyst.com/blog/Interviewing-software-engineer</id><content type="html" xml:base="https://www.thecodinganalyst.com/blog/Interviewing-software-engineer/"><![CDATA[<p>Hiring the right software engineers is one of the highest leverage decisions an engineering organization can make. In the book Software Engineering at Google, Google emphasizes that software engineering is not just about writing code — it is about building maintainable systems, collaborating effectively, scaling engineering practices, and sustaining long-term velocity. A strong engineer improves not only the codebase, but also the quality of discussions, system design decisions, testing culture, operational stability, and mentorship within the team. Conversely, hiring the wrong engineer creates long-term costs that are often invisible at first: fragile systems, technical debt, poor maintainability, weak testing practices, and reduced team productivity. Interviews therefore should not be treated as a checklist exercise, but as a way to evaluate how someone will perform in actual engineering work.</p>

<p><strong>What Not To Do During Interviews</strong></p>

<p>One of the biggest mistakes companies make during interviews is asking shallow technology checklist questions. Questions such as “Have you used Spring Boot?”, “Do you know React?”, or “Have you worked with Kubernetes?” reveal almost nothing about actual engineering capability. A candidate may have used a technology for years without deeply understanding it, while another candidate may have learned it recently but understands the underlying engineering concepts far better.</p>

<p>Similarly, asking purely theoretical questions like:</p>

<ul>
  <li>What are the SOLID principles?</li>
  <li>What is Dependency Injection?</li>
  <li>What is DRY?</li>
</ul>

<p>often tests memorization rather than engineering judgment. Many candidates can recite textbook definitions perfectly while failing to apply those principles in real systems.</p>

<p>Software engineering is ultimately about implementation trade-offs, maintainability, debugging, testing, and collaboration under constraints — not theory recitation.</p>

<p>Another questionable practice is over-reliance on online coding assessments and algorithm platforms such as LeetCode. While algorithms and data structures do matter for certain domains, most real-world engineering work does not involve solving obscure graph problems or reversing binary trees within 20 minutes under pressure.</p>

<p>Real engineers work with existing codebases, debug production issues, write tests, review pull requests, and improve maintainability. Excessive emphasis on puzzle-solving often filters for candidates who are good at interview preparation rather than candidates who are good at engineering.</p>

<p>Interviews should resemble actual work as closely as possible.</p>

<p>Another common mistake is conducting interviews in an adversarial manner, where interviewers attempt to “catch” candidates making mistakes instead of understanding how they think and collaborate. Good interviews should evaluate reasoning, communication, adaptability, and engineering maturity — not create artificial stress.</p>

<p><strong>What Categories Should Be Tested</strong></p>

<p>The first category should always focus on the actual languages, frameworks, and technologies used in the real project. If the project uses Java, Spring Boot, React, GraphQL, or Kubernetes, then the interview should naturally revolve around realistic scenarios involving those technologies.</p>

<p>Instead of asking abstract trivia questions, use examples based on actual engineering problems the team encounters.</p>

<p>One of the best approaches is to use a simplified subset of the real project codebase. Take a real function or service that contains meaningful complexity and ask the candidate to work with it.</p>

<p>The code could intentionally contain:</p>

<ul>
  <li>Poor naming</li>
  <li>Duplicated logic</li>
  <li>Tight coupling</li>
  <li>Missing error handling</li>
  <li>Performance problems</li>
  <li>Hidden bugs</li>
</ul>

<p>Ask the candidate how they would improve the code, refactor it, debug it, or redesign parts of it. This evaluates practical engineering ability far more effectively than theoretical questions.</p>

<p>It also reveals how candidates think about:</p>

<ul>
  <li>Readability</li>
  <li>Maintainability</li>
  <li>Scalability</li>
  <li>Testing</li>
  <li>Engineering trade-offs</li>
</ul>

<p><strong>Automated Testing Matters</strong></p>

<p>Another highly important category is automated testing. Many engineers claim to value testing, but interviews rarely evaluate whether they can actually write good tests.</p>

<p>Give candidates a realistic piece of code and ask them to write unit tests for it. However, the goal should not be writing tests purely for coverage numbers.</p>

<p>Good engineers understand that tests should validate:</p>

<ul>
  <li>Behavior</li>
  <li>Business logic</li>
  <li>Edge cases</li>
  <li>Failure scenarios</li>
</ul>

<p>rather than implementation details.</p>

<p>Strong candidates usually identify meaningful assertions naturally. They also understand when mocking is appropriate and when excessive mocking makes tests brittle and meaningless.</p>

<p>Testing ability is often one of the strongest indicators of engineering maturity.</p>

<p><strong>Test Adaptability and Learning Ability</strong></p>

<p>Another category that is frequently overlooked is adaptability and learning capability.</p>

<p>Technology changes constantly, and engineers will inevitably encounter unfamiliar tools, frameworks, or architectures. Instead of only testing existing knowledge, introduce the candidate to something they have not used before and ask how they would approach learning and implementing it.</p>

<p>For example, ask questions such as:</p>

<ul>
  <li>What steps would you take to understand it?</li>
  <li>How would you validate whether it is suitable?</li>
  <li>What documentation or resources would you look for?</li>
  <li>How would you prototype or test it?</li>
  <li>What would you do if your initial approach failed?</li>
  <li>How would you troubleshoot issues during implementation?</li>
</ul>

<p>This evaluates problem-solving ability, resourcefulness, and engineering mindset far better than memorized answers.</p>

<p>Strong engineers are not defined by knowing everything already — they are defined by how effectively they can learn, adapt, debug, and deliver solutions when facing unfamiliar problems.</p>

<p><strong>Final Thoughts</strong></p>

<p>A good software engineering interview should mirror actual engineering work. It should evaluate how candidates think, communicate, debug, test, improve systems, and adapt to change.</p>

<p>The goal is not to find candidates who can memorize definitions or solve artificial puzzles under pressure.</p>

<p>The goal is to identify engineers who can contribute meaningfully to real systems, collaborate effectively with teams, and continuously improve both the codebase and the engineering culture around them.</p>]]></content><author><name>Dennis Cai</name></author><category term="Blog" /><category term="Software Engineering" /><category term="Interviewing" /><category term="Hiring" /><category term="Engineering Culture" /><summary type="html"><![CDATA[Hiring the right software engineers is one of the highest leverage decisions an engineering organization can make. In the book Software Engineering at Google, Google emphasizes that software engineering is not just about writing code — it is about building maintainable systems, collaborating effectively, scaling engineering practices, and sustaining long-term velocity. A strong engineer improves not only the codebase, but also the quality of discussions, system design decisions, testing culture, operational stability, and mentorship within the team. Conversely, hiring the wrong engineer creates long-term costs that are often invisible at first: fragile systems, technical debt, poor maintainability, weak testing practices, and reduced team productivity. Interviews therefore should not be treated as a checklist exercise, but as a way to evaluate how someone will perform in actual engineering work. What Not To Do During Interviews One of the biggest mistakes companies make during interviews is asking shallow technology checklist questions. Questions such as “Have you used Spring Boot?”, “Do you know React?”, or “Have you worked with Kubernetes?” reveal almost nothing about actual engineering capability. A candidate may have used a technology for years without deeply understanding it, while another candidate may have learned it recently but understands the underlying engineering concepts far better. Similarly, asking purely theoretical questions like: What are the SOLID principles? What is Dependency Injection? What is DRY? often tests memorization rather than engineering judgment. Many candidates can recite textbook definitions perfectly while failing to apply those principles in real systems. Software engineering is ultimately about implementation trade-offs, maintainability, debugging, testing, and collaboration under constraints — not theory recitation. Another questionable practice is over-reliance on online coding assessments and algorithm platforms such as LeetCode. While algorithms and data structures do matter for certain domains, most real-world engineering work does not involve solving obscure graph problems or reversing binary trees within 20 minutes under pressure. Real engineers work with existing codebases, debug production issues, write tests, review pull requests, and improve maintainability. Excessive emphasis on puzzle-solving often filters for candidates who are good at interview preparation rather than candidates who are good at engineering. Interviews should resemble actual work as closely as possible. Another common mistake is conducting interviews in an adversarial manner, where interviewers attempt to “catch” candidates making mistakes instead of understanding how they think and collaborate. Good interviews should evaluate reasoning, communication, adaptability, and engineering maturity — not create artificial stress. What Categories Should Be Tested The first category should always focus on the actual languages, frameworks, and technologies used in the real project. If the project uses Java, Spring Boot, React, GraphQL, or Kubernetes, then the interview should naturally revolve around realistic scenarios involving those technologies. Instead of asking abstract trivia questions, use examples based on actual engineering problems the team encounters. One of the best approaches is to use a simplified subset of the real project codebase. Take a real function or service that contains meaningful complexity and ask the candidate to work with it. The code could intentionally contain: Poor naming Duplicated logic Tight coupling Missing error handling Performance problems Hidden bugs Ask the candidate how they would improve the code, refactor it, debug it, or redesign parts of it. This evaluates practical engineering ability far more effectively than theoretical questions. It also reveals how candidates think about: Readability Maintainability Scalability Testing Engineering trade-offs Automated Testing Matters Another highly important category is automated testing. Many engineers claim to value testing, but interviews rarely evaluate whether they can actually write good tests. Give candidates a realistic piece of code and ask them to write unit tests for it. However, the goal should not be writing tests purely for coverage numbers. Good engineers understand that tests should validate: Behavior Business logic Edge cases Failure scenarios rather than implementation details. Strong candidates usually identify meaningful assertions naturally. They also understand when mocking is appropriate and when excessive mocking makes tests brittle and meaningless. Testing ability is often one of the strongest indicators of engineering maturity. Test Adaptability and Learning Ability Another category that is frequently overlooked is adaptability and learning capability. Technology changes constantly, and engineers will inevitably encounter unfamiliar tools, frameworks, or architectures. Instead of only testing existing knowledge, introduce the candidate to something they have not used before and ask how they would approach learning and implementing it. For example, ask questions such as: What steps would you take to understand it? How would you validate whether it is suitable? What documentation or resources would you look for? How would you prototype or test it? What would you do if your initial approach failed? How would you troubleshoot issues during implementation? This evaluates problem-solving ability, resourcefulness, and engineering mindset far better than memorized answers. Strong engineers are not defined by knowing everything already — they are defined by how effectively they can learn, adapt, debug, and deliver solutions when facing unfamiliar problems. Final Thoughts A good software engineering interview should mirror actual engineering work. It should evaluate how candidates think, communicate, debug, test, improve systems, and adapt to change. The goal is not to find candidates who can memorize definitions or solve artificial puzzles under pressure. The goal is to identify engineers who can contribute meaningfully to real systems, collaborate effectively with teams, and continuously improve both the codebase and the engineering culture around them.]]></summary></entry><entry><title type="html">The importance of writing unit tests</title><link href="https://www.thecodinganalyst.com/blog/writing-unit-tests/" rel="alternate" type="text/html" title="The importance of writing unit tests" /><published>2025-07-29T00:00:00+00:00</published><updated>2025-07-29T00:00:00+00:00</updated><id>https://www.thecodinganalyst.com/blog/writing-unit-tests</id><content type="html" xml:base="https://www.thecodinganalyst.com/blog/writing-unit-tests/"><![CDATA[<p>In modern software development, writing code without tests is like building a house without a blueprint or safety checks. You might finish faster, but you’re gambling with stability, maintainability, and trust. Among all types of testing, unit tests are the foundation of a reliable codebase — quick to write, fast to run, and easy to reason about. Yet many developers still see them as optional or write them reactively.</p>

<p>Let’s break down why unit tests matter, and why your goal should be near-total coverage, only making exceptions when absolutely necessary.</p>

<h3 id="-what-are-unit-tests-really">✅ What Are Unit Tests, Really?</h3>
<p>A unit test is a piece of code that verifies the behavior of the smallest testable part of your application — typically a function, method, or class — in isolation. It checks one thing, with no external dependencies (like databases, networks, or file systems). It tells you immediately if a unit of code behaves as expected under certain conditions.</p>

<h3 id="️-unit-tests-are-like-seat-belts-in-a-racing-car">🏎️ Unit Tests Are Like Seat Belts in a Racing Car</h3>
<p>Imagine a professional race car driver about to take on a high-speed track. Without a seat belt, even the best driver in the world will instinctively hold back. Why? Because there’s no margin for error. One slip, and the consequences are catastrophic.</p>

<p>Now add a seat belt — snug, secure, and crash-tested. Suddenly, the driver gains confidence. They can take sharper turns, go faster, and push the limits of the car, knowing they have a safety mechanism in place.</p>

<p>Unit tests are that seat belt for your code.</p>

<p>They don’t stop accidents, but they reduce the cost of failure. They give you the confidence to move faster, refactor aggressively, and experiment — because if something goes wrong, your tests will catch it before anyone else does.</p>

<h3 id="-unit-tests-are-about-quality--not-just-safety">🎯 Unit Tests Are About Quality — Not Just Safety</h3>
<p>In project management, quality is defined as:</p>

<p>“The degree to which a set of inherent characteristics of the project deliverables and processes fulfill requirements.”</p>

<p>This definition highlights that quality is not subjective — it’s measured by how well a product meets functional and non-functional requirements.</p>

<p>Unit tests enforce this quality.</p>

<p>They verify that each component behaves as expected, ensuring your deliverables meet the defined requirements at the micro level. A system without unit tests may still compile and run — but you have no guarantee that it does the right thing. Without tests, you’re relying on hope instead of proof.</p>

<p>In this light, unit testing isn’t just a technical practice — it’s a quality management practice. And just like quality in manufacturing or construction, it’s non-negotiable if you want reliable results.</p>

<h3 id="-why-unit-testing-is-non-negotiable">🔍 Why Unit Testing Is Non-Negotiable</h3>
<ol>
  <li>
    <p>Prevents Bugs Early
Unit tests catch regressions and logical errors before your application ever reaches QA or production. Finding bugs early is not only cheaper — it avoids fire-fighting and user complaints later on.</p>
  </li>
  <li>
    <p>Supports Confident Refactoring
With good test coverage, you can refactor with peace of mind. Like a seat belt, your tests give you assurance that you won’t crash the system while optimizing or rewriting code.</p>
  </li>
  <li>
    <p>Improves Design
Testable code is often better designed. It’s more modular, has fewer side effects, and adheres to principles like Single Responsibility and Dependency Injection. Writing tests forces you to think about your architecture.</p>
  </li>
  <li>
    <p>Documents Behavior
Tests are live documentation that explain how a function is supposed to behave — more accurate and useful than outdated wiki pages or code comments.</p>
  </li>
  <li>
    <p>Speeds Up Development Over Time
At first, writing tests might seem like overhead. But with a comprehensive test suite, you can make changes quickly and ship features faster — because you’re not constantly worried about breaking things.</p>
  </li>
</ol>

<h3 id="-why-aim-for-100-or-near-100-test-coverage">🎯 Why Aim for 100% (or Near-100%) Test Coverage?</h3>
<p>Striving for 100% unit test coverage is less about vanity metrics and more about discipline and completeness. Every uncovered line of code is a potential point of failure. Here’s why that near-total coverage matters:</p>

<ul>
  <li>
    <p>Uncovered Code Is Untested Code
If a line isn’t covered by any test, it means you’ve never verified how it behaves. That’s a risk, especially when onboarding new team members or making large-scale changes.</p>
  </li>
  <li>
    <p>Edge Cases Live in the Shadows
Most bugs don’t happen in the “happy path.” Reaching high coverage forces you to consider unusual inputs, boundary conditions, and failure scenarios.</p>
  </li>
  <li>
    <p>Legacy Code Is Harder to Modernize Without It
If you ever plan to rewrite, modularize, or extract services from a legacy system, having thorough tests makes that possible without breaking production.</p>
  </li>
</ul>

<h3 id="-when-100-isnt-practical">🚫 When 100% Isn’t Practical</h3>
<p>There are times when 100% coverage is not worth the tradeoff:</p>

<p>Auto-generated code (e.g., by frameworks or tools)</p>

<p>Trivial boilerplate (e.g., simple getters/setters or toString() methods)</p>

<p>Low-level integration glue that’s better tested via integration or end-to-end tests</p>

<p>Code with external dependencies where mocking is more complex than value-add</p>

<p>The key is to be intentional about what’s not tested. You should be able to explain why, not just because it was too hard or forgotten.</p>

<h3 id="-best-practices-for-achieving-high-coverage">💡 Best Practices for Achieving High Coverage</h3>
<p>Test as you go: Don’t wait until the end. Write tests alongside your code (TDD, or at least test-after).</p>

<p>Use mocking wisely: Mock external systems, but not your own business logic.</p>

<p>Use coverage tools: Tools like JaCoCo, Istanbul, or Coverage.py help visualize what’s missing.</p>

<p>Review test quality, not just quantity: 100% coverage with poor assertions is worse than 80% with meaningful tests.</p>

<h3 id="-final-thoughts">🧠 Final Thoughts</h3>
<p>High unit test coverage isn’t about checking a box — it’s about building a foundation of quality and confidence. It enables faster delivery, fewer bugs, and sustainable development. Like a racing seat belt, it lets you move fast and take risks — safely.</p>

<p>And when viewed through the lens of project management, unit tests aren’t just a technical safeguard. They’re a quality assurance measure. They help ensure that what you build actually fulfills the requirements — both stated and implied.</p>

<p>You don’t need to dogmatically hit 100%, but you should aim for it as the norm, not the exception. If a line isn’t worth testing, ask why it’s there at all.</p>]]></content><author><name>Dennis Cai</name></author><category term="Blog" /><category term="Unit Test" /><category term="Testing" /><summary type="html"><![CDATA[In modern software development, writing code without tests is like building a house without a blueprint or safety checks. You might finish faster, but you’re gambling with stability, maintainability, and trust. Among all types of testing, unit tests are the foundation of a reliable codebase — quick to write, fast to run, and easy to reason about. Yet many developers still see them as optional or write them reactively. Let’s break down why unit tests matter, and why your goal should be near-total coverage, only making exceptions when absolutely necessary. ✅ What Are Unit Tests, Really? A unit test is a piece of code that verifies the behavior of the smallest testable part of your application — typically a function, method, or class — in isolation. It checks one thing, with no external dependencies (like databases, networks, or file systems). It tells you immediately if a unit of code behaves as expected under certain conditions. 🏎️ Unit Tests Are Like Seat Belts in a Racing Car Imagine a professional race car driver about to take on a high-speed track. Without a seat belt, even the best driver in the world will instinctively hold back. Why? Because there’s no margin for error. One slip, and the consequences are catastrophic. Now add a seat belt — snug, secure, and crash-tested. Suddenly, the driver gains confidence. They can take sharper turns, go faster, and push the limits of the car, knowing they have a safety mechanism in place. Unit tests are that seat belt for your code. They don’t stop accidents, but they reduce the cost of failure. They give you the confidence to move faster, refactor aggressively, and experiment — because if something goes wrong, your tests will catch it before anyone else does. 🎯 Unit Tests Are About Quality — Not Just Safety In project management, quality is defined as: “The degree to which a set of inherent characteristics of the project deliverables and processes fulfill requirements.” This definition highlights that quality is not subjective — it’s measured by how well a product meets functional and non-functional requirements. Unit tests enforce this quality. They verify that each component behaves as expected, ensuring your deliverables meet the defined requirements at the micro level. A system without unit tests may still compile and run — but you have no guarantee that it does the right thing. Without tests, you’re relying on hope instead of proof. In this light, unit testing isn’t just a technical practice — it’s a quality management practice. And just like quality in manufacturing or construction, it’s non-negotiable if you want reliable results. 🔍 Why Unit Testing Is Non-Negotiable Prevents Bugs Early Unit tests catch regressions and logical errors before your application ever reaches QA or production. Finding bugs early is not only cheaper — it avoids fire-fighting and user complaints later on. Supports Confident Refactoring With good test coverage, you can refactor with peace of mind. Like a seat belt, your tests give you assurance that you won’t crash the system while optimizing or rewriting code. Improves Design Testable code is often better designed. It’s more modular, has fewer side effects, and adheres to principles like Single Responsibility and Dependency Injection. Writing tests forces you to think about your architecture. Documents Behavior Tests are live documentation that explain how a function is supposed to behave — more accurate and useful than outdated wiki pages or code comments. Speeds Up Development Over Time At first, writing tests might seem like overhead. But with a comprehensive test suite, you can make changes quickly and ship features faster — because you’re not constantly worried about breaking things. 🎯 Why Aim for 100% (or Near-100%) Test Coverage? Striving for 100% unit test coverage is less about vanity metrics and more about discipline and completeness. Every uncovered line of code is a potential point of failure. Here’s why that near-total coverage matters: Uncovered Code Is Untested Code If a line isn’t covered by any test, it means you’ve never verified how it behaves. That’s a risk, especially when onboarding new team members or making large-scale changes. Edge Cases Live in the Shadows Most bugs don’t happen in the “happy path.” Reaching high coverage forces you to consider unusual inputs, boundary conditions, and failure scenarios. Legacy Code Is Harder to Modernize Without It If you ever plan to rewrite, modularize, or extract services from a legacy system, having thorough tests makes that possible without breaking production. 🚫 When 100% Isn’t Practical There are times when 100% coverage is not worth the tradeoff: Auto-generated code (e.g., by frameworks or tools) Trivial boilerplate (e.g., simple getters/setters or toString() methods) Low-level integration glue that’s better tested via integration or end-to-end tests Code with external dependencies where mocking is more complex than value-add The key is to be intentional about what’s not tested. You should be able to explain why, not just because it was too hard or forgotten. 💡 Best Practices for Achieving High Coverage Test as you go: Don’t wait until the end. Write tests alongside your code (TDD, or at least test-after). Use mocking wisely: Mock external systems, but not your own business logic. Use coverage tools: Tools like JaCoCo, Istanbul, or Coverage.py help visualize what’s missing. Review test quality, not just quantity: 100% coverage with poor assertions is worse than 80% with meaningful tests. 🧠 Final Thoughts High unit test coverage isn’t about checking a box — it’s about building a foundation of quality and confidence. It enables faster delivery, fewer bugs, and sustainable development. Like a racing seat belt, it lets you move fast and take risks — safely. And when viewed through the lens of project management, unit tests aren’t just a technical safeguard. They’re a quality assurance measure. They help ensure that what you build actually fulfills the requirements — both stated and implied. You don’t need to dogmatically hit 100%, but you should aim for it as the norm, not the exception. If a line isn’t worth testing, ask why it’s there at all.]]></summary></entry><entry><title type="html">Hibernate Save Aggregation Issue: Why Your Test Fails Intermittently and How to Fix It</title><link href="https://www.thecodinganalyst.com/knowledgebase/hibernate-save-aggregation-issue/" rel="alternate" type="text/html" title="Hibernate Save Aggregation Issue: Why Your Test Fails Intermittently and How to Fix It" /><published>2025-04-22T00:00:00+00:00</published><updated>2025-04-22T00:00:00+00:00</updated><id>https://www.thecodinganalyst.com/knowledgebase/hibernate-save-aggregation-issue</id><content type="html" xml:base="https://www.thecodinganalyst.com/knowledgebase/hibernate-save-aggregation-issue/"><![CDATA[<h3 id="-the-problem-an-intermittently-failing-test-in-hibernate">🚨 The Problem: An Intermittently Failing Test in Hibernate</h3>

<p>When using Spring Data JPA and Hibernate, you might encounter <strong>intermittent test failures</strong> even when your logic seems correct. Consider the following typical test case implementation:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Test</span>
<span class="kt">void</span> <span class="nf">findAllByModifiedAtAfter</span><span class="o">()</span> <span class="o">{</span>
    <span class="c1">// Setup</span>
    <span class="nc">Book</span> <span class="n">book</span> <span class="o">=</span> <span class="nc">Book</span><span class="o">.</span><span class="na">builder</span><span class="o">().</span><span class="na">id</span><span class="o">(</span><span class="s">"1"</span><span class="o">).</span><span class="na">title</span><span class="o">(</span><span class="s">"Hibernate Basics"</span><span class="o">).</span><span class="na">build</span><span class="o">();</span>
    <span class="n">bookRepository</span><span class="o">.</span><span class="na">save</span><span class="o">(</span><span class="n">book</span><span class="o">);</span>

    <span class="nc">Book</span> <span class="n">savedBook</span> <span class="o">=</span> <span class="n">bookRepository</span><span class="o">.</span><span class="na">findById</span><span class="o">(</span><span class="s">"1"</span><span class="o">).</span><span class="na">orElseThrow</span><span class="o">();</span>
    <span class="nc">LocalDateTime</span> <span class="n">originalModifiedAt</span> <span class="o">=</span> <span class="n">savedBook</span><span class="o">.</span><span class="na">getModifiedAt</span><span class="o">();</span>

    <span class="n">savedBook</span><span class="o">.</span><span class="na">setTitle</span><span class="o">(</span><span class="s">"Hibernate Advanced"</span><span class="o">);</span>
    <span class="n">bookRepository</span><span class="o">.</span><span class="na">save</span><span class="o">(</span><span class="n">savedBook</span><span class="o">);</span>

    <span class="c1">// Execute</span>
    <span class="nc">List</span><span class="o">&lt;</span><span class="nc">Book</span><span class="o">&gt;</span> <span class="n">result</span> <span class="o">=</span> <span class="n">bookRepository</span><span class="o">.</span><span class="na">findAllByModifiedAtAfter</span><span class="o">(</span><span class="n">originalModifiedAt</span><span class="o">);</span>

    <span class="c1">// Verify</span>
    <span class="n">assertThat</span><span class="o">(</span><span class="n">result</span><span class="o">,</span> <span class="n">hasSize</span><span class="o">(</span><span class="mi">1</span><span class="o">));</span>
    <span class="n">assertThat</span><span class="o">(</span><span class="n">result</span><span class="o">.</span><span class="na">getFirst</span><span class="o">().</span><span class="na">getId</span><span class="o">(),</span> <span class="n">is</span><span class="o">(</span><span class="s">"1"</span><span class="o">));</span>
<span class="o">}</span>
</code></pre></div></div>

<p>At first glance, the test looks <strong>correct</strong>—you save an entity, modify it, and then query for entities modified after the original timestamp. However, <strong>this test fails intermittently</strong>. Why?</p>

<hr />

<h2 id="-why-this-test-fails-intermittently">🔎 Why This Test Fails Intermittently</h2>

<p>Spring and Hibernate optimize performance by <strong>aggregating save operations</strong> within a transaction. This is part of Hibernate’s <strong>write-behind caching strategy</strong>, where changes to entities are held in memory and only written to the database <strong>at transaction commit or when <code class="language-plaintext highlighter-rouge">flush()</code> is called</strong>.</p>

<h3 id="1️⃣-hibernates-delayed-execution">1️⃣ Hibernate’s Delayed Execution</h3>

<ul>
  <li>When <code class="language-plaintext highlighter-rouge">bookRepository.save()</code> is called, Hibernate <strong>does not immediately execute</strong> the <code class="language-plaintext highlighter-rouge">INSERT</code> or <code class="language-plaintext highlighter-rouge">UPDATE</code> statements.</li>
  <li>It defers them until a <strong>flush</strong>, <strong>query</strong>, or <strong>transaction commit</strong>, which can cause <code class="language-plaintext highlighter-rouge">@LastModifiedDate</code> to appear unchanged in the current session.</li>
</ul>

<h3 id="2️⃣-lastmodifieddate-might-not-update-immediately">2️⃣ <code class="language-plaintext highlighter-rouge">@LastModifiedDate</code> Might Not Update Immediately</h3>

<ul>
  <li>Hibernate updates fields like <code class="language-plaintext highlighter-rouge">@LastModifiedDate</code> only <strong>when it detects a change and flushes it to the database</strong>.</li>
  <li>Without explicitly flushing or committing the transaction, the update may not be persisted by the time you query for it.</li>
</ul>

<hr />

<h2 id="-the-solution-flush-immediately-and-isolate-the-transaction">✅ The Solution: Flush Immediately and Isolate the Transaction</h2>

<p>To fix this issue, we must:</p>

<ul>
  <li><strong>Flush after each save</strong> to force Hibernate to persist changes immediately.</li>
  <li><strong>Ensure that at least one field is modified</strong> before saving again.</li>
  <li><strong>Use separate transactions</strong> to isolate each save, preventing Hibernate from aggregating operations.</li>
</ul>

<hr />

<h3 id="-book-entity-with-audit-fields">📦 Book Entity with Audit Fields</h3>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Entity</span>
<span class="nd">@EntityListeners</span><span class="o">(</span><span class="nc">AuditingEntityListener</span><span class="o">.</span><span class="na">class</span><span class="o">)</span>
<span class="nd">@Data</span>
<span class="nd">@Builder</span>
<span class="nd">@AllArgsConstructor</span>
<span class="nd">@NoArgsConstructor</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">Book</span> <span class="o">{</span>

    <span class="nd">@Id</span>
    <span class="kd">private</span> <span class="nc">String</span> <span class="n">id</span><span class="o">;</span>

    <span class="kd">private</span> <span class="nc">String</span> <span class="n">title</span><span class="o">;</span>

    <span class="nd">@CreatedDate</span>
    <span class="kd">private</span> <span class="nc">LocalDateTime</span> <span class="n">createdAt</span><span class="o">;</span>

    <span class="nd">@LastModifiedDate</span>
    <span class="kd">private</span> <span class="nc">LocalDateTime</span> <span class="n">modifiedAt</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div></div>

<hr />

<h3 id="-reliable-test-case-that-always-passes">✅ Reliable Test Case That Always Passes</h3>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Test</span>
<span class="kt">void</span> <span class="nf">findAllByModifiedAtAfter</span><span class="o">()</span> <span class="o">{</span>
    <span class="c1">// Setup</span>
    <span class="nc">Book</span> <span class="n">book</span> <span class="o">=</span> <span class="nc">Book</span><span class="o">.</span><span class="na">builder</span><span class="o">().</span><span class="na">id</span><span class="o">(</span><span class="s">"1"</span><span class="o">).</span><span class="na">title</span><span class="o">(</span><span class="s">"Hibernate Basics"</span><span class="o">).</span><span class="na">build</span><span class="o">();</span>
    <span class="n">saveWithTransaction</span><span class="o">(</span><span class="n">book</span><span class="o">);</span>
    <span class="n">entityManager</span><span class="o">.</span><span class="na">flush</span><span class="o">();</span> <span class="c1">// ✅ Forces immediate INSERT</span>

    <span class="nc">Book</span> <span class="n">savedBook</span> <span class="o">=</span> <span class="n">getBook</span><span class="o">(</span><span class="s">"1"</span><span class="o">);</span>
    <span class="nc">LocalDateTime</span> <span class="n">originalModifiedAt</span> <span class="o">=</span> <span class="n">savedBook</span><span class="o">.</span><span class="na">getModifiedAt</span><span class="o">();</span>

    <span class="n">savedBook</span><span class="o">.</span><span class="na">setTitle</span><span class="o">(</span><span class="s">"Hibernate Advanced"</span><span class="o">);</span> <span class="c1">// ✅ Ensure change is detected</span>
    <span class="n">saveWithTransaction</span><span class="o">(</span><span class="n">savedBook</span><span class="o">);</span>
    <span class="n">entityManager</span><span class="o">.</span><span class="na">flush</span><span class="o">();</span> <span class="c1">// ✅ Ensures update is persisted</span>

    <span class="c1">// Execute</span>
    <span class="nc">List</span><span class="o">&lt;</span><span class="nc">Book</span><span class="o">&gt;</span> <span class="n">result</span> <span class="o">=</span> <span class="n">findModifiedAfter</span><span class="o">(</span><span class="n">originalModifiedAt</span><span class="o">);</span>

    <span class="c1">// Verify</span>
    <span class="n">assertThat</span><span class="o">(</span><span class="n">result</span><span class="o">,</span> <span class="n">hasSize</span><span class="o">(</span><span class="mi">1</span><span class="o">));</span>
    <span class="n">assertThat</span><span class="o">(</span><span class="n">result</span><span class="o">.</span><span class="na">getFirst</span><span class="o">().</span><span class="na">getId</span><span class="o">(),</span> <span class="n">is</span><span class="o">(</span><span class="s">"1"</span><span class="o">));</span>
<span class="o">}</span>

<span class="nd">@Transactional</span><span class="o">(</span><span class="n">propagation</span> <span class="o">=</span> <span class="nc">Propagation</span><span class="o">.</span><span class="na">REQUIRES_NEW</span><span class="o">)</span>
<span class="kt">void</span> <span class="nf">saveWithTransaction</span><span class="o">(</span><span class="nc">Book</span> <span class="n">book</span><span class="o">)</span> <span class="o">{</span>
    <span class="n">bookRepository</span><span class="o">.</span><span class="na">save</span><span class="o">(</span><span class="n">book</span><span class="o">);</span>
    <span class="n">entityManager</span><span class="o">.</span><span class="na">flush</span><span class="o">();</span>   <span class="c1">// Force DB write</span>
    <span class="n">entityManager</span><span class="o">.</span><span class="na">clear</span><span class="o">();</span>   <span class="c1">// Clear Hibernate cache</span>
<span class="o">}</span>

<span class="nd">@Transactional</span><span class="o">(</span><span class="n">readOnly</span> <span class="o">=</span> <span class="kc">true</span><span class="o">)</span>
<span class="nc">Book</span> <span class="nf">getBook</span><span class="o">(</span><span class="nc">String</span> <span class="n">id</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">return</span> <span class="n">bookRepository</span><span class="o">.</span><span class="na">findById</span><span class="o">(</span><span class="n">id</span><span class="o">).</span><span class="na">orElseThrow</span><span class="o">();</span>
<span class="o">}</span>

<span class="nd">@Transactional</span><span class="o">(</span><span class="n">readOnly</span> <span class="o">=</span> <span class="kc">true</span><span class="o">)</span>
<span class="nc">List</span><span class="o">&lt;</span><span class="nc">Book</span><span class="o">&gt;</span> <span class="nf">findModifiedAfter</span><span class="o">(</span><span class="nc">LocalDateTime</span> <span class="n">threshold</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">return</span> <span class="n">bookRepository</span><span class="o">.</span><span class="na">findAllByModifiedAtAfter</span><span class="o">(</span><span class="n">threshold</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>

<hr />

<h3 id="-key-fixes-that-prevent-aggregation-issues">🔹 Key Fixes That Prevent Aggregation Issues</h3>

<ol>
  <li><strong>Immediate Execution with <code class="language-plaintext highlighter-rouge">flush()</code></strong>
    <ul>
      <li>Ensures Hibernate writes changes to the DB immediately instead of batching.</li>
    </ul>
  </li>
  <li><strong>Modifying a Field to Trigger <code class="language-plaintext highlighter-rouge">@LastModifiedDate</code></strong>
    <ul>
      <li>Hibernate only updates the field if a change is detected.</li>
    </ul>
  </li>
  <li><strong>Clearing the Persistence Context</strong>
    <ul>
      <li>Forces Hibernate to reload from the database rather than using cached entities.</li>
    </ul>
  </li>
  <li><strong>Using <code class="language-plaintext highlighter-rouge">@Transactional(readOnly = true)</code> for Queries</strong>
    <ul>
      <li>Ensures fresh, non-stale data is read without caching interference.</li>
    </ul>
  </li>
</ol>

<hr />

<h2 id="-should-you-even-write-this-test">🧠 Should You Even Write This Test?</h2>

<p>In most cases, writing a test just to check whether <code class="language-plaintext highlighter-rouge">@LastModifiedDate</code> is updated is unnecessary. This auditing behavior is already provided and tested by <strong>Spring Data JPA</strong>. If you’ve properly configured auditing (via <code class="language-plaintext highlighter-rouge">@EnableJpaAuditing</code> and <code class="language-plaintext highlighter-rouge">@EntityListeners(AuditingEntityListener.class)</code>), then you can trust the framework to manage those fields—just like you wouldn’t write a test to verify that <code class="language-plaintext highlighter-rouge">@GeneratedValue</code> creates unique IDs.</p>

<p>You should only write such a test if your business logic depends on <strong>custom behavior</strong> involving modification timestamps—for example, filtering modified entities manually or triggering downstream processes.</p>

<hr />

<h2 id="-final-thoughts">🚀 Final Thoughts</h2>

<p>Yes, Hibernate aggregates save operations by default due to <strong>write-behind caching</strong> in the persistence context. This can lead to <strong>unreliable tests</strong> if you rely on immediate updates to <code class="language-plaintext highlighter-rouge">@LastModifiedDate</code>.</p>

<p>To write a reliable test:</p>
<ul>
  <li>Use <code class="language-plaintext highlighter-rouge">flush()</code> to force Hibernate to write changes</li>
  <li>Modify at least one field before saving</li>
  <li>Clear the persistence context if needed</li>
  <li>Separate your save operations into isolated transactions</li>
</ul>

<p>That way, you ensure deterministic behavior—and your tests will pass consistently. 🚀</p>]]></content><author><name>Dennis Cai</name></author><category term="Knowledgebase" /><category term="Spring Boot" /><category term="Testing" /><summary type="html"><![CDATA[🚨 The Problem: An Intermittently Failing Test in Hibernate When using Spring Data JPA and Hibernate, you might encounter intermittent test failures even when your logic seems correct. Consider the following typical test case implementation: @Test void findAllByModifiedAtAfter() { // Setup Book book = Book.builder().id("1").title("Hibernate Basics").build(); bookRepository.save(book); Book savedBook = bookRepository.findById("1").orElseThrow(); LocalDateTime originalModifiedAt = savedBook.getModifiedAt(); savedBook.setTitle("Hibernate Advanced"); bookRepository.save(savedBook); // Execute List&lt;Book&gt; result = bookRepository.findAllByModifiedAtAfter(originalModifiedAt); // Verify assertThat(result, hasSize(1)); assertThat(result.getFirst().getId(), is("1")); } At first glance, the test looks correct—you save an entity, modify it, and then query for entities modified after the original timestamp. However, this test fails intermittently. Why? 🔎 Why This Test Fails Intermittently Spring and Hibernate optimize performance by aggregating save operations within a transaction. This is part of Hibernate’s write-behind caching strategy, where changes to entities are held in memory and only written to the database at transaction commit or when flush() is called. 1️⃣ Hibernate’s Delayed Execution When bookRepository.save() is called, Hibernate does not immediately execute the INSERT or UPDATE statements. It defers them until a flush, query, or transaction commit, which can cause @LastModifiedDate to appear unchanged in the current session. 2️⃣ @LastModifiedDate Might Not Update Immediately Hibernate updates fields like @LastModifiedDate only when it detects a change and flushes it to the database. Without explicitly flushing or committing the transaction, the update may not be persisted by the time you query for it. ✅ The Solution: Flush Immediately and Isolate the Transaction To fix this issue, we must: Flush after each save to force Hibernate to persist changes immediately. Ensure that at least one field is modified before saving again. Use separate transactions to isolate each save, preventing Hibernate from aggregating operations. 📦 Book Entity with Audit Fields @Entity @EntityListeners(AuditingEntityListener.class) @Data @Builder @AllArgsConstructor @NoArgsConstructor public class Book { @Id private String id; private String title; @CreatedDate private LocalDateTime createdAt; @LastModifiedDate private LocalDateTime modifiedAt; } ✅ Reliable Test Case That Always Passes @Test void findAllByModifiedAtAfter() { // Setup Book book = Book.builder().id("1").title("Hibernate Basics").build(); saveWithTransaction(book); entityManager.flush(); // ✅ Forces immediate INSERT Book savedBook = getBook("1"); LocalDateTime originalModifiedAt = savedBook.getModifiedAt(); savedBook.setTitle("Hibernate Advanced"); // ✅ Ensure change is detected saveWithTransaction(savedBook); entityManager.flush(); // ✅ Ensures update is persisted // Execute List&lt;Book&gt; result = findModifiedAfter(originalModifiedAt); // Verify assertThat(result, hasSize(1)); assertThat(result.getFirst().getId(), is("1")); } @Transactional(propagation = Propagation.REQUIRES_NEW) void saveWithTransaction(Book book) { bookRepository.save(book); entityManager.flush(); // Force DB write entityManager.clear(); // Clear Hibernate cache } @Transactional(readOnly = true) Book getBook(String id) { return bookRepository.findById(id).orElseThrow(); } @Transactional(readOnly = true) List&lt;Book&gt; findModifiedAfter(LocalDateTime threshold) { return bookRepository.findAllByModifiedAtAfter(threshold); } 🔹 Key Fixes That Prevent Aggregation Issues Immediate Execution with flush() Ensures Hibernate writes changes to the DB immediately instead of batching. Modifying a Field to Trigger @LastModifiedDate Hibernate only updates the field if a change is detected. Clearing the Persistence Context Forces Hibernate to reload from the database rather than using cached entities. Using @Transactional(readOnly = true) for Queries Ensures fresh, non-stale data is read without caching interference. 🧠 Should You Even Write This Test? In most cases, writing a test just to check whether @LastModifiedDate is updated is unnecessary. This auditing behavior is already provided and tested by Spring Data JPA. If you’ve properly configured auditing (via @EnableJpaAuditing and @EntityListeners(AuditingEntityListener.class)), then you can trust the framework to manage those fields—just like you wouldn’t write a test to verify that @GeneratedValue creates unique IDs. You should only write such a test if your business logic depends on custom behavior involving modification timestamps—for example, filtering modified entities manually or triggering downstream processes. 🚀 Final Thoughts Yes, Hibernate aggregates save operations by default due to write-behind caching in the persistence context. This can lead to unreliable tests if you rely on immediate updates to @LastModifiedDate. To write a reliable test: Use flush() to force Hibernate to write changes Modify at least one field before saving Clear the persistence context if needed Separate your save operations into isolated transactions That way, you ensure deterministic behavior—and your tests will pass consistently. 🚀]]></summary></entry><entry><title type="html">Using Instancio to generate sample date for testing</title><link href="https://www.thecodinganalyst.com/knowledgebase/Using-Instancio-to-generate-sample-data-for-testing/" rel="alternate" type="text/html" title="Using Instancio to generate sample date for testing" /><published>2024-11-10T00:00:00+00:00</published><updated>2024-11-10T00:00:00+00:00</updated><id>https://www.thecodinganalyst.com/knowledgebase/Using-Instancio-to-generate-sample-data-for-testing</id><content type="html" xml:base="https://www.thecodinganalyst.com/knowledgebase/Using-Instancio-to-generate-sample-data-for-testing/"><![CDATA[<p>Testing is a critical component of software development, ensuring that applications behave as expected. In Spring Boot projects, creating robust and maintainable tests often requires generating realistic test data. Manually crafting this data can be time-consuming and error-prone. This is where Instancio shines. Instancio is a Java library designed to simplify the process of generating test data with minimal configuration, enabling developers to focus on writing effective tests.</p>

<p>Instancio is particularly a life-saver when dealing with objects that have a large number of fields. For example, consider a Customer class with over 20 fields, including nested objects. Manually mocking such an object can quickly become cumbersome and error-prone. With Instancio, you can generate such objects with ease:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@Test
public void generateComplexObject() {
    Customer customer = Instancio.create(Customer.class);
    System.out.println(customer);
}
</code></pre></div></div>

<p>This simple code snippet creates an instance of Customer with all its fields populated, including nested objects, eliminating the need for manual setup.</p>

<!--more-->

<h2 id="what-is-instancio">What is Instancio?</h2>

<p>Instancio is a flexible and powerful library that automates the creation of Java objects with populated fields. It supports complex object graphs and works seamlessly with both primitive and custom types. You can generate realistic test data with just a few lines of code, making it an excellent tool for unit and integration testing in Spring Boot.</p>

<h2 id="key-features-of-instancio">Key Features of Instancio</h2>

<ul>
  <li>
    <p>Automatic Object Creation: Instancio automatically creates objects and populates their fields.</p>
  </li>
  <li>
    <p>Customizable Rules: You can specify generation rules for specific fields or types.</p>
  </li>
  <li>
    <p>Support for Nested Objects: Generate complex object graphs effortlessly.</p>
  </li>
  <li>
    <p>Integration with JUnit and TestNG: Easily integrate Instancio into your test framework.</p>
  </li>
  <li>
    <p>Fluent API: The library offers a user-friendly API for customizing object creation.</p>
  </li>
</ul>

<h2 id="setting-up-instancio-in-a-spring-boot-project">Setting Up Instancio in a Spring Boot Project</h2>

<p>To start using Instancio, add the following dependency to your pom.xml file if you’re using Maven:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;dependency&gt;
    &lt;groupId&gt;org.instancio&lt;/groupId&gt;
    &lt;artifactId&gt;instancio-core&lt;/artifactId&gt;
    &lt;version&gt;2.0.0&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;
</code></pre></div></div>

<p>For Gradle, add:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>testImplementation 'org.instancio:instancio-core:2.0.0'
</code></pre></div></div>

<h2 id="basic-usage">Basic Usage</h2>

<h3 id="generating-a-simple-object">Generating a Simple Object</h3>

<p>Suppose you have a User class with fields like id, name, and email. You can use Instancio to generate a User instance as follows:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>import org.instancio.Instancio;

@Test
public void generateSimpleObject() {
    User user = Instancio.create(User.class);
    System.out.println(user);
}
</code></pre></div></div>

<p>Instancio automatically populates the fields of the User class with realistic values, such as random strings for name and email.</p>

<h3 id="generating-a-list-of-objects">Generating a List of Objects</h3>

<p>To generate a collection of objects, use the Instancio.ofList() method:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@Test
public void generateListOfObjects() {
    List&lt;User&gt; users = Instancio.ofList(User.class).size(10).create();
    users.forEach(System.out::println);
}
</code></pre></div></div>

<p>This creates a list of 10 User objects with populated fields.</p>

<h3 id="customizing-object-generation">Customizing Object Generation</h3>

<p>Setting Specific Values</p>

<p>You can customize object generation by setting specific values for certain fields:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@Test
public void customizeFieldGeneration() {
    User user = Instancio.of(User.class)
            .set(field(User::getName), "John Doe")
            .set(field(User::getEmail), "john.doe@example.com")
            .create();
    System.out.println(user);
}
</code></pre></div></div>

<h3 id="ignoring-fields">Ignoring Fields</h3>

<p>If you want to exclude certain fields from being populated, you can do so with the ignore() method:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@Test
public void ignoreFields() {
    User user = Instancio.of(User.class)
            .ignore(field(User::getPassword))
            .create();
    System.out.println(user);
}
</code></pre></div></div>

<h3 id="generating-a-past-date">Generating a Past Date</h3>

<p>Instancio provides a generate() method that allows for advanced customizations, such as generating dates in the past. For example:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@Test
public void generatePastDate() {
    User user = Instancio.of(User.class)
            .generate(field(User::getBirthDate), gen -&gt; gen.temporal().localDate().past(LocalDate.now().minusYears(1)))
            .create();
    System.out.println(user.getBirthDate());
}
</code></pre></div></div>

<p>In this example, the birthDate field is generated as a date from the past year.</p>

<h3 id="generating-a-string-in-microsoft-json-date-format">Generating a String in Microsoft JSON Date Format</h3>

<p>To generate a string representing a date in the Microsoft JSON date format, you can use the generate() method with a custom generator:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@Test
public void generateMicrosoftJsonDateFormat() {
    User user = Instancio.of(User.class)
            .generate(field(User::getDateString), gen -&gt; gen.string().from(() -&gt; {
                Date date = Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant());
                return "/Date(" + date.getTime() + ")/";
            }))
            .create();
    System.out.println(user.getDateString());
}
</code></pre></div></div>

<p>In this example, the dateString field is generated as a string in the Microsoft JSON date format (e.g., /Date(1672531200000)/).</p>

<h2 id="using-instancio-in-spring-boot-tests">Using Instancio in Spring Boot Tests</h2>

<h3 id="integration-with-spring-boot">Integration with Spring Boot</h3>

<p>Instancio can be used in unit and integration tests in a Spring Boot project. Here is an example using Instancio with Spring Boot’s testing framework:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@SpringBootTest
public class UserServiceTest {

    @Autowired
    private UserService userService;

    @Test
    public void testCreateUser() {
        User user = Instancio.of(User.class)
                .set(field(User::getName), "Jane Doe")
                .set(field(User::getEmail), "jane.doe@example.com")
                .create();

        userService.save(user);

        User retrievedUser = userService.findById(user.getId());
        assertEquals("Jane Doe", retrievedUser.getName());
        assertEquals("jane.doe@example.com", retrievedUser.getEmail());
    }
}
</code></pre></div></div>

<h3 id="mocking-with-instancio">Mocking with Instancio</h3>

<p>When writing unit tests with mocking frameworks like Mockito, you can use Instancio to generate mock data:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@Test
public void testWithMockedRepository() {
    User user = Instancio.create(User.class);

    when(userRepository.save(any(User.class))).thenReturn(user);

    User savedUser = userService.save(new User());
    assertNotNull(savedUser);
}
</code></pre></div></div>

<h3 id="advantages-of-using-instancio">Advantages of Using Instancio</h3>

<ul>
  <li>
    <p>Time-Saving: Automatically generating test data saves time and effort.</p>
  </li>
  <li>
    <p>Improved Test Quality: Realistic and diverse data leads to better test coverage.</p>
  </li>
  <li>
    <p>Flexibility: Customization options allow you to control the generated data.</p>
  </li>
  <li>
    <p>Ease of Use: The fluent API makes Instancio easy to integrate and use.</p>
  </li>
</ul>

<h2 id="conclusion">Conclusion</h2>

<p>Instancio is a powerful tool for generating test data in Spring Boot projects. By automating object creation, it reduces the time and effort needed to write effective tests, allowing developers to focus on building robust applications. Whether you’re writing unit tests or integration tests, Instancio can streamline your testing process and enhance the quality of your tests.</p>]]></content><author><name>Dennis Cai</name></author><category term="Knowledgebase" /><category term="Spring Boot" /><category term="Instancio" /><category term="Testing" /><summary type="html"><![CDATA[Testing is a critical component of software development, ensuring that applications behave as expected. In Spring Boot projects, creating robust and maintainable tests often requires generating realistic test data. Manually crafting this data can be time-consuming and error-prone. This is where Instancio shines. Instancio is a Java library designed to simplify the process of generating test data with minimal configuration, enabling developers to focus on writing effective tests. Instancio is particularly a life-saver when dealing with objects that have a large number of fields. For example, consider a Customer class with over 20 fields, including nested objects. Manually mocking such an object can quickly become cumbersome and error-prone. With Instancio, you can generate such objects with ease: @Test public void generateComplexObject() { Customer customer = Instancio.create(Customer.class); System.out.println(customer); } This simple code snippet creates an instance of Customer with all its fields populated, including nested objects, eliminating the need for manual setup.]]></summary></entry><entry><title type="html">Getting the security context in reactive spring applications</title><link href="https://www.thecodinganalyst.com/knowledgebase/reactive-security-context-holder/" rel="alternate" type="text/html" title="Getting the security context in reactive spring applications" /><published>2024-10-14T00:00:00+00:00</published><updated>2024-10-14T00:00:00+00:00</updated><id>https://www.thecodinganalyst.com/knowledgebase/reactive-security-context-holder</id><content type="html" xml:base="https://www.thecodinganalyst.com/knowledgebase/reactive-security-context-holder/"><![CDATA[<p>In reactive applications, typically when you are using Spring Webflux, handling security contexts, including authentication and authorization, requires a non-blocking approach to integrate with reactive streams effectively. The <code class="language-plaintext highlighter-rouge">ReactiveSecurityContextHolder</code> class is a vital component in Spring Security’s reactive stack, helping manage security contexts across different reactive threads and ensuring consistent access to authentication information throughout the request lifecycle. In this article, we’ll explore what <code class="language-plaintext highlighter-rouge">ReactiveSecurityContextHolder</code> is, when to use it, and how to incorporate it into your reactive Spring applications.</p>

<!--more-->

<p><code class="language-plaintext highlighter-rouge">ReactiveSecurityContextHolder</code> is a utility class in Spring Security’s reactive stack, designed to work with Project Reactor, a reactive programming library. It provides non-blocking access to the security context, holding the current user’s authentication details in a Mono<SecurityContext>. This class is akin to SecurityContextHolder in traditional, blocking Spring Security but tailored for reactive applications where blocking operations are discouraged or even disallowed.
The `ReactiveSecurityContextHolder` operates within the ReactorContext, which carries contextual information in a reactive application. In practice, this enables the retrieval and manipulation of security context information (such as user authentication) seamlessly across different stages of a reactive pipeline.</SecurityContext></p>

<h2 id="example-to-get-the-security-context-with-reactivesecuritycontextholder">Example to get the security context with ReactiveSecurityContextHolder</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import reactor.core.publisher.Mono;

public Mono&lt;String&gt; getUserDetails() {
    return ReactiveSecurityContextHolder.getContext()
        .map(securityContext -&gt; {
            Authentication authentication = securityContext.getAuthentication();
            UserDetails userDetails = (UserDetails) authentication.getPrincipal();
            return "User: " + userDetails.getUsername();
        });
}
</code></pre></div></div>

<h2 id="example-to-save-the-security-context-with-reactivesecuritycontextholder">Example to save the security context with ReactiveSecurityContextHolder</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import reactor.core.publisher.Mono;

public Mono&lt;Void&gt; setCustomSecurityContext(String username, String role) {
    UsernamePasswordAuthenticationToken authentication = 
        new UsernamePasswordAuthenticationToken(username, null, List.of(new SimpleGrantedAuthority(role)));
    SecurityContextImpl securityContext = new SecurityContextImpl(authentication);

    return Mono.deferContextual(context -&gt; 
        ReactiveSecurityContextHolder.withSecurityContext(Mono.just(securityContext)))
        .then();
}

</code></pre></div></div>

<p>Reactive Web Filters are often used for cross-cutting concerns like logging, authentication, and authorization. In scenarios where you need to intercept and modify the SecurityContext in a filter, you can use ReactiveSecurityContextHolder as shown below:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>import org.springframework.web.server.WebFilter;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

public class CustomSecurityContextFilter implements WebFilter {
    
    @Override
    public Mono&lt;Void&gt; filter(ServerWebExchange exchange, WebFilterChain chain) {
        return ReactiveSecurityContextHolder.getContext()
            .flatMap(securityContext -&gt; {
                // Modify or inspect security context as needed
                return chain.filter(exchange).contextWrite(ReactiveSecurityContextHolder.withSecurityContext(Mono.just(securityContext)));
            });
    }
}

</code></pre></div></div>

<h2 id="practical-tips">Practical Tips</h2>
<ul>
  <li><strong>Avoid Blocking Calls:</strong> Ensure that you only use ReactiveSecurityContextHolder within reactive flows, avoiding any blocking operations as they could lead to performance issues in reactive applications.</li>
  <li><strong>Context Propagation:</strong> Use contextWrite to propagate security context changes within the reactive pipeline, especially if you’re creating custom authentication mechanisms or performing role checks.</li>
  <li><strong>Fallback Mechanisms:</strong> Always handle cases where the security context might be absent, especially in routes that are not secured, to avoid NullPointerExceptions.</li>
</ul>

<p><code class="language-plaintext highlighter-rouge">ReactiveSecurityContextHolder</code> is a powerful tool for managing security contexts in Spring reactive applications, enabling access to authentication details across non-blocking, asynchronous streams. By following the patterns and examples above, you can confidently manage security in your reactive applications, ensuring a seamless and efficient user authentication experience.</p>

<p>Understanding <code class="language-plaintext highlighter-rouge">ReactiveSecurityContextHolder</code> and its usage will help you harness the full power of Spring Security’s reactive capabilities, making it an essential part of any developer’s toolkit in reactive programming.</p>]]></content><author><name>Dennis Cai</name></author><category term="Knowledgebase" /><category term="Spring Security" /><category term="Webflux" /><category term="Project Reactor" /><summary type="html"><![CDATA[In reactive applications, typically when you are using Spring Webflux, handling security contexts, including authentication and authorization, requires a non-blocking approach to integrate with reactive streams effectively. The ReactiveSecurityContextHolder class is a vital component in Spring Security’s reactive stack, helping manage security contexts across different reactive threads and ensuring consistent access to authentication information throughout the request lifecycle. In this article, we’ll explore what ReactiveSecurityContextHolder is, when to use it, and how to incorporate it into your reactive Spring applications.]]></summary></entry><entry><title type="html">Set spring profile in IntelliJ</title><link href="https://www.thecodinganalyst.com/knowledgebase/set-spring-profile-in-intellij/" rel="alternate" type="text/html" title="Set spring profile in IntelliJ" /><published>2024-09-17T00:00:00+00:00</published><updated>2024-09-17T00:00:00+00:00</updated><id>https://www.thecodinganalyst.com/knowledgebase/set-spring-profile-in-intellij</id><content type="html" xml:base="https://www.thecodinganalyst.com/knowledgebase/set-spring-profile-in-intellij/"><![CDATA[<p>To set the spring profile in IntelliJ, just edit the configuration, usually <code class="language-plaintext highlighter-rouge">spring-boot:run</code> if you are using maven, or <code class="language-plaintext highlighter-rouge">bootRun</code> if you are using gradle, and add the environment variable <code class="language-plaintext highlighter-rouge">SPRING_PROFILES_ACTIVE</code>.
In the below example <code class="language-plaintext highlighter-rouge">SPRING_PROFILES_ACTIVE=dev</code>, the spring profile is set to <code class="language-plaintext highlighter-rouge">dev</code>.</p>

<p><img src="/assets/images/2024/09/intellij_spring_profile.png" alt="IntelliJ edit configuration" /></p>

<p>And to confirm that the profile is really activated, check that the log <code class="language-plaintext highlighter-rouge">The following 1 profile is active: </code> followed by the activated profile name.
Example - <code class="language-plaintext highlighter-rouge">[demo] [           main] com.example.demo.DemoApplication         : The following 1 profile is active: "dev"</code>.</p>]]></content><author><name>Dennis Cai</name></author><category term="Knowledgebase" /><category term="IntelliJ" /><category term="Spring" /><summary type="html"><![CDATA[To set the spring profile in IntelliJ, just edit the configuration, usually spring-boot:run if you are using maven, or bootRun if you are using gradle, and add the environment variable SPRING_PROFILES_ACTIVE. In the below example SPRING_PROFILES_ACTIVE=dev, the spring profile is set to dev. And to confirm that the profile is really activated, check that the log The following 1 profile is active: followed by the activated profile name. Example - [demo] [ main] com.example.demo.DemoApplication : The following 1 profile is active: "dev".]]></summary></entry><entry><title type="html">Use artifact from another repository as a dependency in Azure DevOps (Part 2)</title><link href="https://www.thecodinganalyst.com/knowledgebase/mavenAuthenticateFeed-in-azure-devops2/" rel="alternate" type="text/html" title="Use artifact from another repository as a dependency in Azure DevOps (Part 2)" /><published>2024-08-13T00:00:00+00:00</published><updated>2024-08-13T00:00:00+00:00</updated><id>https://www.thecodinganalyst.com/knowledgebase/mavenAuthenticateFeed-in-azure-devops2</id><content type="html" xml:base="https://www.thecodinganalyst.com/knowledgebase/mavenAuthenticateFeed-in-azure-devops2/"><![CDATA[<p>Now that we have successfully deployed the Common artifact to our Azure Artifacts Feed, we can set up the Main project to consume this dependency. This will allow us to share the Common project’s compiled code across other projects, streamlining dependency management within our Azure DevOps setup.</p>

<p>Step 1: Configure the Artifacts Feed in the Main Project
To access the artifact from the Common project, we need to add the Common-Feed as a repository in the Main project’s pom.xml. This will ensure Maven can resolve dependencies from this feed.</p>

<p>In the Main project’s pom.xml, add the following repository configuration:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;repositories&gt;
    &lt;repository&gt;
        &lt;id&gt;Common-Feed&lt;/id&gt;
        &lt;url&gt;https://pkgs.dev.azure.com/ORGANIZATION/PROJECT/_packaging/Common-Feed/maven/v1&lt;/url&gt;
        &lt;releases&gt;
            &lt;enabled&gt;true&lt;/enabled&gt;
        &lt;/releases&gt;
        &lt;snapshots&gt;
            &lt;enabled&gt;true&lt;/enabled&gt;
        &lt;/snapshots&gt;
    &lt;/repository&gt;
&lt;/repositories&gt;
</code></pre></div></div>

<p>Replace ORGANIZATION and PROJECT with the relevant names in your Azure DevOps organization.</p>

<p>Step 2: Add the Common Dependency
Next, add a dependency in the Main project’s pom.xml to specify the artifact from the Common project. Ensure that the artifactId, groupId, and version match those used in the Common project’s pom.xml.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;dependencies&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;com.yourcompany.common&lt;/groupId&gt;
        &lt;artifactId&gt;common-artifact&lt;/artifactId&gt;
        &lt;version&gt;1.0.0&lt;/version&gt;
    &lt;/dependency&gt;
&lt;/dependencies&gt;
</code></pre></div></div>

<p>After each update to the Common project, increment the version number to pull the latest changes.</p>

<p>Step 3: Update the Pipeline for Main
In the Main project pipeline, we’ll use MavenAuthenticate@0 to handle authentication for the feed and ensure Maven can access our internal artifact.</p>

<p>Here’s the updated pipeline YAML for the Main project, which will download and use the Common dependency from the Artifacts Feed.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>trigger:
  - main

pool:
  vmImage: ubuntu-latest

steps:
  - checkout: self

  - task: JavaToolInstaller@0
    inputs:
      versionSpec: '11'
      jdkArchitectureOption: 'x64'
      jdkSourceOption: 'PreInstalled'

  # Authenticate with the Common-Feed
  - task: MavenAuthenticate@0
    inputs:
      artifactsFeeds: Common-Feed

  # Build and test the Main project
  - task: Maven@4
    inputs:
      mavenPomFile: 'pom.xml'
      goals: 'clean install'
      publishJUnitResults: true
      testResultsFiles: '**/surefire-reports/TEST-*.xml'
      javaHomeOption: 'JDKVersion'
      jdkVersionOption: '1.11'
      mavenVersionOption: 'Default'
      mavenAuthenticateFeed: false
      effectivePomSkip: false
      sonarQubeRunAnalysis: false
</code></pre></div></div>

<p>Step 4: Verify the Dependency Resolution
After setting up the pipeline and pom.xml, run the pipeline in Azure DevOps. Maven should authenticate with Common-Feed automatically and retrieve the Common artifact. You should see the dependency being resolved in the pipeline logs during the build step.</p>

<p>Managing Artifact Versions
As noted previously, remember to update the version in pom.xml each time there’s a change in the Common project to reflect the latest updates.</p>

<p>Summary
By setting up an Artifacts Feed in Azure DevOps and using MavenAuthenticate@0, we have created a simple way for projects within an organization to share and manage dependencies without relying on public repositories. This setup is scalable and secure for any size of enterprise or startup, leveraging Azure DevOps’ integrated artifact management capabilities.</p>]]></content><author><name>Dennis Cai</name></author><category term="Knowledgebase" /><category term="Azure DevOps" /><category term="Artifact Feed" /><category term="Maven" /><category term="Pipeline" /><category term="CI/CD" /><summary type="html"><![CDATA[Now that we have successfully deployed the Common artifact to our Azure Artifacts Feed, we can set up the Main project to consume this dependency. This will allow us to share the Common project’s compiled code across other projects, streamlining dependency management within our Azure DevOps setup. Step 1: Configure the Artifacts Feed in the Main Project To access the artifact from the Common project, we need to add the Common-Feed as a repository in the Main project’s pom.xml. This will ensure Maven can resolve dependencies from this feed. In the Main project’s pom.xml, add the following repository configuration: &lt;repositories&gt; &lt;repository&gt; &lt;id&gt;Common-Feed&lt;/id&gt; &lt;url&gt;https://pkgs.dev.azure.com/ORGANIZATION/PROJECT/_packaging/Common-Feed/maven/v1&lt;/url&gt; &lt;releases&gt; &lt;enabled&gt;true&lt;/enabled&gt; &lt;/releases&gt; &lt;snapshots&gt; &lt;enabled&gt;true&lt;/enabled&gt; &lt;/snapshots&gt; &lt;/repository&gt; &lt;/repositories&gt; Replace ORGANIZATION and PROJECT with the relevant names in your Azure DevOps organization. Step 2: Add the Common Dependency Next, add a dependency in the Main project’s pom.xml to specify the artifact from the Common project. Ensure that the artifactId, groupId, and version match those used in the Common project’s pom.xml. &lt;dependencies&gt; &lt;dependency&gt; &lt;groupId&gt;com.yourcompany.common&lt;/groupId&gt; &lt;artifactId&gt;common-artifact&lt;/artifactId&gt; &lt;version&gt;1.0.0&lt;/version&gt; &lt;/dependency&gt; &lt;/dependencies&gt; After each update to the Common project, increment the version number to pull the latest changes. Step 3: Update the Pipeline for Main In the Main project pipeline, we’ll use MavenAuthenticate@0 to handle authentication for the feed and ensure Maven can access our internal artifact. Here’s the updated pipeline YAML for the Main project, which will download and use the Common dependency from the Artifacts Feed. trigger: - main pool: vmImage: ubuntu-latest steps: - checkout: self - task: JavaToolInstaller@0 inputs: versionSpec: '11' jdkArchitectureOption: 'x64' jdkSourceOption: 'PreInstalled' # Authenticate with the Common-Feed - task: MavenAuthenticate@0 inputs: artifactsFeeds: Common-Feed # Build and test the Main project - task: Maven@4 inputs: mavenPomFile: 'pom.xml' goals: 'clean install' publishJUnitResults: true testResultsFiles: '**/surefire-reports/TEST-*.xml' javaHomeOption: 'JDKVersion' jdkVersionOption: '1.11' mavenVersionOption: 'Default' mavenAuthenticateFeed: false effectivePomSkip: false sonarQubeRunAnalysis: false Step 4: Verify the Dependency Resolution After setting up the pipeline and pom.xml, run the pipeline in Azure DevOps. Maven should authenticate with Common-Feed automatically and retrieve the Common artifact. You should see the dependency being resolved in the pipeline logs during the build step. Managing Artifact Versions As noted previously, remember to update the version in pom.xml each time there’s a change in the Common project to reflect the latest updates. Summary By setting up an Artifacts Feed in Azure DevOps and using MavenAuthenticate@0, we have created a simple way for projects within an organization to share and manage dependencies without relying on public repositories. This setup is scalable and secure for any size of enterprise or startup, leveraging Azure DevOps’ integrated artifact management capabilities.]]></summary></entry><entry><title type="html">Use artifact from another repository as a dependency in Azure DevOps (Part 1)</title><link href="https://www.thecodinganalyst.com/knowledgebase/mavenAuthenticateFeed-in-azure-devops/" rel="alternate" type="text/html" title="Use artifact from another repository as a dependency in Azure DevOps (Part 1)" /><published>2024-08-12T00:00:00+00:00</published><updated>2024-08-12T00:00:00+00:00</updated><id>https://www.thecodinganalyst.com/knowledgebase/mavenAuthenticateFeed-in-azure-devops</id><content type="html" xml:base="https://www.thecodinganalyst.com/knowledgebase/mavenAuthenticateFeed-in-azure-devops/"><![CDATA[<p>In enterprise projects, it is quite common to have references to other projects as dependency. However, the dependent project is not supposed to be on the public domain. So within the enterprise, it is quite common to have an internal maven repository, using either <a href="https://www.sonatype.com/products/sonatype-nexus-repository">Sonatype Nexus</a> or <a href="https://jfrog.com/artifactory/">JFrog Artifactory</a>. However, this might not be the case for a small startup. One alternative is to use what is available in the pipeline your project is using. For Azure DevOps, we can use the Artifacts Feed.</p>

<p>In a simple example in my Azure DevOps project, I have 2 repositories - Common and Main. Common is a dependency in Main. To begin, I will create a Artifacts Feed for my artifacts, assigned with the relevant visibility, and calling it <code class="language-plaintext highlighter-rouge">Common-Feed</code>.</p>

<p>So in my pipeline for Common, I will call <code class="language-plaintext highlighter-rouge">mvn deploy</code> to deploy the jar file to this feed, so that it can be consumed by Main. Usually, this will mean updating the <code class="language-plaintext highlighter-rouge">settings.xml</code> in the <code class="language-plaintext highlighter-rouge">Maven Home</code>, so I’ll need some additional tasks in my pipeline to either get the file from the <code class="language-plaintext highlighter-rouge">Secured Files</code> and add it to the maven options for my deployment task. However, Azure DevOps has a handy shortcut to achieve that without the dirty work.</p>

<p>Before we run the deploy task, we’ll need to call the <a href="https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/reference/maven-authenticate-v0?view=azure-pipelines"><code class="language-plaintext highlighter-rouge">MavenAuthenticate@0</code></a> task to do the authentication automatically.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>- task: MavenAuthenticate@0
  inputs:
    artifactsFeeds: Common-Feed
</code></pre></div></div>

<p>This step will update the <code class="language-plaintext highlighter-rouge">settings.xml</code> for us. Make sure to set the <code class="language-plaintext highlighter-rouge">artifactsFeed</code> to the name of the feed created earlier.</p>

<p>Then in our deploy task, we set the deployment location to the url of the Artifacts Feed we created too, and <strong>make sure the property <code class="language-plaintext highlighter-rouge">mavenAuthenticateFeed</code> is set to <code class="language-plaintext highlighter-rouge">false</code></strong>.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>- task: Maven@4
  inputs:
    mavenPomFile: 'pom.xml'
    goals: 'deploy'
    options: '-Dmaven.test.skip=true -DaltDeploymentRepository=Common-Feed::default::https://pkgs.dev.azure.com/ORGANIZATION/PROJECT/_packaging/Common-Feed/maven/v1'
    javaHomeOption: 'JDKVersion'
    jdkVersionOption: '1.11'
    mavenAuthenticateFeed: false
</code></pre></div></div>
<p>Also do note thate the id of the <code class="language-plaintext highlighter-rouge">altDeploymentRepository</code> is the name of the feed too, in our case, it is <code class="language-plaintext highlighter-rouge">Common-Feed</code>, as mentioned earlier.</p>

<p>Then, we also need to add this new <code class="language-plaintext highlighter-rouge">Common-Feed</code> to our <code class="language-plaintext highlighter-rouge">pom.xml</code> as a <a href="https://maven.apache.org/pom.html#Repositories">repository</a>.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;repositories&gt;
    &lt;repository&gt;
        &lt;id&gt;Common-Feed&lt;/id&gt;
        &lt;url&gt;https://pkgs.dev.azure.com/ORGANIZATION/PROJECT/_packaging/Common-Feed/maven/v1&lt;/url&gt;
        &lt;releases&gt;
            &lt;enabled&gt;true&lt;/enabled&gt;
        &lt;/releases&gt;
        &lt;snapshots&gt;
            &lt;enabled&gt;true&lt;/enabled&gt;
        &lt;/snapshots&gt;
    &lt;/repository&gt;
&lt;/repositories&gt;
</code></pre></div></div>

<p>The full azure-pipelines.xml is as below.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>trigger:
  - main

pool:
  vmImage: ubuntu-latest

steps:
  - checkout: self
  - task: JavaToolInstaller@0
    inputs:
      versionSpec: '11'
      jdkArchitectureOption: 'x64'
      jdkSourceOption: 'PreInstalled'
  - task: MavenAuthenticate@0
    inputs:
      artifactsFeeds: Common-Feed
  - task: Maven@4
    inputs:
      mavenPomFile: 'pom.xml'
      goals: 'clean install'
      publishJUnitResults: true
      testResultsFiles: '**/surefire-reports/TEST-*.xml'
      javaHomeOption: 'JDKVersion'
      jdkVersionOption: '1.11'
      mavenVersionOption: 'Default'
      mavenAuthenticateFeed: false
      effectivePomSkip: false
      sonarQubeRunAnalysis: false
- task: Maven@4
  inputs:
    mavenPomFile: 'pom.xml'
    goals: 'deploy'
    options: '-Dmaven.test.skip=true -DaltDeploymentRepository=Common-Feed::default::https://pkgs.dev.azure.com/ORGANIZATION/PROJECT/_packaging/Common-Feed/maven/v1'
    javaHomeOption: 'JDKVersion'
    jdkVersionOption: '1.11'
    mavenAuthenticateFeed: false
</code></pre></div></div>

<p>So after the feed runs, it will deploy an artifact to the Artifacts Feed, and it will be visible in the Artifacts tab in Azure DevOps.</p>

<p>Do note that after the first artifact is available in the Artifacts Feed, you will need to update the version number of the project in the pom file every time you update the code.</p>]]></content><author><name>Dennis Cai</name></author><category term="Knowledgebase" /><category term="Azure DevOps" /><category term="Artifact Feed" /><category term="Maven" /><category term="Pipeline" /><category term="CI/CD" /><summary type="html"><![CDATA[In enterprise projects, it is quite common to have references to other projects as dependency. However, the dependent project is not supposed to be on the public domain. So within the enterprise, it is quite common to have an internal maven repository, using either Sonatype Nexus or JFrog Artifactory. However, this might not be the case for a small startup. One alternative is to use what is available in the pipeline your project is using. For Azure DevOps, we can use the Artifacts Feed. In a simple example in my Azure DevOps project, I have 2 repositories - Common and Main. Common is a dependency in Main. To begin, I will create a Artifacts Feed for my artifacts, assigned with the relevant visibility, and calling it Common-Feed. So in my pipeline for Common, I will call mvn deploy to deploy the jar file to this feed, so that it can be consumed by Main. Usually, this will mean updating the settings.xml in the Maven Home, so I’ll need some additional tasks in my pipeline to either get the file from the Secured Files and add it to the maven options for my deployment task. However, Azure DevOps has a handy shortcut to achieve that without the dirty work. Before we run the deploy task, we’ll need to call the MavenAuthenticate@0 task to do the authentication automatically. - task: MavenAuthenticate@0 inputs: artifactsFeeds: Common-Feed This step will update the settings.xml for us. Make sure to set the artifactsFeed to the name of the feed created earlier. Then in our deploy task, we set the deployment location to the url of the Artifacts Feed we created too, and make sure the property mavenAuthenticateFeed is set to false. - task: Maven@4 inputs: mavenPomFile: 'pom.xml' goals: 'deploy' options: '-Dmaven.test.skip=true -DaltDeploymentRepository=Common-Feed::default::https://pkgs.dev.azure.com/ORGANIZATION/PROJECT/_packaging/Common-Feed/maven/v1' javaHomeOption: 'JDKVersion' jdkVersionOption: '1.11' mavenAuthenticateFeed: false Also do note thate the id of the altDeploymentRepository is the name of the feed too, in our case, it is Common-Feed, as mentioned earlier. Then, we also need to add this new Common-Feed to our pom.xml as a repository. &lt;repositories&gt; &lt;repository&gt; &lt;id&gt;Common-Feed&lt;/id&gt; &lt;url&gt;https://pkgs.dev.azure.com/ORGANIZATION/PROJECT/_packaging/Common-Feed/maven/v1&lt;/url&gt; &lt;releases&gt; &lt;enabled&gt;true&lt;/enabled&gt; &lt;/releases&gt; &lt;snapshots&gt; &lt;enabled&gt;true&lt;/enabled&gt; &lt;/snapshots&gt; &lt;/repository&gt; &lt;/repositories&gt; The full azure-pipelines.xml is as below. trigger: - main pool: vmImage: ubuntu-latest steps: - checkout: self - task: JavaToolInstaller@0 inputs: versionSpec: '11' jdkArchitectureOption: 'x64' jdkSourceOption: 'PreInstalled' - task: MavenAuthenticate@0 inputs: artifactsFeeds: Common-Feed - task: Maven@4 inputs: mavenPomFile: 'pom.xml' goals: 'clean install' publishJUnitResults: true testResultsFiles: '**/surefire-reports/TEST-*.xml' javaHomeOption: 'JDKVersion' jdkVersionOption: '1.11' mavenVersionOption: 'Default' mavenAuthenticateFeed: false effectivePomSkip: false sonarQubeRunAnalysis: false - task: Maven@4 inputs: mavenPomFile: 'pom.xml' goals: 'deploy' options: '-Dmaven.test.skip=true -DaltDeploymentRepository=Common-Feed::default::https://pkgs.dev.azure.com/ORGANIZATION/PROJECT/_packaging/Common-Feed/maven/v1' javaHomeOption: 'JDKVersion' jdkVersionOption: '1.11' mavenAuthenticateFeed: false So after the feed runs, it will deploy an artifact to the Artifacts Feed, and it will be visible in the Artifacts tab in Azure DevOps. Do note that after the first artifact is available in the Artifacts Feed, you will need to update the version number of the project in the pom file every time you update the code.]]></summary></entry><entry><title type="html">Resolve git SSL certificate problem on windows</title><link href="https://www.thecodinganalyst.com/knowledgebase/git-backend-for-windows/" rel="alternate" type="text/html" title="Resolve git SSL certificate problem on windows" /><published>2023-10-17T00:00:00+00:00</published><updated>2023-10-17T00:00:00+00:00</updated><id>https://www.thecodinganalyst.com/knowledgebase/git-backend-for-windows</id><content type="html" xml:base="https://www.thecodinganalyst.com/knowledgebase/git-backend-for-windows/"><![CDATA[<p>While trying to push my project to Azure DevOps on my corporate windows machine, I got this error message when I am trying to push my code - <code class="language-plaintext highlighter-rouge">SSL certificate problem: unable to get local issuer certificate</code>.</p>

<p>Turns out according to this <a href="https://confluence.atlassian.com/bitbucketserverkb/ssl-certificate-problem-unable-to-get-local-issuer-certificate-816521128.html">article</a>, git by default uses the “linux” crypto backend, which is openssl, and I don’t have openssl in my local machine. To fix the issue, I just have to amend the git configuration <code class="language-plaintext highlighter-rouge">http.sslbackend</code> to use Windows built-in networking layer - <a href="https://www.techtarget.com/searchsecurity/definition/Microsoft-Schannel-Microsoft-Secure-Channel">SChannel</a>.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git config --global http.sslbackend schannel
</code></pre></div></div>

<p>Doing so will use the Windows certificate storage mechanism when required. Now when I try to push again, I am through!</p>]]></content><author><name>Dennis Cai</name></author><category term="Knowledgebase" /><category term="Git" /><category term="Windows" /><summary type="html"><![CDATA[While trying to push my project to Azure DevOps on my corporate windows machine, I got this error message when I am trying to push my code - SSL certificate problem: unable to get local issuer certificate. Turns out according to this article, git by default uses the “linux” crypto backend, which is openssl, and I don’t have openssl in my local machine. To fix the issue, I just have to amend the git configuration http.sslbackend to use Windows built-in networking layer - SChannel. git config --global http.sslbackend schannel Doing so will use the Windows certificate storage mechanism when required. Now when I try to push again, I am through!]]></summary></entry><entry><title type="html">How to handle internal error in Spring for GraphQL</title><link href="https://www.thecodinganalyst.com/tutorial/how-to-handle-internal-error-in-spring-for-graphql/" rel="alternate" type="text/html" title="How to handle internal error in Spring for GraphQL" /><published>2023-09-06T00:00:00+00:00</published><updated>2023-09-06T00:00:00+00:00</updated><id>https://www.thecodinganalyst.com/tutorial/how-to-handle-internal-error-in-spring-for-graphql</id><content type="html" xml:base="https://www.thecodinganalyst.com/tutorial/how-to-handle-internal-error-in-spring-for-graphql/"><![CDATA[<p>This is an extension to the articles - <a href="https://www.thecodinganalyst.com/tutorial/Getting-started-with-spring-and-graphql/"><code class="language-plaintext highlighter-rouge">Getting started with Spring and GraphQl</code></a> and <a href="https://www.thecodinganalyst.com/tutorial/Integration-testing-on-Spring-Boot-GraphQL-Starter-with-HttpGraphQlTester/"><code class="language-plaintext highlighter-rouge">Integration testing on Spring Boot GraphQL Starter with HttpGraphQlTester</code></a>.</p>

<p>GraphQL pretty much handles validation issues for us, like the screenshot below. We missed out a required field, and graphql provides the appropriate message for us automatically.</p>

<p><img src="/assets/images/2023/09/graphiql-validation-error.png" alt="validation error" /></p>

<p>However, if the exception is due to the internal execution to do the mutation or query of the data, graphql will only give an <code class="language-plaintext highlighter-rouge">Internal Error</code>, without much information.</p>

<p><img src="/assets/images/2023/09/graphiql-internal-error.png" alt="internal error" /></p>

<p>For example, in the update function below, the program will first get the repository to find the product, before updating the product with the fields from the <code class="language-plaintext highlighter-rouge">updatedProduct</code> and save it back in the repository.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>public Mono&lt;Product&gt; updateProduct(String id, Product updatedProduct){
    return productRepository.findById(id)
            .switchIfEmpty(Mono.error(new IllegalArgumentException("Product not found")))
            .flatMap(product -&gt; {
                product.setName(updatedProduct.getName());
                product.setDescription(updatedProduct.getDescription());
                product.setPrice(updatedProduct.getPrice());
                product.setCategory(updatedProduct.getCategory());
                return productRepository.save(product);
            });
}
</code></pre></div></div>

<p>If the product id is not found in the repository, it should return a Mono error, encapsulating an IllegalArgumentException with the appropriate error message - <code class="language-plaintext highlighter-rouge">Product not found</code>.</p>

<p>However, this information is not passed on to the graphql, like what we saw in the screenshot earlier. The message is intentionally opaque to avoid leaking implementation details. Nevertheless, we can handle this error such that it can return the appropriate message to the client.</p>

<p>To handle the exceptions for only with the specific controller itself, we can add the handle function with the <code class="language-plaintext highlighter-rouge">@GraphQlExceptionHandler</code>, as described in the <a href="https://docs.spring.io/spring-graphql/docs/current/reference/html/#controllers.exception-handler">documentation</a>.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@Controller
@Slf4j
public class ProductController {

    ...

    @GraphQlExceptionHandler
    public GraphQLError handle(@NonNull Throwable ex, @NonNull DataFetchingEnvironment environment){
        return GraphQLError
                .newError()
                .errorType(ErrorType.BAD_REQUEST)
                .message(ex.getMessage())
                .path(environment.getExecutionStepInfo().getPath())
                .location(environment.getField().getSourceLocation())
                .build();
    }
}
</code></pre></div></div>

<p>In the above function, we got the Throwable and DataFetchingEnvironment to return the error message and the path and location of where the exception occurred, returning a <code class="language-plaintext highlighter-rouge">GraphQLError</code> to the client.</p>

<p><img src="/assets/images/2023/09/graphiql-error-message.png" alt="graphiql error message" /></p>

<p>Running the same function again, now we get a more meaningful message. Do note that for the above method, it only handles exceptions from the <code class="language-plaintext highlighter-rouge">ProductController</code> class.</p>

<p>Alternatively, we can also create an extension of the <code class="language-plaintext highlighter-rouge">DataFetcherExceptionResolverAdapter</code> as a fallback to handle exceptions not caught by the respective controllers, as described in the <a href="https://docs.spring.io/spring-graphql/docs/current/reference/html/#execution.exceptions">documentation</a>.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@Component
public class CustomExceptionResolver extends DataFetcherExceptionResolverAdapter {
    @Override
    protected GraphQLError resolveToSingleError(@NonNull Throwable ex, @NonNull DataFetchingEnvironment env){
        return GraphqlErrorBuilder.newError()
                .errorType(ErrorType.BAD_REQUEST)
                .message(ex.getMessage())
                .path(env.getExecutionStepInfo().getPath())
                .location(env.getField().getSourceLocation())
                .build();
    }
}
</code></pre></div></div>

<p>We can test that it works in the following integration test. Here, after executing the graphql, we call the <code class="language-plaintext highlighter-rouge">errors()</code> and <code class="language-plaintext highlighter-rouge">expect()</code> to check on the error message. Without the above implementation, the test will fail because it would get in Internal Error instead.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@Test
@Order(5)
void updateProduct_invalidProduct(){
    this.httpGraphQlTester
            .document("""
                    mutation {
                        updateProduct(
                            id: "123",
                            updatedProduct: {
                                name: "Pilot G1 Pen",
                                description: "Best selling gel-based ball point pen",
                                price: 1.80
                                category: "Stationery"
                            }
                        ){
                            id
                            name
                            description
                            price
                            category
                        }
                    }
                    """)
            .execute()
            .errors()
            .expect(error -&gt; Objects.equals(error.getMessage(), "Product not found"));
}
</code></pre></div></div>

<p>A working copy of the above code is available on <a href="https://github.com/thecodinganalyst/graphql/blob/main/src/main/java/com/hevlar/intro/graphql/controller/ProductController.java">https://github.com/thecodinganalyst/graphql/blob/main/src/main/java/com/hevlar/intro/graphql/controller/ProductController.java</a>.</p>]]></content><author><name>Dennis Cai</name></author><category term="Tutorial" /><category term="Java" /><category term="GraphQL" /><category term="HttpGraphQlTester" /><category term="Spring Boot" /><category term="Spring Boot GraphQL Starter" /><summary type="html"><![CDATA[This is an extension to the articles - Getting started with Spring and GraphQl and Integration testing on Spring Boot GraphQL Starter with HttpGraphQlTester. GraphQL pretty much handles validation issues for us, like the screenshot below. We missed out a required field, and graphql provides the appropriate message for us automatically. However, if the exception is due to the internal execution to do the mutation or query of the data, graphql will only give an Internal Error, without much information. For example, in the update function below, the program will first get the repository to find the product, before updating the product with the fields from the updatedProduct and save it back in the repository. public Mono&lt;Product&gt; updateProduct(String id, Product updatedProduct){ return productRepository.findById(id) .switchIfEmpty(Mono.error(new IllegalArgumentException("Product not found"))) .flatMap(product -&gt; { product.setName(updatedProduct.getName()); product.setDescription(updatedProduct.getDescription()); product.setPrice(updatedProduct.getPrice()); product.setCategory(updatedProduct.getCategory()); return productRepository.save(product); }); } If the product id is not found in the repository, it should return a Mono error, encapsulating an IllegalArgumentException with the appropriate error message - Product not found. However, this information is not passed on to the graphql, like what we saw in the screenshot earlier. The message is intentionally opaque to avoid leaking implementation details. Nevertheless, we can handle this error such that it can return the appropriate message to the client. To handle the exceptions for only with the specific controller itself, we can add the handle function with the @GraphQlExceptionHandler, as described in the documentation. @Controller @Slf4j public class ProductController { ... @GraphQlExceptionHandler public GraphQLError handle(@NonNull Throwable ex, @NonNull DataFetchingEnvironment environment){ return GraphQLError .newError() .errorType(ErrorType.BAD_REQUEST) .message(ex.getMessage()) .path(environment.getExecutionStepInfo().getPath()) .location(environment.getField().getSourceLocation()) .build(); } } In the above function, we got the Throwable and DataFetchingEnvironment to return the error message and the path and location of where the exception occurred, returning a GraphQLError to the client. Running the same function again, now we get a more meaningful message. Do note that for the above method, it only handles exceptions from the ProductController class. Alternatively, we can also create an extension of the DataFetcherExceptionResolverAdapter as a fallback to handle exceptions not caught by the respective controllers, as described in the documentation. @Component public class CustomExceptionResolver extends DataFetcherExceptionResolverAdapter { @Override protected GraphQLError resolveToSingleError(@NonNull Throwable ex, @NonNull DataFetchingEnvironment env){ return GraphqlErrorBuilder.newError() .errorType(ErrorType.BAD_REQUEST) .message(ex.getMessage()) .path(env.getExecutionStepInfo().getPath()) .location(env.getField().getSourceLocation()) .build(); } } We can test that it works in the following integration test. Here, after executing the graphql, we call the errors() and expect() to check on the error message. Without the above implementation, the test will fail because it would get in Internal Error instead. @Test @Order(5) void updateProduct_invalidProduct(){ this.httpGraphQlTester .document(""" mutation { updateProduct( id: "123", updatedProduct: { name: "Pilot G1 Pen", description: "Best selling gel-based ball point pen", price: 1.80 category: "Stationery" } ){ id name description price category } } """) .execute() .errors() .expect(error -&gt; Objects.equals(error.getMessage(), "Product not found")); } A working copy of the above code is available on https://github.com/thecodinganalyst/graphql/blob/main/src/main/java/com/hevlar/intro/graphql/controller/ProductController.java.]]></summary></entry></feed>