<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ed Legaspi</title>
    <description>The latest articles on DEV Community by Ed Legaspi (@czetsuya).</description>
    <link>https://dev.to/czetsuya</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F918356%2F3bd969db-a70a-492b-bad3-72081965f313.jpg</url>
      <title>DEV Community: Ed Legaspi</title>
      <link>https://dev.to/czetsuya</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/czetsuya"/>
    <language>en</language>
    <item>
      <title>Why I Stopped Writing Exception Handlers in Every Spring Boot Service</title>
      <dc:creator>Ed Legaspi</dc:creator>
      <pubDate>Sat, 01 Aug 2026 08:50:46 +0000</pubDate>
      <link>https://dev.to/czetsuya/why-i-stopped-writing-exception-handlers-in-every-spring-boot-service-3bm0</link>
      <guid>https://dev.to/czetsuya/why-i-stopped-writing-exception-handlers-in-every-spring-boot-service-3bm0</guid>
      <description>&lt;h1&gt;
  
  
  Why I Stopped Writing Exception Handlers in Every Spring Boot Service
&lt;/h1&gt;

&lt;p&gt;One of my favorite things about Spring Boot is how easy it is to get started.&lt;/p&gt;

&lt;p&gt;Until exception handling enters the picture.&lt;/p&gt;

&lt;p&gt;At first, it's simple.&lt;/p&gt;

&lt;p&gt;You create a &lt;code&gt;@RestControllerAdvice&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Handle a couple of business exceptions.&lt;/p&gt;

&lt;p&gt;Return a consistent error response.&lt;/p&gt;

&lt;p&gt;Done.&lt;/p&gt;

&lt;p&gt;Then the application grows.&lt;/p&gt;

&lt;p&gt;Suddenly you're handling validation exceptions.&lt;/p&gt;

&lt;p&gt;Authentication failures.&lt;/p&gt;

&lt;p&gt;Access denied.&lt;/p&gt;

&lt;p&gt;JPA exceptions.&lt;/p&gt;

&lt;p&gt;Media type errors.&lt;/p&gt;

&lt;p&gt;JSON parsing errors.&lt;/p&gt;

&lt;p&gt;Method argument errors.&lt;/p&gt;

&lt;p&gt;Missing parameters.&lt;/p&gt;

&lt;p&gt;Type mismatches.&lt;/p&gt;

&lt;p&gt;And before long, your once-simple exception handler has become one of the biggest classes in the application.&lt;/p&gt;

&lt;p&gt;I've been there more than once.&lt;/p&gt;

&lt;p&gt;After building enough services, I noticed I wasn't solving business problems anymore—I was rebuilding the exact same exception handling infrastructure in every project.&lt;/p&gt;

&lt;p&gt;That became the motivation behind &lt;strong&gt;nerv-exception&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The real problem isn't writing exception handlers
&lt;/h2&gt;

&lt;p&gt;Creating an exception handler isn't difficult.&lt;/p&gt;

&lt;p&gt;The difficult part is keeping every service consistent.&lt;/p&gt;

&lt;p&gt;One service returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User not found"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"USER_NOT_FOUND"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A third includes timestamps.&lt;/p&gt;

&lt;p&gt;Another includes trace IDs.&lt;/p&gt;

&lt;p&gt;HTTP status codes aren't always consistent.&lt;/p&gt;

&lt;p&gt;Some services expose raw exception messages.&lt;/p&gt;

&lt;p&gt;Others don't.&lt;/p&gt;

&lt;p&gt;Eventually every microservice speaks a different error language.&lt;/p&gt;

&lt;p&gt;For consumers, that's frustrating.&lt;/p&gt;

&lt;p&gt;For developers, it's even worse.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I wanted instead
&lt;/h2&gt;

&lt;p&gt;I wanted exception handling to be something applications configured, not something they rebuilt.&lt;/p&gt;

&lt;p&gt;The goal wasn't to replace Spring's exception handling.&lt;/p&gt;

&lt;p&gt;It was to standardize it.&lt;/p&gt;

&lt;p&gt;Applications should be able to share:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a consistent error response&lt;/li&gt;
&lt;li&gt;centralized error codes&lt;/li&gt;
&lt;li&gt;framework integrations&lt;/li&gt;
&lt;li&gt;sensible defaults&lt;/li&gt;
&lt;li&gt;the ability to customize when necessary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without copying hundreds of lines of infrastructure between repositories.&lt;/p&gt;




&lt;h2&gt;
  
  
  A modular approach
&lt;/h2&gt;

&lt;p&gt;One design decision became clear very early.&lt;/p&gt;

&lt;p&gt;Not every Spring application uses the same stack.&lt;/p&gt;

&lt;p&gt;Some applications use Spring Security.&lt;/p&gt;

&lt;p&gt;Others don't.&lt;/p&gt;

&lt;p&gt;Some use Spring Data JPA.&lt;/p&gt;

&lt;p&gt;Others use MongoDB.&lt;/p&gt;

&lt;p&gt;Some don't even have a database.&lt;/p&gt;

&lt;p&gt;So instead of creating one large dependency that tries to handle everything, I chose a modular architecture.&lt;/p&gt;

&lt;p&gt;The core library remains lightweight.&lt;/p&gt;

&lt;p&gt;Framework integrations live in dedicated modules.&lt;/p&gt;

&lt;p&gt;That means applications only add the functionality they actually need.&lt;/p&gt;




&lt;h2&gt;
  
  
  The latest addition
&lt;/h2&gt;

&lt;p&gt;The newest release expands framework support with built-in integrations for two of the most common Spring technologies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Spring Security
&lt;/h3&gt;

&lt;p&gt;Authentication and authorization exceptions can now be translated into the same standardized error response used throughout the rest of the application.&lt;/p&gt;

&lt;p&gt;No additional exception handlers required.&lt;/p&gt;

&lt;h3&gt;
  
  
  Spring Data JPA
&lt;/h3&gt;

&lt;p&gt;Persistence-related exceptions are now supported through a dedicated module:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;nerv-exception-spring-data-jpa&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Keeping JPA support separate means applications that don't use Spring Data JPA don't inherit unnecessary dependencies.&lt;/p&gt;

&lt;p&gt;It's a small architectural decision, but one that keeps the library flexible as the ecosystem grows.&lt;/p&gt;




&lt;h2&gt;
  
  
  The philosophy hasn't changed
&lt;/h2&gt;

&lt;p&gt;Whenever I add support for another framework, I ask the same question.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Should every application have to implement this itself?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the answer is "probably not," it belongs in the library.&lt;/p&gt;

&lt;p&gt;The goal isn't to hide Spring.&lt;/p&gt;

&lt;p&gt;The goal is to remove repetitive infrastructure while still feeling like Spring.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;I'm continuing to expand the Nerv ecosystem one problem at a time.&lt;/p&gt;

&lt;p&gt;Not by building another framework...&lt;/p&gt;

&lt;p&gt;...but by extracting the infrastructure I've implemented repeatedly across real-world projects into reusable, production-ready libraries.&lt;/p&gt;

&lt;p&gt;If you've ever copied an exception handler from one project into another, I'd love to hear how you've approached it.&lt;/p&gt;

&lt;p&gt;I'm always interested in seeing the different patterns teams use.&lt;/p&gt;




&lt;p&gt;The latest version of &lt;strong&gt;nerv-exception&lt;/strong&gt; is available on &lt;strong&gt;Maven Central&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Source code:&lt;br&gt;
&lt;a href="https://github.com/czetsuyatech/nerv-exception" rel="noopener noreferrer"&gt;https://github.com/czetsuyatech/nerv-exception&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedback, ideas, and contributions are always welcome.&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>opensource</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Stop Rewriting the Same Spring Data JPA Code in Every Project</title>
      <dc:creator>Ed Legaspi</dc:creator>
      <pubDate>Sat, 01 Aug 2026 08:40:47 +0000</pubDate>
      <link>https://dev.to/czetsuya/stop-rewriting-the-same-spring-data-jpa-code-in-every-project-2bfn</link>
      <guid>https://dev.to/czetsuya/stop-rewriting-the-same-spring-data-jpa-code-in-every-project-2bfn</guid>
      <description>&lt;h1&gt;
  
  
  I Got Tired of Rewriting the Same Spring Data JPA Code
&lt;/h1&gt;

&lt;p&gt;After building enough Spring Boot applications, I noticed something strange.&lt;/p&gt;

&lt;p&gt;No matter what the application was—a REST API, an internal tool, or a microservice—the persistence layer always started the same way.&lt;/p&gt;

&lt;p&gt;I would create a &lt;code&gt;BaseEntity&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then an &lt;code&gt;AuditableEntity&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then a repository base class.&lt;/p&gt;

&lt;p&gt;Then pagination models.&lt;/p&gt;

&lt;p&gt;Then DTOs.&lt;/p&gt;

&lt;p&gt;Then a generic Specification builder.&lt;/p&gt;

&lt;p&gt;Then projection utilities.&lt;/p&gt;

&lt;p&gt;Every.&lt;/p&gt;

&lt;p&gt;Single.&lt;/p&gt;

&lt;p&gt;Project.&lt;/p&gt;

&lt;p&gt;The business logic changed.&lt;/p&gt;

&lt;p&gt;The persistence infrastructure didn't.&lt;/p&gt;

&lt;p&gt;Eventually I asked myself:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why am I rebuilding the same foundation every time I start a new application?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That question became &lt;strong&gt;nerv-persistence&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Not another ORM.&lt;/p&gt;

&lt;p&gt;Not a replacement for Spring Data JPA.&lt;/p&gt;

&lt;p&gt;Just a reusable persistence foundation for applications that have already outgrown copy-pasting infrastructure between repositories.&lt;/p&gt;




&lt;h2&gt;
  
  
  The moment I realized something was wrong
&lt;/h2&gt;

&lt;p&gt;It happened while creating a new service.&lt;/p&gt;

&lt;p&gt;I copied my old &lt;code&gt;BaseEntity&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then my audit fields.&lt;/p&gt;

&lt;p&gt;Then my repository interfaces.&lt;/p&gt;

&lt;p&gt;Then my Specification utilities.&lt;/p&gt;

&lt;p&gt;Again.&lt;/p&gt;

&lt;p&gt;Nothing I was writing was specific to the application.&lt;/p&gt;

&lt;p&gt;I was spending the first few hours rebuilding plumbing instead of solving business problems.&lt;/p&gt;

&lt;p&gt;I'm guessing many Spring developers have done exactly the same thing.&lt;/p&gt;




&lt;h2&gt;
  
  
  The hidden cost of "just copy it"
&lt;/h2&gt;

&lt;p&gt;Copying code feels free.&lt;/p&gt;

&lt;p&gt;Until six months later.&lt;/p&gt;

&lt;p&gt;One project fixes a bug.&lt;/p&gt;

&lt;p&gt;Another project improves the Specification builder.&lt;/p&gt;

&lt;p&gt;A third project adds projection support.&lt;/p&gt;

&lt;p&gt;Now every application has a slightly different version of the same infrastructure.&lt;/p&gt;

&lt;p&gt;Maintaining consistency becomes harder than writing the code in the first place.&lt;/p&gt;

&lt;p&gt;I wanted a single place where those common building blocks could evolve together.&lt;/p&gt;




&lt;h2&gt;
  
  
  What ended up inside the library?
&lt;/h2&gt;

&lt;p&gt;Instead of trying to become another framework, I focused on extracting the pieces I kept rebuilding.&lt;/p&gt;

&lt;p&gt;The library includes reusable entity foundations like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;BaseEntity&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;BusinessEntity&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AuditableEntity&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;EnableEntity&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also provides common API models for things like slice pagination and reference data.&lt;/p&gt;

&lt;p&gt;On the repository side, I extracted reusable repository implementations, projection support, and slice-based repositories that I found myself implementing over and over.&lt;/p&gt;

&lt;p&gt;But the part I'm probably happiest with is the dynamic query support.&lt;/p&gt;

&lt;p&gt;If you've worked with Spring Data JPA Specifications, you know how powerful they are...&lt;/p&gt;

&lt;p&gt;...and how quickly the surrounding infrastructure grows.&lt;/p&gt;

&lt;p&gt;Search criteria.&lt;/p&gt;

&lt;p&gt;Builders.&lt;/p&gt;

&lt;p&gt;Operators.&lt;/p&gt;

&lt;p&gt;Generic specifications.&lt;/p&gt;

&lt;p&gt;Projection utilities.&lt;/p&gt;

&lt;p&gt;Most applications eventually reinvent this wheel.&lt;/p&gt;

&lt;p&gt;So I stopped copying it between projects and turned it into reusable components instead.&lt;/p&gt;




&lt;h2&gt;
  
  
  One philosophy guided the entire project
&lt;/h2&gt;

&lt;p&gt;Whenever I had to make a design decision, I asked myself one question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Would I want to maintain this in ten different repositories?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the answer was "no," it belonged in the library.&lt;/p&gt;

&lt;p&gt;That kept the project surprisingly focused.&lt;/p&gt;

&lt;p&gt;Rather than replacing Spring Data JPA, it simply removes the repetitive code that tends to accumulate around it.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;This is only the initial release.&lt;/p&gt;

&lt;p&gt;There are still plenty of ideas I'd like to explore as the project grows.&lt;/p&gt;

&lt;p&gt;More importantly, I want the library to evolve from real-world usage rather than assumptions.&lt;/p&gt;

&lt;p&gt;If there's a persistence problem you've solved repeatedly, I'd genuinely like to hear about it.&lt;/p&gt;

&lt;p&gt;Those are usually the best candidates for reusable abstractions.&lt;/p&gt;




&lt;p&gt;The project is available on &lt;strong&gt;Maven Central&lt;/strong&gt;, and the source code is on GitHub:&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://github.com/czetsuyatech/nerv-persistence" rel="noopener noreferrer"&gt;https://github.com/czetsuyatech/nerv-persistence&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have feedback, ideas, or feature requests, I'd love to hear them.&lt;/p&gt;

&lt;p&gt;After all, this library exists because I got tired of solving the same problem over and over again. I'm sure I'm not the only one.&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>jpa</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Stop Rebuilding Exception Handling in Every Spring Boot Project</title>
      <dc:creator>Ed Legaspi</dc:creator>
      <pubDate>Mon, 06 Jul 2026 13:20:38 +0000</pubDate>
      <link>https://dev.to/czetsuya/stop-rebuilding-exception-handling-in-every-spring-boot-project-24hc</link>
      <guid>https://dev.to/czetsuya/stop-rebuilding-exception-handling-in-every-spring-boot-project-24hc</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjnvmlkgvde90cz3915du.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjnvmlkgvde90cz3915du.png" alt="Discover nerv-exception" width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
After working on multiple Spring Boot projects over the years, I noticed an interesting pattern.&lt;/p&gt;

&lt;p&gt;Every application had different business requirements.&lt;/p&gt;

&lt;p&gt;But almost every application ended up with the same exception handling infrastructure.&lt;/p&gt;

&lt;p&gt;I found myself recreating the same classes over and over again:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@RestControllerAdvice&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Custom exceptions&lt;/li&gt;
&lt;li&gt;Error response models&lt;/li&gt;
&lt;li&gt;Error codes&lt;/li&gt;
&lt;li&gt;Validation handlers&lt;/li&gt;
&lt;li&gt;Feign error decoders&lt;/li&gt;
&lt;li&gt;Utility classes&lt;/li&gt;
&lt;li&gt;Configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The business logic changed.&lt;/p&gt;

&lt;p&gt;The exception handling didn't.&lt;/p&gt;

&lt;p&gt;Eventually I asked myself:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why am I rebuilding this for every project?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That question became &lt;strong&gt;nerv-exception&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of copying hundreds of lines of exception handling infrastructure from project to project, I wanted a reusable, production-ready library that could become the foundation for every Spring Boot application.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;A typical Spring Boot application usually starts with something like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@RestControllerAdvice&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GlobalExceptionHandler&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@ExceptionHandler&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UserNotFoundException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ApiError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UserNotFoundException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NOT_FOUND&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ApiError&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                        &lt;span class="s"&gt;"USER_NOT_FOUND"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMessage&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@ExceptionHandler&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MethodArgumentNotValidException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ApiError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MethodArgumentNotValidException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Looks simple.&lt;/p&gt;

&lt;p&gt;Until the application grows.&lt;/p&gt;

&lt;p&gt;Now you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;business exceptions&lt;/li&gt;
&lt;li&gt;validation exceptions&lt;/li&gt;
&lt;li&gt;security exceptions&lt;/li&gt;
&lt;li&gt;Feign client exceptions&lt;/li&gt;
&lt;li&gt;Kafka consumer exceptions&lt;/li&gt;
&lt;li&gt;asynchronous processing&lt;/li&gt;
&lt;li&gt;scheduled jobs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every new integration introduces another place where exceptions need to be translated.&lt;/p&gt;

&lt;p&gt;Soon enough, different parts of your application return completely different error payloads.&lt;/p&gt;

&lt;p&gt;Your REST API becomes inconsistent.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Wanted
&lt;/h2&gt;

&lt;p&gt;I wasn't trying to replace Spring Boot.&lt;/p&gt;

&lt;p&gt;Spring Boot already provides excellent exception handling capabilities.&lt;/p&gt;

&lt;p&gt;Instead, I wanted a reusable foundation that provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;consistent API responses&lt;/li&gt;
&lt;li&gt;centralized error codes&lt;/li&gt;
&lt;li&gt;minimal boilerplate&lt;/li&gt;
&lt;li&gt;RFC 7807 Problem Details&lt;/li&gt;
&lt;li&gt;Spring Boot auto-configuration&lt;/li&gt;
&lt;li&gt;modular architecture&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most importantly...&lt;/p&gt;

&lt;p&gt;I wanted something &lt;strong&gt;I would actually use in production.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Introducing nerv-exception
&lt;/h2&gt;

&lt;p&gt;The library is intentionally split into multiple modules.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nerv-exception-api
nerv-exception-core
nerv-exception-spring-web
nerv-exception-spring-boot-starter
nerv-exception-spring-feign
nerv-exception-event
nerv-exception-spring-kafka
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each module has a single responsibility.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;api&lt;/strong&gt; contains only the public contracts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;core&lt;/strong&gt; contains the domain exception model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;spring-web&lt;/strong&gt; integrates with Spring MVC.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;starter&lt;/strong&gt; provides auto-configuration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;feign&lt;/strong&gt; handles remote service errors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;event&lt;/strong&gt; standardizes exception events.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;spring-kafka&lt;/strong&gt; integrates with Kafka consumers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Applications only depend on what they actually need.&lt;/p&gt;




&lt;h2&gt;
  
  
  Adding the Library
&lt;/h2&gt;

&lt;p&gt;Getting started is intentionally simple.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.czetsuyatech&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;nerv-exception-spring-boot-starter&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.0.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it.&lt;/p&gt;

&lt;p&gt;Spring Boot auto-configuration registers everything automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  Standardized Error Responses
&lt;/h2&gt;

&lt;p&gt;One of the biggest goals of the project was consistency.&lt;/p&gt;

&lt;p&gt;Instead of every controller returning its own custom JSON, APIs can return standardized RFC 7807 Problem Details.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/problems/user-not-found"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User not found"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"detail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User 123 was not found."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"instance"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/users/123"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes APIs significantly easier to consume.&lt;/p&gt;

&lt;p&gt;Frontend developers know exactly what to expect.&lt;/p&gt;

&lt;p&gt;API documentation becomes simpler.&lt;/p&gt;

&lt;p&gt;Clients become easier to implement.&lt;/p&gt;




&lt;h2&gt;
  
  
  Designed for Extension
&lt;/h2&gt;

&lt;p&gt;One design decision I made very early was:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Avoid forcing applications into one way of doing things.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The library provides sensible defaults while remaining extensible.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;custom error codes&lt;/li&gt;
&lt;li&gt;custom exception mapping&lt;/li&gt;
&lt;li&gt;trace context propagation&lt;/li&gt;
&lt;li&gt;Feign integration&lt;/li&gt;
&lt;li&gt;Kafka integration&lt;/li&gt;
&lt;li&gt;event publishing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Applications can override behavior without modifying the library itself.&lt;/p&gt;




&lt;h2&gt;
  
  
  Runnable Examples
&lt;/h2&gt;

&lt;p&gt;Documentation is helpful.&lt;/p&gt;

&lt;p&gt;Runnable code is even better.&lt;/p&gt;

&lt;p&gt;That's why I also created a companion repository containing complete Spring Boot applications demonstrating how to use the library in real projects.&lt;/p&gt;

&lt;p&gt;Rather than reading isolated snippets, developers can clone the repository, run the application, and explore the implementation themselves.&lt;/p&gt;

&lt;p&gt;Repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/czetsuyatech/nerv-examples" rel="noopener noreferrer"&gt;https://github.com/czetsuyatech/nerv-examples&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Open Source?
&lt;/h2&gt;

&lt;p&gt;Throughout my career I've benefited enormously from open source.&lt;/p&gt;

&lt;p&gt;Many libraries have saved me countless hours.&lt;/p&gt;

&lt;p&gt;Building &lt;strong&gt;nerv-exception&lt;/strong&gt; is my opportunity to give something back.&lt;/p&gt;

&lt;p&gt;If another developer no longer has to rebuild the same exception handling infrastructure for their next project, then this library has already accomplished its goal.&lt;/p&gt;




&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;h2&gt;
  
  
  GitHub
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/czetsuyatech/nerv-exception" rel="noopener noreferrer"&gt;https://github.com/czetsuyatech/nerv-exception&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Maven Central
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.czetsuyatech&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;nerv-exception-spring-boot-starter&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.0.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Example Projects
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/czetsuyatech/nerv-examples" rel="noopener noreferrer"&gt;https://github.com/czetsuyatech/nerv-examples&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;I'm continuously improving the library based on real-world experience.&lt;/p&gt;

&lt;p&gt;If you have ideas, suggestions, or find it useful, I'd love to hear your feedback.&lt;/p&gt;

&lt;p&gt;Happy coding! 🚀&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>opensource</category>
      <category>api</category>
    </item>
    <item>
      <title>Stop Rewriting CI/CD: Reusable GitHub Actions for Maven Projects</title>
      <dc:creator>Ed Legaspi</dc:creator>
      <pubDate>Tue, 28 Apr 2026 00:36:48 +0000</pubDate>
      <link>https://dev.to/czetsuya/stop-rewriting-cicd-reusable-github-actions-for-maven-projects-1bp1</link>
      <guid>https://dev.to/czetsuya/stop-rewriting-cicd-reusable-github-actions-for-maven-projects-1bp1</guid>
      <description>&lt;p&gt;If you’ve worked on multiple Java projects, you’ve probably run into this:&lt;/p&gt;

&lt;p&gt;Every repository has its own version of a CI/CD pipeline.&lt;/p&gt;

&lt;p&gt;Slightly different YAML.&lt;br&gt;&lt;br&gt;
Slightly different setup steps.&lt;br&gt;&lt;br&gt;
Slightly different ways of doing the same thing.&lt;/p&gt;

&lt;p&gt;And somehow… none of them are reusable.&lt;/p&gt;




&lt;h2&gt;
  
  
  😤 The Real Problem
&lt;/h2&gt;

&lt;p&gt;It’s not that CI/CD is hard.&lt;/p&gt;

&lt;p&gt;It’s that it’s &lt;strong&gt;repetitive&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You end up doing the same things over and over:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set up Java
&lt;/li&gt;
&lt;li&gt;Cache Maven dependencies
&lt;/li&gt;
&lt;li&gt;Run tests
&lt;/li&gt;
&lt;li&gt;Build artifacts
&lt;/li&gt;
&lt;li&gt;Handle versioning
&lt;/li&gt;
&lt;li&gt;Publish or release
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then copy that workflow into another repo…&lt;br&gt;&lt;br&gt;
…and tweak it just enough to break consistency.&lt;/p&gt;

&lt;p&gt;This is exactly the kind of problem automation should solve — yet we keep duplicating it.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 A Different Approach
&lt;/h2&gt;

&lt;p&gt;Instead of treating each pipeline as a one-off YAML file, I started thinking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What if CI/CD steps were modular and reusable — just like code?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s where &lt;strong&gt;NERV-Actions&lt;/strong&gt; came from.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/czetsuyatech/nerv-actions" rel="noopener noreferrer"&gt;https://github.com/czetsuyatech/nerv-actions&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ What NERV-Actions Is
&lt;/h2&gt;

&lt;p&gt;NERV-Actions is a collection of &lt;strong&gt;reusable GitHub Actions designed for Maven-based projects&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The idea is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Break CI/CD into small, composable actions
&lt;/li&gt;
&lt;li&gt;Reuse them across repositories
&lt;/li&gt;
&lt;li&gt;Keep pipelines consistent without rewriting everything
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# repeated in every repo
- uses: actions/setup-java@v4
- run: mvn clean install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You plug in reusable building blocks that already handle those concerns.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧱 Why This Matters
&lt;/h2&gt;

&lt;p&gt;Reusable workflows aren’t just about convenience — they solve real scaling problems.&lt;/p&gt;

&lt;p&gt;When you define things once and reuse them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You reduce duplication
&lt;/li&gt;
&lt;li&gt;You avoid inconsistencies across repos
&lt;/li&gt;
&lt;li&gt;You make updates easier (change once, apply everywhere)
&lt;/li&gt;
&lt;li&gt;You spend less time debugging YAML
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧠 Design Philosophy
&lt;/h2&gt;

&lt;p&gt;I didn’t try to build a “one-size-fits-all” pipeline.&lt;/p&gt;

&lt;p&gt;Instead, NERV-Actions focuses on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Composable units&lt;/strong&gt; → mix only what you need
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sensible defaults&lt;/strong&gt; → minimal setup required
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistency&lt;/strong&gt; → same patterns across projects
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extensibility&lt;/strong&gt; → override when necessary
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s closer to building blocks than a framework.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Example Use Case
&lt;/h2&gt;

&lt;p&gt;For a typical Maven project, your pipeline usually boils down to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run tests
&lt;/li&gt;
&lt;li&gt;Build artifacts
&lt;/li&gt;
&lt;li&gt;Publish packages
&lt;/li&gt;
&lt;li&gt;Create releases
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With reusable actions, you don’t redefine these steps every time—you just assemble them.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤔 Why Not Just Copy-Paste?
&lt;/h2&gt;

&lt;p&gt;Because copy-paste doesn’t scale.&lt;/p&gt;

&lt;p&gt;It works for 2–3 repos.&lt;br&gt;&lt;br&gt;
It breaks down at 10+.  &lt;/p&gt;

&lt;p&gt;Suddenly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fixes don’t propagate
&lt;/li&gt;
&lt;li&gt;Pipelines drift
&lt;/li&gt;
&lt;li&gt;Debugging becomes inconsistent
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reusable actions solve that by centralizing the logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 Still Evolving
&lt;/h2&gt;

&lt;p&gt;This isn’t meant to be a “perfect CI/CD solution.”&lt;/p&gt;

&lt;p&gt;It’s a practical attempt to reduce the friction I kept running into across projects.&lt;/p&gt;

&lt;p&gt;If you’re dealing with the same repetition in GitHub Actions, this might be useful:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/your-repo-link" rel="noopener noreferrer"&gt;https://github.com/your-repo-link&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  💬 Curious About Your Setup
&lt;/h2&gt;

&lt;p&gt;Are you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;copying workflows between repos?
&lt;/li&gt;
&lt;li&gt;using reusable workflows heavily?
&lt;/li&gt;
&lt;li&gt;or building your own internal action libraries?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Would be interesting to hear how others are handling this.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>githubactions</category>
      <category>cicd</category>
      <category>java</category>
    </item>
    <item>
      <title>I Got Tired of Rewriting Audit Logs in Spring Boot — So I Built nerv-audit</title>
      <dc:creator>Ed Legaspi</dc:creator>
      <pubDate>Fri, 17 Apr 2026 07:18:23 +0000</pubDate>
      <link>https://dev.to/czetsuya/i-got-tired-of-rewriting-audit-logs-in-spring-boot-so-i-built-nerv-audit-3cg4</link>
      <guid>https://dev.to/czetsuya/i-got-tired-of-rewriting-audit-logs-in-spring-boot-so-i-built-nerv-audit-3cg4</guid>
      <description>&lt;p&gt;Every backend system eventually hits this moment:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Who changed this record?”&lt;br&gt;
“What was the previous value?”&lt;br&gt;
“When did it happen?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Simple questions… until you actually need answers in production.&lt;/p&gt;




&lt;p&gt;⚠️ Note: The core module is commercial, but you can explore the public modules and examples here:&lt;br&gt;
👉 &lt;a href="https://github.com/czetsuyatech/nerv-audit" rel="noopener noreferrer"&gt;https://github.com/czetsuyatech/nerv-audit&lt;/a&gt;&lt;br&gt;
👉 &lt;a href="https://github.com/czetsuyatech/nerv-examples" rel="noopener noreferrer"&gt;https://github.com/czetsuyatech/nerv-examples&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;In most of my Spring Boot projects, I relied on Hibernate Envers.&lt;/p&gt;

&lt;p&gt;It works—but in real systems, it starts to hurt:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You repeat the same setup across services&lt;/li&gt;
&lt;li&gt;Audit queries are hard to read and maintain&lt;/li&gt;
&lt;li&gt;Business-level audit logic gets scattered&lt;/li&gt;
&lt;li&gt;Small mistakes become painful in production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After a few projects, I realized:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I wasn’t building features anymore—I was rebuilding audit infrastructure.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  What I Actually Wanted
&lt;/h2&gt;

&lt;p&gt;Not a replacement for Envers.&lt;/p&gt;

&lt;p&gt;Just something that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Standardizes audit handling&lt;/li&gt;
&lt;li&gt;Reduces boilerplate&lt;/li&gt;
&lt;li&gt;Makes queries readable&lt;/li&gt;
&lt;li&gt;Works consistently across projects&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  So I Built nerv-audit
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/czetsuyatech/nerv-audit" rel="noopener noreferrer"&gt;nerv-audit&lt;/a&gt; is a lightweight layer on top of Envers that focuses on &lt;strong&gt;developer experience&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of wiring everything manually, you get a cleaner way to work with audit data.&lt;/p&gt;


&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Without nerv-audit
&lt;/h3&gt;

&lt;p&gt;You end up dealing with low-level Envers APIs and custom query logic.&lt;/p&gt;
&lt;h3&gt;
  
  
  With nerv-audit
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getVerticalAudits&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;criteria&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That’s it.&lt;/p&gt;



&lt;p&gt;Want to see how it's implemented in a real project?&lt;br&gt;
👉 &lt;a href="https://github.com/czetsuyatech/nerv-audit" rel="noopener noreferrer"&gt;https://github.com/czetsuyatech/nerv-audit&lt;/a&gt;&lt;br&gt;
👉 &lt;a href="https://github.com/czetsuyatech/nerv-examples" rel="noopener noreferrer"&gt;https://github.com/czetsuyatech/nerv-examples&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  What It Improves
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Consistent Audit Handling
&lt;/h3&gt;

&lt;p&gt;Define audit behavior once, reuse everywhere.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@AuditedEntity&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  2. Cleaner Queries
&lt;/h3&gt;

&lt;p&gt;No more complex Envers query construction.&lt;/p&gt;

&lt;p&gt;You focus on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What changed&lt;/li&gt;
&lt;li&gt;When it changed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not &lt;em&gt;how&lt;/em&gt; to retrieve it.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Less Repetition
&lt;/h3&gt;

&lt;p&gt;Across projects, the pattern is always the same.&lt;/p&gt;

&lt;p&gt;nerv-audit abstracts that pattern so you don’t rewrite it every time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I Built This
&lt;/h2&gt;

&lt;p&gt;This came from real production work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple systems&lt;/li&gt;
&lt;li&gt;Repeated audit requirements&lt;/li&gt;
&lt;li&gt;Real incidents where audit data mattered&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At some point, it made more sense to &lt;strong&gt;abstract the solution&lt;/strong&gt; than keep rebuilding it.&lt;/p&gt;




&lt;h2&gt;
  
  
  About the Model (Transparency)
&lt;/h2&gt;

&lt;p&gt;nerv-audit is &lt;strong&gt;not fully open-source&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There is a &lt;strong&gt;free tier&lt;/strong&gt; you can use&lt;/li&gt;
&lt;li&gt;Some advanced capabilities are part of a &lt;strong&gt;paid core&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚠️ Note: The core module is commercial, but you can explore the public modules and examples here:&lt;br&gt;
👉 &lt;a href="https://github.com/czetsuyatech/nerv-audit" rel="noopener noreferrer"&gt;https://github.com/czetsuyatech/nerv-audit&lt;/a&gt;&lt;br&gt;
👉 &lt;a href="https://github.com/czetsuyatech/nerv-examples" rel="noopener noreferrer"&gt;https://github.com/czetsuyatech/nerv-examples&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I chose this approach to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep the project sustainable&lt;/li&gt;
&lt;li&gt;Continue improving it over time&lt;/li&gt;
&lt;li&gt;Focus on real-world use cases&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Who This Is For
&lt;/h2&gt;

&lt;p&gt;This might be useful if you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build Spring Boot applications&lt;/li&gt;
&lt;li&gt;Use Hibernate Envers (or plan to)&lt;/li&gt;
&lt;li&gt;Want a cleaner way to handle audit logs&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  I’d Like Your Input
&lt;/h2&gt;

&lt;p&gt;How are you handling audit logs today?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pure Envers?&lt;/li&gt;
&lt;li&gt;Custom implementation?&lt;/li&gt;
&lt;li&gt;Something else?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m especially interested in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pain points&lt;/li&gt;
&lt;li&gt;Query challenges&lt;/li&gt;
&lt;li&gt;Scaling issues&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If you're working with Envers, try it out and let me know what breaks—or what works better.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔗 Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/czetsuyatech/nerv-audit" rel="noopener noreferrer"&gt;https://github.com/czetsuyatech/nerv-audit&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/czetsuyatech/nerv-examples" rel="noopener noreferrer"&gt;https://github.com/czetsuyatech/nerv-examples&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>hibernate</category>
      <category>backend</category>
    </item>
    <item>
      <title>Hands-On Coding: Exploring Hyperparameters for Programmers</title>
      <dc:creator>Ed Legaspi</dc:creator>
      <pubDate>Thu, 07 Mar 2024 04:54:31 +0000</pubDate>
      <link>https://dev.to/czetsuya/hands-on-coding-exploring-hyperparameters-for-programmers-5c9c</link>
      <guid>https://dev.to/czetsuya/hands-on-coding-exploring-hyperparameters-for-programmers-5c9c</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;In this article, we will explore different techniques for finding the optimal hyperparameter values from a given set of parameters in a grid. Particularly we will look at RandomizedSearchCV, GridSearchCV, and BayesSearchCV.&lt;/p&gt;

&lt;p&gt;In this blog you will learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to initialize the parameter grid.&lt;/li&gt;
&lt;li&gt;How to find the optimal hyperparameters based on a given technique.&lt;/li&gt;
&lt;li&gt;How to build a model (XGBClassifier) to use the hyperparameters.&lt;/li&gt;
&lt;li&gt;How to score the performance of the model.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  RandomizedSearchCV
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;param_grid = {
    "gamma": [0, 0.1, 0.2, 0.5, 1, 1.5, 2, 3, 6, 12, 20],
    "learning_rate": [0.01, 0.02, 0.03, 0.05, 0.1, 0.2, 0.3, 0.5, 0.7, 0.8],
    "max_depth": [1, 2, 3, 4, 5, 6, 8, 12],
    "n_estimators": [25, 50, 65, 80, 100, 115, 200]
}

grid_search = RandomizedSearchCV(estimator=classifier_0, param_distributions=param_grid, scoring=scoring)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  GridSearchCV
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;param_grid = {
    "gamma": [0, 0.1, 0.2, 0.5, 1, 1.5, 2, 3, 6, 12, 20],
    "learning_rate": [0.01, 0.02, 0.03, 0.05, 0.1, 0.2, 0.3, 0.5, 0.7, 0.8],
    "max_depth": [2, 3, 4, 5, 6, 8, 12],
    "n_estimators": [25, 50, 65, 80, 100, 115, 200]
}

grid_search = GridSearchCV(estimator=classifier_0, param_grid=param_grid, scoring=scoring)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  BayesSearchCV
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;param_bayes = {
    'gamma': Categorical(param_grid['gamma']),
    'learning_rate': Categorical(param_grid['learning_rate']),
    'max_depth': Categorical(param_grid['max_depth']),
    'n_estimators': Categorical(param_grid['n_estimators'])
}

grid_search = BayesSearchCV(estimator=classifier_0, search_spaces=param_bayes, scoring=scoring, n_jobs=-1, cv=10)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Finding the Best HyperParameters
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;best_model = grid_search.fit(X_train, y_train)
hyperparams = best_model.best_params_
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Building and Scoring the Classifier using the HyperParameters
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Fitting the Model
ne = hyperparams['n_estimators']
lr = hyperparams['learning_rate']
md = hyperparams['max_depth']
gm = hyperparams['gamma']
print("Recommended Params &amp;gt;&amp;gt;", f"ne: {ne},", f"lr: {lr}", f"md: {md}", f"gm: {gm}")

# Build Classification Model
classifier_1 = XGBClassifier(
    base_score=0.5,
    colsample_bylevel=1,
    colsample_bynode=1,
    objective=objective,
    booster="gbtree",
    eval_metric=eval_metric_list,
    n_estimators=ne,
    learning_rate=lr,
    max_depth=md,
    gamma=gm,
    subsample=0.8,
    colsample_bytree=1,
    random_state=1
)

# Fit Model
eval_set = [(X_train, y_train)]
classifier_1.fit(
    X_train,
    y_train,
    eval_set=eval_set,
    verbose=False
)

# Get predictions for training data
train_yhat = classifier_1.predict(X_train)
print("Training Preds: \n", train_yhat[:5])

# Set K-Fold Cross Validation Levels
cv = RepeatedStratifiedKFold(n_splits=5, n_repeats=3, random_state=1)

# Training Results
train_results = cross_val_score(classifier_1, X_train, y_train, scoring=scoring, cv=cv, n_jobs=1)

# Brief Review of Training Results
print("Average Accuracy K-Fold: ", round(train_results.mean(), 2))
print("Std Deviation K-Fold: ", round(train_results.std(), 2))
print("Precision Score 0: ", round(precision_score(y_train, train_yhat, average=None)[0], 3))
print("Precision Score 1: ", round(precision_score(y_train, train_yhat, average=None)[1], 3))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;Machine: Laptop &lt;br&gt;
Processor: AMD Ryzen 7 &lt;br&gt;
OS: Windows &lt;br&gt;
DataFrame Shape: (7282, 17)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkkxfai73dfdz9tjcqz69.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkkxfai73dfdz9tjcqz69.png" alt="Image description" width="800" height="169"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>programming</category>
      <category>learning</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>Understanding How Scope Affects Values in Your Spring REST Controller</title>
      <dc:creator>Ed Legaspi</dc:creator>
      <pubDate>Sat, 02 Mar 2024 03:33:59 +0000</pubDate>
      <link>https://dev.to/czetsuya/understanding-how-scope-affects-values-in-your-spring-rest-controller-4c97</link>
      <guid>https://dev.to/czetsuya/understanding-how-scope-affects-values-in-your-spring-rest-controller-4c97</guid>
      <description>&lt;p&gt;Below we explore how a scope annotation affects an instance value in a Spring REST controller.&lt;/p&gt;

&lt;p&gt;Each controller is annotated with scope.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@RestController
@Scope([SCOPE_VALUE])
public class XXXScopeController {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnwos5ouwyufdrudx13r9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnwos5ouwyufdrudx13r9.png" alt="Image description" width="800" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to Convert Vertically Stored Asset Data into Columnar Format for Cointegration Analysis</title>
      <dc:creator>Ed Legaspi</dc:creator>
      <pubDate>Sat, 02 Mar 2024 01:12:16 +0000</pubDate>
      <link>https://dev.to/czetsuya/how-to-convert-vertically-stored-asset-data-into-columnar-format-for-cointegration-analysis-54f9</link>
      <guid>https://dev.to/czetsuya/how-to-convert-vertically-stored-asset-data-into-columnar-format-for-cointegration-analysis-54f9</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This piece of code fetches asset information from a table stored vertically. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F08t3ue8ulmjcwbr4wi4u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F08t3ue8ulmjcwbr4wi4u.png" alt="Image description" width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependencies
&lt;/h2&gt;

&lt;p&gt;Install the following package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;conda install pandas
conda install numpy as np
conda install mysql-connector-python
conda install sqlalchemy
conda install pymysql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Hands-on Coding
&lt;/h2&gt;

&lt;p&gt;Connect to the database&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def query_df(query):
    try: 
        engine_uri = f"mysql+pymysql://db_user:db_pass_123@localhost:3306/tradewise_pse"
        db_conn = create_engine(engine_uri)        
        df_result = pd.read_sql(query, db_conn)    
        return df_result

    except Exception as e:    
        print(str(e))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Fetching the Dataset
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if not load_existing:
    sql_distinct_tickers = "select ticker from candlestick where event_time='2023-12-29' and ticker not like '^%%'"
    df_tickers = query_df(sql_distinct_tickers)

    df = pd.DataFrame(index=['event_time'])

    ### Get the candlesticks
    for ticker in df_tickers['ticker']:
        sql_ticker_col = "select event_time, close from candlestick where ticker='{0}'"
        df_temp = query_df(sql_ticker_col.format(ticker))
        df_temp.set_index('event_time', inplace=True)
        df_temp.rename(columns={'close': ticker}, inplace=True)        
        df = df.add(df_temp, fill_value=0)

    df.to_csv(file_name)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Load the dataset from file
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;df = pd.read_csv(file_name, index_col=0)
df.drop(index=df.index[-1],axis=0, inplace=True)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Drop NA
&lt;/h2&gt;

&lt;p&gt;df.dropna(axis=1, inplace=True)&lt;/p&gt;

&lt;h2&gt;
  
  
  Print the Dataset
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;print(f"Shape: {df.shape}")
print(f"Null values: {df.isnull().values.any()}")
df

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ypd0yfpe8ihrfvx58cl.png)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>machinelearning</category>
      <category>python</category>
      <category>programming</category>
    </item>
    <item>
      <title>Learn to Incorporate Rolling Hurst Values into Your DataFrame</title>
      <dc:creator>Ed Legaspi</dc:creator>
      <pubDate>Sat, 02 Mar 2024 01:08:30 +0000</pubDate>
      <link>https://dev.to/czetsuya/learn-to-incorporate-rolling-hurst-values-into-your-dataframe-40jk</link>
      <guid>https://dev.to/czetsuya/learn-to-incorporate-rolling-hurst-values-into-your-dataframe-40jk</guid>
      <description>&lt;h2&gt;
  
  
  The hurst function.
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def hurst(ts, min_lag=1, max_lag=7):
    lags = range(min_lag, max_lag)
    tau = [np.sqrt(np.std(np.subtract(ts[lag:], ts[:-lag]))) for lag in lags]
    poly = np.polyfit(np.log(lags), np.log(tau), 1)
    return poly[0]*2.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Adding to our DataFrame
&lt;/h2&gt;

&lt;p&gt;The hurst value is computed with the last 14 close values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;df['Hurst'] = df['close'].rolling(14).apply(hurst, raw=True)
df[10:20]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5huizfpyrqhicnwiekmy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5huizfpyrqhicnwiekmy.png" alt="Image description" width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>python</category>
      <category>programming</category>
    </item>
    <item>
      <title>Implementing Glowroot: A Hands-On Tech Review for Application Monitoring Mastery</title>
      <dc:creator>Ed Legaspi</dc:creator>
      <pubDate>Mon, 05 Feb 2024 02:16:41 +0000</pubDate>
      <link>https://dev.to/czetsuya/implementing-glowroot-a-hands-on-tech-review-for-application-monitoring-mastery-31c0</link>
      <guid>https://dev.to/czetsuya/implementing-glowroot-a-hands-on-tech-review-for-application-monitoring-mastery-31c0</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;In the realms of information technology and systems management, Application Performance Management (APM) involves monitoring and overseeing the performance and availability of software applications. APM aims to identify and diagnose intricate application performance issues to uphold a predefined level of service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Glowroot&lt;/strong&gt; is an open-source APM that facilitates a quicker resolution of application performance issues by helping us pinpoint the root causes. It supports applications running from Java 6 onwards.&lt;/p&gt;

&lt;h1&gt;
  
  
  Key Features
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Response Time Breakdown Charts: Visualizes the breakdown of response times for better analysis.&lt;/li&gt;
&lt;li&gt;Response Time Percentile Charts: Offers percentile charts to understand response time distribution.&lt;/li&gt;
&lt;li&gt;SQL Capture and Aggregation: Captures and aggregates SQL queries for in-depth analysis.&lt;/li&gt;
&lt;li&gt;Service Call Capture and Aggregation: Gathers and aggregates data on service calls for comprehensive insights.&lt;/li&gt;
&lt;li&gt;MBean Attribute Capture and Charts: Monitors and charts MBean attributes for performance evaluation.&lt;/li&gt;
&lt;li&gt;Configurable Alerting: Allows users to configure alerts based on specific criteria.&lt;/li&gt;
&lt;li&gt;Historical Rollup: Provides historical data rollup at different intervals (1m, 5m, 30m, 4h) with configurable retention settings.&lt;/li&gt;
&lt;li&gt;Full Support for Async Requests: Supports asynchronous requests that span multiple threads.&lt;/li&gt;
&lt;li&gt;Responsive UI with Mobile Support: User-friendly and responsive interface with mobile support for accessibility.&lt;/li&gt;
&lt;li&gt;Optional Central Collector: Offers the flexibility of an optional central collector for centralized data management.&lt;/li&gt;
&lt;li&gt;Supports Multiple Application Servers: Wildfly, JBoss EAP, Tomcat, TomEE, Jetty, Glassfish, Payara, WebLogic, WebSphere&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Central Collector
&lt;/h1&gt;

&lt;p&gt;The central collector collects runtime information from the registered services and offers a GUI for easy viewing. &lt;a href="https://github.com/glowroot/glowroot/wiki/Central-Collector-Installation" rel="noopener noreferrer"&gt;https://github.com/glowroot/glowroot/wiki/Central-Collector-Installation&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;You can follow the steps above for running the GlowRoot central collector either as a standalone or as a docker image. For this section, I'll share how it can be run locally.&lt;br&gt;
Here's my docker-compose file for running glowroot-central with cassandra. Override username, password, and contactPoints in glowroot-central.properties.&lt;/p&gt;


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

&lt;p&gt;version: '3.8'&lt;/p&gt;

&lt;p&gt;networks:&lt;br&gt;
  tradewise-network:&lt;/p&gt;

&lt;p&gt;services:&lt;br&gt;
  cassandra:&lt;br&gt;
    image: cassandra:latest&lt;br&gt;
    container_name: cassandra&lt;br&gt;
    restart: unless-stopped&lt;br&gt;
    ports:&lt;br&gt;
      - "9042:9042"&lt;br&gt;
    networks:&lt;br&gt;
      - tradewise-network&lt;/p&gt;

&lt;p&gt;glowroot-central:&lt;br&gt;
    image: glowroot/glowroot-central:0.14.1&lt;br&gt;
    container_name: glowroot-central&lt;br&gt;
    restart: unless-stopped&lt;br&gt;
    volumes:&lt;br&gt;
      - ./glowroot-central.properties:/usr/share/glowroot-central/glowroot-central.properties&lt;br&gt;
    depends_on:&lt;br&gt;
      - cassandra&lt;br&gt;
    ports:&lt;br&gt;
      - "4000:4000"&lt;br&gt;
      - "8181:8181"&lt;br&gt;
    networks:&lt;br&gt;
      - tradewise-network&lt;/p&gt;

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

&lt;/div&gt;
&lt;h1&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Instrumentation&lt;br&gt;
&lt;/h1&gt;

&lt;p&gt;There are 4 ways in which we can integrate GlowRoot into our services  &lt;a href="https://glowroot.org/instrumentation.html" rel="noopener noreferrer"&gt;https://glowroot.org/instrumentation.html&lt;/a&gt;. For this exercise, we will focus on using the agent API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Editing the pom.xml File
&lt;/h2&gt;

&lt;p&gt;In our Spring Boot project's pom.xml file, add the GlowRoot agent configuration.&lt;/p&gt;


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

&lt;p&gt;&amp;lt;plugin&amp;gt;&lt;br&gt;
    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;&lt;br&gt;
    &amp;lt;artifactId&amp;gt;maven-resources-plugin&amp;lt;/artifactId&amp;gt;&lt;br&gt;
    &amp;lt;executions&amp;gt;&lt;br&gt;
        &amp;lt;execution&amp;gt;&lt;br&gt;
            &amp;lt;id&amp;gt;glowroot-plugins&amp;lt;/id&amp;gt;&lt;br&gt;
            &amp;lt;phase&amp;gt;validate&amp;lt;/phase&amp;gt;&lt;br&gt;
            &amp;lt;goals&amp;gt;&lt;br&gt;
                &amp;lt;goal&amp;gt;copy-resources&amp;lt;/goal&amp;gt;&lt;br&gt;
            &amp;lt;/goals&amp;gt;&lt;br&gt;
            &amp;lt;configuration&amp;gt;&lt;br&gt;
                &amp;lt;outputDirectory&amp;gt;target/glowroot-plugins/&amp;lt;/outputDirectory&amp;gt;&lt;br&gt;
                &amp;lt;resources&amp;gt;&lt;br&gt;
                    &amp;lt;resource&amp;gt;&lt;br&gt;
                        &amp;lt;directory&amp;gt;glowroot-plugins&amp;lt;/directory&amp;gt;&lt;br&gt;
                        &amp;lt;filtering&amp;gt;false&amp;lt;/filtering&amp;gt;&lt;br&gt;
                    &amp;lt;/resource&amp;gt;&lt;br&gt;
                &amp;lt;/resources&amp;gt;&lt;br&gt;
            &amp;lt;/configuration&amp;gt;&lt;br&gt;
        &amp;lt;/execution&amp;gt;&lt;br&gt;
    &amp;lt;/executions&amp;gt;&lt;br&gt;
&amp;lt;/plugin&amp;gt;&lt;/p&gt;

&lt;p&gt;&amp;lt;plugin&amp;gt;&lt;br&gt;
    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;&lt;br&gt;
    &amp;lt;artifactId&amp;gt;maven-dependency-plugin&amp;lt;/artifactId&amp;gt;&lt;br&gt;
    &amp;lt;version&amp;gt;${maven-dependency-plugin.version}&amp;lt;/version&amp;gt;&lt;br&gt;
    &amp;lt;executions&amp;gt;&lt;br&gt;
        &amp;lt;execution&amp;gt;&lt;br&gt;
            &amp;lt;id&amp;gt;copy-glowroot-jar&amp;lt;/id&amp;gt;&lt;br&gt;
            &amp;lt;phase&amp;gt;prepare-package&amp;lt;/phase&amp;gt;&lt;br&gt;
            &amp;lt;goals&amp;gt;&lt;br&gt;
                &amp;lt;goal&amp;gt;copy&amp;lt;/goal&amp;gt;&lt;br&gt;
            &amp;lt;/goals&amp;gt;&lt;br&gt;
        &amp;lt;/execution&amp;gt;&lt;br&gt;
    &amp;lt;/executions&amp;gt;&lt;br&gt;
    &amp;lt;configuration&amp;gt;&lt;br&gt;
        &amp;lt;artifactItems&amp;gt;&lt;br&gt;
            &amp;lt;artifactItem&amp;gt;&lt;br&gt;
                &amp;lt;groupId&amp;gt;org.glowroot&amp;lt;/groupId&amp;gt;&lt;br&gt;
                &amp;lt;artifactId&amp;gt;glowroot-agent&amp;lt;/artifactId&amp;gt;&lt;br&gt;
                &amp;lt;version&amp;gt;${glowroot-agent.version}&amp;lt;/version&amp;gt;&lt;br&gt;
                &amp;lt;type&amp;gt;jar&amp;lt;/type&amp;gt;&lt;br&gt;
                &amp;lt;overWrite&amp;gt;false&amp;lt;/overWrite&amp;gt;&lt;br&gt;
                &amp;lt;outputDirectory&amp;gt;${project.build.directory}&amp;lt;/outputDirectory&amp;gt;&lt;br&gt;
                &amp;lt;destFileName&amp;gt;glowroot.jar&amp;lt;/destFileName&amp;gt;&lt;br&gt;
            &amp;lt;/artifactItem&amp;gt;&lt;br&gt;
        &amp;lt;/artifactItems&amp;gt;&lt;br&gt;
    &amp;lt;/configuration&amp;gt;&lt;br&gt;
&amp;lt;/plugin&amp;gt;&lt;/p&gt;

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

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Preparing the Dockerfile&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;We need to add the GlowRoot files in the docker image.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&lt;h1&gt;
  
  
  Base Image
&lt;/h1&gt;

&lt;p&gt;FROM eclipse-temurin:17-jdk-alpine&lt;br&gt;
LABEL author=CzetsuyaTech&lt;br&gt;
LABEL maintainer=CzetsuyaTech&lt;/p&gt;
&lt;h1&gt;
  
  
  Configuration
&lt;/h1&gt;

&lt;p&gt;WORKDIR /&lt;/p&gt;

&lt;p&gt;RUN addgroup --system czetsuyatech &amp;amp;&amp;amp; \&lt;br&gt;
    adduser --system czetsuyatech --ingroup czetsuyatech &amp;amp;&amp;amp; \&lt;br&gt;
    mkdir -p /glowroot /glowroot/tmp /glowroot/logs /glowroot/plugins &amp;amp;&amp;amp; \&lt;br&gt;
    echo '{ "web": { "bindAddress": "0.0.0.0" } }' &amp;gt; /glowroot/admin.json &amp;amp;&amp;amp; \&lt;br&gt;
    chown czetsuyatech:czetsuyatech -R /glowroot &amp;amp;&amp;amp; \&lt;br&gt;
    chmod -R 777 /glowroot&lt;/p&gt;

&lt;p&gt;USER czetsuyatech&lt;br&gt;
ADD --chown=czetsuyatech:czetsuyatech target/glowroot.jar /glowroot&lt;br&gt;
ADD --chown=czetsuyatech:czetsuyatech target/glowroot-plugins /glowroot/plugins&lt;/p&gt;
&lt;h1&gt;
  
  
  Service
&lt;/h1&gt;

&lt;p&gt;ADD --chown=czetsuyatech:czetsuyatech target/*.jar app.jar&lt;/p&gt;
&lt;h1&gt;
  
  
  Start
&lt;/h1&gt;

&lt;p&gt;ENV JAVA_JAR "/app.jar"&lt;br&gt;
ENV JAVA_OTHERS "-Xshare:off"&lt;br&gt;
ENV JAVA_OPTS ${JAVA_OPTS}&lt;br&gt;
ENV JAVA_MEM ${JAVA_MEM}&lt;/p&gt;

&lt;p&gt;RUN echo "exec java $JAVA_MEM $JAVA_OPTS $JAVA_OTHERS -jar $JAVA_JAR"&lt;br&gt;
ENTRYPOINT exec java $JAVA_MEM $JAVA_OPTS $JAVA_OTHERS -jar $JAVA_JAR&lt;/p&gt;

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

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Running the Spring Boot Service&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;To enable instrumentation in our instance, we need to specify the javaagent property. And to send information to the central collector we need to specify the central collector and give our instance an agent id.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;JAVA_OPTS=-javaagent:glowroot/glowroot.jar -Dglowroot.collector.address=localhost:8181 -server -Dglowroot.agent.id=TradewiseAI&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  GUI
&lt;/h1&gt;

&lt;h1&gt;
  
  
  Usage
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk7aki3psigfk8syzkk3d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk7aki3psigfk8syzkk3d.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Transactions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Web
&lt;/h3&gt;

&lt;p&gt;To assess our REST Endpoints' performance, we access the "Web" section. In the provided example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;By choosing "Response Time," we can identify which HttpRequests and JDBC Queries are taking longer in the REST Endpoints.&lt;/li&gt;
&lt;li&gt;Opting for "Slow Traces" allows us to pinpoint the specific endpoint that consumes more time.&lt;/li&gt;
&lt;li&gt;Selecting "Queries" reveals insights into the queries made, indicating that using the count query is more resource-intensive compared to the select query. This information aids in optimizing and refining the performance of REST Endpoints.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Background
&lt;/h3&gt;

&lt;p&gt;To analyze our background performance, we navigate to the "Background" section. In the given example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Choosing "Response Time" allows us to identify which Job and Hibernate Queries are consuming more time in the background processes.&lt;/li&gt;
&lt;li&gt;Opting for "Slow Traces" reveals that some calls take more time, providing insights into areas that may require attention.&lt;/li&gt;
&lt;li&gt;Selecting "Queries" and filtering by the select query, we observe that it is called more frequently and takes longer, particularly when filtered by status. This information helps in understanding and addressing potential bottlenecks in the background processes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2tu9jlngltybia6nfbbz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2tu9jlngltybia6nfbbz.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Startup
&lt;/h3&gt;

&lt;p&gt;To assess our startup performance, we can utilize the "Startup" section. In the provided example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;By choosing "Response Time," we can identify which startup and filter init processes consume more time.&lt;/li&gt;
&lt;li&gt;Opting for "Slow Traces" reveals the duration it takes for the context to initialize fully.&lt;/li&gt;
&lt;li&gt;Selecting "Queries" provides insights into the database queries. Some queries will be more resource intensive, with fewer calls but longer duration. This information aids in pinpointing specific areas for optimization within the startup processes.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Errors
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Web
&lt;/h3&gt;

&lt;p&gt;To visualize errors in our REST endpoints, we can navigate to the "Web" section. In the following example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choosing "Error Messages" reveals errors of type XXXException.&lt;/li&gt;
&lt;li&gt;Opting for "Error Traces" provides details on the errors.&lt;/li&gt;
&lt;li&gt;Clicking on a specific error allows us to view the detailed trace, aiding in the understanding and resolution of the issue.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  JVM
&lt;/h2&gt;

&lt;p&gt;In our services' JVM, we can monitor and analyze memory status. This allows us to gain insights into the memory usage patterns, allocations, and overall health of the Java Virtual Machine, aiding in the effective management and optimization of our services.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftdo3q22y5422r8y15at5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftdo3q22y5422r8y15at5.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  MBeanTree
&lt;/h2&gt;

&lt;p&gt;The MBeanTree functionality in Glowroot proves invaluable in monitoring instance creation. For instance, to track thread-related metrics and identify potential Thread Leaks, users can navigate to the java.lang section, specifically under Threading. This allows for a detailed examination of thread-related information, aiding in the identification and resolution of potential thread-related issues, such as Thread Leaks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo68n8lnr4ex1wid1n5gb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo68n8lnr4ex1wid1n5gb.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Recommendation
&lt;/h1&gt;

&lt;p&gt;In a typical product infrastructure, Glowroot serves as our APM tool in each microservice. All microservices are instrumented to gather and transmit data to Glowroot, enhancing our understanding of system behavior. We've chosen Glowroot based on various criteria, including its license-free nature, alignment with the Java ecosystem, and straightforward instrumentation for microservices, ensuring a simple ramp-up and configuration process.&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>productivity</category>
      <category>java</category>
      <category>learning</category>
    </item>
    <item>
      <title>Navigating the Code: A Guide to Environment Variables, Configuration, and Feature Flags</title>
      <dc:creator>Ed Legaspi</dc:creator>
      <pubDate>Thu, 14 Dec 2023 00:10:28 +0000</pubDate>
      <link>https://dev.to/czetsuya/navigating-the-code-a-guide-to-environment-variables-configuration-and-feature-flags-3c07</link>
      <guid>https://dev.to/czetsuya/navigating-the-code-a-guide-to-environment-variables-configuration-and-feature-flags-3c07</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F93g7xodr20h2fvcvl07h.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F93g7xodr20h2fvcvl07h.jpg" alt="App Configuration" width="800" height="532"&gt;&lt;/a&gt;&lt;br&gt;
Determining the optimal location for storing essential information crucial for an application's functionality necessitates thoughtful planning. This guide aims to assist you in making informed decisions about where to store crucial data. Here, the term "application" encompasses any software created with code and deployed on various platforms and runtimes, irrespective of the underlying software architecture.&lt;/p&gt;

&lt;p&gt;A fundamental principle is to avoid hard-coding any values within your application. Instead, adopt the practice of retrieving all configuration settings from a distinct storage system, separate from the deployment environment. This approach allows for seamless modifications to configuration settings even after the application has been deployed, eliminating the need for redeployment. This separation ensures greater flexibility and facilitates the adjustment of critical parameters without disrupting the operational state of your deployed application.&lt;/p&gt;

&lt;p&gt;When considering the storage location for key/value pairs, it's crucial to evaluate the volatility of each pair—how frequently and by whom it might change. Reflect on the dynamic nature of the data and the responsibilities associated with its modification. This thoughtful approach will guide you in choosing an appropriate storage solution that aligns with the specific needs and characteristics of each key/value pair. By understanding the frequency and ownership of potential changes, you can make informed decisions that optimize the efficiency and maintainability of your data storage strategy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Environment Variables
&lt;/h2&gt;

&lt;p&gt;Environment variables, characterized by their infrequent changes, typically occur only once per deployment. Common examples include sensitive information like usernames and passwords for databases, which are often stored securely in a Vault. Additionally, environment variables encompass essential details required for the system's initialization, such as environment specifics and the connection details for the application configuration store, which hosts additional settings. By utilizing environment variables for these foundational aspects, you ensure a secure and stable system setup while centralizing critical configuration information.&lt;/p&gt;

&lt;h2&gt;
  
  
  Application Configuration
&lt;/h2&gt;

&lt;p&gt;Application configuration, in contrast to environment variables, operates independently of deployments. It encompasses supplementary settings for the system that have the potential to change between deployments at runtime. This flexibility allows for real-time adjustments to the application's behavior and features, accommodating evolving requirements without the need for redeployment. By leveraging application configuration for these dynamic settings, you establish a modular and adaptable structure, enhancing the responsiveness of your system to changing runtime conditions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Runtime User Settings
&lt;/h2&gt;

&lt;p&gt;Runtime user settings represent the most volatile category, as users can alter any key/value pair at any given moment. Therefore, the system must be designed to accommodate this high level of dynamism. Options for handling such volatility include implementing robust real-time validation mechanisms and ensuring the integrity and security of user-initiated changes. Additionally, the system should provide an intuitive user interface for managing these settings, enabling seamless customization while maintaining overall system stability and security.&lt;/p&gt;

&lt;h3&gt;
  
  
  Here are three options for handling configuration updates:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Re-read Configuration All the Time:&lt;/strong&gt; Continuously monitor and re-read the configuration, ensuring that the system remains up-to-date with any changes. This approach provides real-time responsiveness to modifications but may impose a continuous processing overhead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Re-read Configuration at Set Intervals (e.g., Every 15 Minutes):&lt;/strong&gt; Implement a periodic schedule to re-read the configuration at predefined intervals, such as every 15 minutes. This approach balances responsiveness with reduced processing overhead, making it suitable for scenarios where near-real-time updates are acceptable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Receive Push Notifications When New Application Configuration Is Available:&lt;/strong&gt; Set up a push notification mechanism to alert the system when new application configuration becomes available. This approach minimizes the need for continuous or scheduled re-reading, optimizing efficiency by updating the system only when changes occur. However, it requires a reliable notification infrastructure. Choosing among these options depends on the specific requirements of your system, considering factors such as the criticality of real-time updates, resource constraints, and the overall responsiveness desired for configuration changes.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>appconfig</category>
      <category>tutorial</category>
      <category>learning</category>
    </item>
    <item>
      <title>Java XML Validation: How to Validate an XML Document against an XSD</title>
      <dc:creator>Ed Legaspi</dc:creator>
      <pubDate>Sat, 01 Jul 2023 11:58:22 +0000</pubDate>
      <link>https://dev.to/czetsuya/java-xml-validation-how-to-validate-an-xml-document-against-an-xsd-nn7</link>
      <guid>https://dev.to/czetsuya/java-xml-validation-how-to-validate-an-xml-document-against-an-xsd-nn7</guid>
      <description>&lt;p&gt;Introducing our Java XML Validation Project! Master the art of validating XML effortlessly against XSD in a Java environment. Gain hands-on experience, ensuring the integrity and conformity of your data.&lt;/p&gt;

&lt;h1&gt;
  
  
  1. Introduction
&lt;/h1&gt;

&lt;p&gt;Introducing our Java XML Validation Project! Gain hands-on experience in validating XML documents against XSD with ease. This project serves as a practical guide, equipping you with the necessary knowledge and tools to ensure the integrity and conformity of your XML data in a Java environment. Discover the simplicity of our step-by-step approach, which walks you through the entire validation process. Master the art of validating XML effortlessly and unlock a new level of confidence in your data. Join us on this journey as we empower you to harness the power of XML validation in your Java projects. &lt;/p&gt;

&lt;h1&gt;
  
  
  2. Generating Java Classes from XSD
&lt;/h1&gt;

&lt;p&gt;For this exercise, we will be using an XSD from w3schools  &lt;a href="https://www.w3schools.com/xml/schema_example.asp"&gt;https://www.w3schools.com/xml/schema_example.asp&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To be able to generate the Java classes from XSD, we will be using Eclipse Enterprise Edition. IntelliJ can also do it with the Jakarta plugin, but Eclipse performs better, especially when dealing with XJB files.&lt;/p&gt;

&lt;p&gt;IntelliJ&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fclhm3821xl2sfg2b33lj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fclhm3821xl2sfg2b33lj.png" alt="Image description" width="800" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Eclipse JAXB Classes Generator&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft98dbv71fkwtl60jak2r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft98dbv71fkwtl60jak2r.png" alt="Image description" width="800" height="727"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Generated Classes&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fceuz1p5bxrwxqkepueka.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fceuz1p5bxrwxqkepueka.png" alt="Image description" width="800" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  3. Dependencies
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;com.fasterxml.jackson.dataformat&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;jackson-dataformat-xml&amp;lt;/artifactId&amp;gt;
&amp;lt;/dependency&amp;gt;

&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;jakarta.activation&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;jakarta.activation-api&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.1.1&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;jakarta.xml.bind&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;jakarta.xml.bind-api&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;${jakarta.version}&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.glassfish.jaxb&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;jaxb-runtime&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;${jakarta.version}&amp;lt;/version&amp;gt;
    &amp;lt;scope&amp;gt;runtime&amp;lt;/scope&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  4. Core Classes
&lt;/h1&gt;

&lt;p&gt;To run the validations and throw the appropriate exception or name of the tag where a constraint is violated, we will need the following classes.&lt;/p&gt;

&lt;h2&gt;
  
  
  4.1 ResourceResolver
&lt;/h2&gt;

&lt;p&gt;To import an external XSD, for example, if we will be using the XML digital signature.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;xs:import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="xmldsig-core-schema.xsd"/&amp;gt;&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ResourceResolver implements LSResourceResolver {

  private static final Logger LOGGER = LoggerFactory.getLogger(ResourceResolver.class);

  public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) {

    // note: in this sample, the XSD's are expected to be in the root of the classpath
    InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("xsd/" + systemId);
    return new Input(publicId, systemId, resourceAsStream);
  }

  static class Input implements LSInput {

    private String publicId;

    private String systemId;

    public String getStringData() {

      String textDataFromFile;

      try {
        BufferedReader bufferReader = new BufferedReader(new InputStreamReader(inputStream));
        StringBuilder stringBuilder = new StringBuilder();
        String eachStringLine;

        while ((eachStringLine = bufferReader.readLine()) != null) {
          stringBuilder.append(eachStringLine).append("\n");
        }
        textDataFromFile = stringBuilder.toString();

        return textDataFromFile;

      } catch (IOException e) {
        LOGGER.error("Fail reading from inputStream={}", e.getMessage());
        return null;
      }
    }
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4.2 SaxErrorHandler
&lt;/h2&gt;

&lt;p&gt;For us to be able to know the tag where a constraint exception is thrown, we need to define a custom exception that accepts an XMLStreamReader object where we can get the localName property.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class SaxErrorHandler implements ErrorHandler {

  private XMLStreamReader reader;

  public SaxErrorHandler(XMLStreamReader reader) {
    this.reader = reader;
  }

  @Override
  public void error(SAXParseException e) {
    warning(e);
  }

  @Override
  public void fatalError(SAXParseException e) {
    warning(e);
  }

  @Override
  public void warning(SAXParseException e) {

    throw new XmlValidationException(reader.getLocalName());
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4.3 Miscellaneous Classes
&lt;/h2&gt;

&lt;p&gt;We will also be needing utility classes for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating a JAXBElement&lt;/li&gt;
&lt;li&gt;Convert JAXBElement to XMLStreamReader&lt;/li&gt;
&lt;li&gt;Defining the correct marshaller object&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These classes are all available in the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  4.4 XmlSchemaValidator Interface
&lt;/h2&gt;

&lt;p&gt;And finally, the interface that pieces together all components to do the validation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;default void validateXMLSchema(String xsdPath, JAXBElement&amp;lt;?&amp;gt; xml) {

  Validator validator = null;
  try {
    SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
    factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
    factory.setResourceResolver(new ResourceResolver());

    Schema schema = factory.newSchema(ResourceUtils.getFile(xsdPath));
    validator = schema.newValidator();
    XMLStreamReader xmlStreamReader = asStreamReader(xml);

    ErrorHandler errorHandler = new SaxErrorHandler(xmlStreamReader);
    validator.setErrorHandler(errorHandler);

    validator.validate(new StAXSource(xmlStreamReader));

  } catch (IOException | SAXException | JAXBException | XMLStreamException e) {

    var xmlEx = getXmlValidationExceptionIfPresent(e);
    throw new InvalidXmlException(xmlEx.getLocalName(), e);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  5. Source Code / Git Repository
&lt;/h1&gt;

&lt;p&gt;The complete source code for this project is available for my sponsors at &lt;a href="https://github.com/czetsuyatech/java-xml-validation-by-xsd"&gt;https://github.com/czetsuyatech/java-xml-validation-by-xsd&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Sponsorship link: &lt;a href="https://github.com/sponsors/czetsuya"&gt;https://github.com/sponsors/czetsuya&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Project Screenshot&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxybdgpwcqcu0pnhv9mkf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxybdgpwcqcu0pnhv9mkf.png" alt="Image description" width="800" height="567"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>xml</category>
      <category>xsd</category>
    </item>
  </channel>
</rss>
