<?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: Petter Holmström</title>
    <description>The latest articles on DEV Community by Petter Holmström (@peholmst).</description>
    <link>https://dev.to/peholmst</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F617684%2Fecd6a636-8d82-4e61-930d-cf87ebe6850b.jpg</url>
      <title>DEV Community: Petter Holmström</title>
      <link>https://dev.to/peholmst</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/peholmst"/>
    <language>en</language>
    <item>
      <title>Thoughts on AI and Software Design Patterns</title>
      <dc:creator>Petter Holmström</dc:creator>
      <pubDate>Fri, 31 Oct 2025 09:47:08 +0000</pubDate>
      <link>https://dev.to/peholmst/thoughts-on-ai-and-software-design-patterns-3f59</link>
      <guid>https://dev.to/peholmst/thoughts-on-ai-and-software-design-patterns-3f59</guid>
      <description>&lt;p&gt;&lt;em&gt;Before I start, I should mention that I have not yet tried out vibe coding myself. I use AI every day for programming related tasks, but I still write the code myself, for myself. This blog post was inspired by a dream I had last night, after having spent a stressful week thinking about these sort of things. I had to write it down to get it out of my head and make some sense of it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I started programming "real" applications with Borland Delphi in the late 1990s, when I was a teenager. My first database applications were two-tiered Delphi user interfaces on top of Paradox databases. I did not know SQL and relied only on Delphi's ready-made database components. The user interface was therefore 100% driven by the database schema. It worked, it got the job done, and you could tell that it was a Delphi application only by looking at it.&lt;/p&gt;

&lt;p&gt;Then the three-tiered paradigm showed up. You were now supposed to have an application server between the UI and the database. Business logic. Business objects. Web services. Thin clients. Web clients. APIs. I learned PHP and MySQL. Then Java, Spring, and Hibernate. I built UIs with Swing and Eclipse RCP because the old web 1.0 user interfaces felt too restricting.&lt;/p&gt;

&lt;p&gt;I heard about Vaadin the first time when I was interviewing for a position at the company (then called IT Mill). I got hired and started my professional journey into web application development with Java.&lt;/p&gt;

&lt;p&gt;Back then, our motto was "thinking of U and I". When we gave trainings to other companies, we started by saying that "to the end user, the user interface &lt;em&gt;is&lt;/em&gt; the product". Proper UX design was key in all customer projects we delivered. This was a long step away from the data-driven CRUD user interfaces that I used to build with Delphi a decade earlier.&lt;/p&gt;

&lt;p&gt;As I worked on customer projects, the biggest challenges were not actually in the user interface, but in the backend. I made lots of mistakes while also cleaning up other peoples' mistakes. Many problems could have been avoided with better architectural design decisions. I learned domain-driven design, first the tactical part, later the strategic part. I read about architectural styles and object oriented design patterns. Decoupling. Separation of concerns. Abstractions. All these helped me build better systems, although it took a while to find the right balance between them.&lt;/p&gt;

&lt;p&gt;I started to see system design and coding as a craft, and finished code as an art. There is beauty in well designed and well written software. I bet that's what tailors, carpenters, blacksmiths and other craftspeople thought right before the industrial revolution.&lt;/p&gt;

&lt;p&gt;Now look around us. Everything, from clothes to furniture to household items to houses, is streamlined and functional and boring. Mass-produced. Non-customized. Cheap. And gets the job done.&lt;/p&gt;

&lt;p&gt;Is this what is happening with the software through the AI revolution? If the code is generated by an AI, the most important artefacts become the specifications and the database. If these are designed well enough, the rest can be generated. And if it can be generated, it can be thrown away and re-generated in the future when a better model comes along.&lt;/p&gt;

&lt;p&gt;Is this going to lead us back to the data-driven programming model of the 1990s, where user interfaces where just a thin layer on top of the database? They were ugly, but they worked. If you can get them generated by an AI for a fraction of the cost it would have taken to build them manually, is poorer UX an acceptable trade off? To many people and companies I think it might be.&lt;/p&gt;

&lt;p&gt;This in turn makes me question the need for many of the design patterns that I have learned to use and even take for granted. The design patterns we use today were built by humans, for humans. Their intention was to make code bases easy to read, understand, maintain and extend, over long periods of time. If the code base can now be auto-generated, does it matter how it is structured? &lt;/p&gt;

&lt;p&gt;Should our focus as developers shift to writing good specs and creating good database schemas, and just accept whatever the AI spits out as long as it makes the tests pass and gets the job done? Do we need to worry about separation of concerns? Decoupling? Layers? Extendability? Should we still think about database normalization or try to design database schemas that are more humane, as they could be used as a basis for UI generation? Should we still be teaching and writing about coding patterns these days? Or should we focus on architectural patterns and start treating the code itself as human-readable byte code?&lt;/p&gt;

&lt;p&gt;I know I will continue to make hand-crafted applications on my free time, because I enjoy it - just as there are still carpenters, tailors, and blacksmiths making things by hand (with some help of modern power tools). But professionally, I'm writing documentation and examples for other developers - and AIs - to learn from. And now I'm not sure what level of detail I should focus on. What I have built my career on, and gained all my experience from, appears to become more and more outdated as time passes.&lt;/p&gt;

</description>
      <category>design</category>
      <category>ai</category>
      <category>coding</category>
      <category>braindump</category>
    </item>
    <item>
      <title>How I think about Vaadin application architecture today</title>
      <dc:creator>Petter Holmström</dc:creator>
      <pubDate>Thu, 27 Mar 2025 14:27:48 +0000</pubDate>
      <link>https://dev.to/peholmst/how-i-think-about-vaadin-application-architecture-today-2ejp</link>
      <guid>https://dev.to/peholmst/how-i-think-about-vaadin-application-architecture-today-2ejp</guid>
      <description>&lt;p&gt;During the past year, my main task at work has been to come up with and publish a recommendation for how business applications should be built with Vaadin. This is an ongoing task that won't end as long as Vaadin remains in business. It's also a task that involves sifting through lots of patterns, practices, and opinions. Everybody has their own preferred way of building business applications with Vaadin - including myself.&lt;/p&gt;

&lt;p&gt;You may already have read my articles about domain-driven design. It's still an approach I keep close to my heart, but I also realize there are many cases in which other approaches are more appropriate. I could say the same about the ports-and-adapters/hexagonal architectural style.&lt;/p&gt;

&lt;h2&gt;
  
  
  Well, It Depends
&lt;/h2&gt;

&lt;p&gt;When I was still working as a consultant, helping customers with various Vaadin (and sometimes non-Vaadin) related problems, my first answer to many of their question was "well, it depends". Then, as we gathered more information about the problem, we could narrow down the options until we were confident to make a decision.&lt;/p&gt;

&lt;p&gt;When making an architecture recommendation, there's no size that fits all. The best you can do is to come up with a recommendation that hopefully scales. You start out with something simple that you can expand later, if needed. You have to future proof just enough, avoiding painting yourself into a corner while also not over-engineering anything.&lt;/p&gt;

&lt;p&gt;My approach to this problem was to go back to the various designs and architectures I've used in my career, and my favorite books on the subject. However, instead of just selecting one at face value, I wanted to pick them apart to find the fundamental ideas behind each, and build something from that.&lt;/p&gt;

&lt;p&gt;I wanted to find something that would resonate with most developers (including myself), use terms that were familiar to most developers, and that could be converted into the most common architectural styles without too much effort.&lt;/p&gt;

&lt;h2&gt;
  
  
  Backend or Frontend?
&lt;/h2&gt;

&lt;p&gt;I soon ran into my first terminology problem. A traditional web-app consists of a frontend and a backend. The frontend contains the UI and runs in the browser; the backend contains the business logic and runs on the server. However, this is problematic in a Vaadin application.&lt;/p&gt;

&lt;p&gt;For a Hilla UI, the frontend-backend distinction still applies. For a Flow UI, a big chunk of the user interface actually lives and runs on the server. I decided to introduce the terms &lt;strong&gt;presentation layer&lt;/strong&gt; and &lt;strong&gt;application layer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The presentation layer contains everything related to the user interface, regardless of whether it's running in the browser or on the server. &lt;/p&gt;

&lt;p&gt;The application layer contains "the rest of the application", that is, business logic, persistence, integrations to other systems, and so on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2vh446unct7dlat03nwc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2vh446unct7dlat03nwc.png" alt="The presentation and application layers in Flow and Hilla" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thus, instead of talking about frontend and backend, I try to talk about presentation layer and application layer. I'm still doubting whether I should have called the presentation layer the &lt;em&gt;UI layer&lt;/em&gt; instead...&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting in the Presentation Layer
&lt;/h2&gt;

&lt;p&gt;Since Vaadin has always been about the user interface, I decided to start there. If I stand in the presentation layer and look at the application layer, what do I see? A big, black box with API:s that I can use. Some API:s may be more generic in nature, others may have been especially crafted for me alone.&lt;/p&gt;

&lt;p&gt;Now what to call these API:s? Ports? Endpoints? Facades? Boundaries? Services? Controllers? I decided to settle for &lt;strong&gt;application services&lt;/strong&gt;, inspired by the book &lt;em&gt;Implementing Domain-Driven Design&lt;/em&gt; by Vaughn Vernon. I figured most developers would be OK with the idea of having a user interface call services to do what it needs to do.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F58zl4s3k6r3ui1g30svh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F58zl4s3k6r3ui1g30svh.png" alt="A diagram illustrating the presentation layer calling an API of the application layer" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking at the Application Services
&lt;/h2&gt;

&lt;p&gt;So what does the implementation of the application services themselves look like? Well, that depends... For instance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They could send SQL queries to a database directly. I would not recommend this for anything but really simple, throw-away applications, but it is possible.&lt;/li&gt;
&lt;li&gt;They could implement business logic and delegate to DAO:s or repositories to interact with the database.&lt;/li&gt;
&lt;li&gt;They could orchestrate workflows with a deep domain model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Regardless of how the application services are implemented, I think they should always handle two main responsibilities: &lt;strong&gt;manage transactions&lt;/strong&gt; and &lt;strong&gt;enforce security&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Transactions
&lt;/h3&gt;

&lt;p&gt;If an application service method touches a database, I believe that method should run inside its own transaction. The application service itself should be responsible for starting the transaction, and either committing it or rolling it back before returning. &lt;/p&gt;

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

&lt;p&gt;I've always considered security in the user interface as improvements of the user experience rather than real security. Even when writing Flow UI:s, I've always protected my application services with method-level security. This means that even if I forget to hide or disable a button in the UI, a user can't perform an unauthorized operation. &lt;/p&gt;

&lt;p&gt;This is also the main reason why I never recommend people call DAO:s or repositories directly from their user interfaces. Although you can protect a repository with method-level security, it makes other things more difficult. One good example is writing background jobs, where the a background thread needs to access the database without a valid security context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layers vs. Components
&lt;/h2&gt;

&lt;p&gt;I wanted to get away from the traditional layered way of thinking (UI layer, business layer, domain layer, entity layer, infrastructure layer, whatever-you-want-to-call-it-layer). I believe this is too limited, especially if you're only allowing dependencies from an upper layer to a lower one. This makes some things more difficult than they need be.&lt;/p&gt;

&lt;p&gt;Instead, inspired by the &lt;a href="https://c4model.com/" rel="noopener noreferrer"&gt;C4 model&lt;/a&gt; of visualizing software, I've explored a component based approach, where an application consists of multiple components that interact with each other. These components aren't classified into any particular layer (except, maybe the presentation layer and application layer).&lt;/p&gt;

&lt;p&gt;In my mind, a component has the following qualities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It can have an API that can be called by other components.&lt;/li&gt;
&lt;li&gt;It can have an SPI that can be implemented by other components.&lt;/li&gt;
&lt;li&gt;It can be instantiated.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The problem here is that &lt;em&gt;component&lt;/em&gt; is a saturated term in our industry. There are components everywhere and they all mean slightly different things. For instance, in Vaadin Flow, you compose your user interfaces by combining UI components. &lt;/p&gt;

&lt;p&gt;In Spring, you can make a bean by annotating it with &lt;code&gt;@Component&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Java as a language has no concept of a component at all.&lt;/p&gt;

&lt;p&gt;So what is a component then? Is every application service a component, or do they form a component together? Is the domain model a component, or does it consist of components? What about integrations to other systems? Background jobs? Event listeners? Utility classes? &lt;/p&gt;

&lt;p&gt;Enter analysis paralysis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Naming is Difficult
&lt;/h2&gt;

&lt;p&gt;My first attempt was to distinguish between &lt;em&gt;system components&lt;/em&gt; and &lt;em&gt;UI components&lt;/em&gt;, but I'm about to abandon that. I don't like terms that require a prefix for people to understand what they mean. Having &lt;em&gt;application service&lt;/em&gt; and &lt;em&gt;domain service&lt;/em&gt; as separate concepts is bad enough.&lt;/p&gt;

&lt;p&gt;I've talked with colleagues and various LLMs about alternative naming, but nothing has really stuck. I'm now looking at identifying the typical building blocks of a business application and calling them what they are: entities, services, background jobs, repositories, and so on. I no longer try to force them into being components; however I do think many of them have the component qualities I listed earlier. &lt;/p&gt;

&lt;p&gt;I've also started to look closer at Spring Modulith to see if I can get some inspiration from there, though at first sight, I think its application modules are more coarse-grained than what I'm looking for here. Or maybe not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;I plan to explore what a modern, data-driven Vaadin application could look like, and what a modern, domain-driven Vaadin application could look like. I'm hoping to get new insights and ideas that will make developing business applications in Vaadin even easier in the future.&lt;/p&gt;

&lt;p&gt;If you have any comments, thoughts, suggestions, or counter-arguments I would very much like to hear from you!&lt;/p&gt;

</description>
      <category>vaadin</category>
      <category>architecture</category>
      <category>behindthescenes</category>
    </item>
    <item>
      <title>A Potentially Expensive Mistake</title>
      <dc:creator>Petter Holmström</dc:creator>
      <pubDate>Mon, 27 Feb 2023 14:45:06 +0000</pubDate>
      <link>https://dev.to/peholmst/a-potentially-expensive-mistake-53l9</link>
      <guid>https://dev.to/peholmst/a-potentially-expensive-mistake-53l9</guid>
      <description>&lt;p&gt;Once upon a time, there was a project. We upgraded its JVM from Java 11 to Java 17 and did some smoke testing. Everything looked fine, except our financial values, which were not formatted correctly anymore.&lt;/p&gt;

&lt;p&gt;We had been using the standard &lt;code&gt;NumberFormat&lt;/code&gt; class with the correct locale in order to ensure the correct formatting. Java 11 did this right and formatted numbers with spaces as thousand separators, like this: &lt;code&gt;1 000 000&lt;/code&gt;. Java 17, for some strange reason, decided to change this and used commas instead, like this: &lt;code&gt;1,000,000&lt;/code&gt;, even though the locale was exactly the same.&lt;/p&gt;

&lt;p&gt;We of course needed to fix this, so we changed the &lt;code&gt;DecimalFormatSymbols&lt;/code&gt; 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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;formatter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;NumberFormat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getNumberInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;locale&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;symbols&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="nc"&gt;DecimalFormat&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDecimalFormatSymbols&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;symbols&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setGroupingSeparator&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;' '&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;symbols&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setMonetaryGroupingSeparator&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;' '&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="nc"&gt;DecimalFormat&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;setDecimalFormatSymbols&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbols&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This did the trick and the financial values were again formatted correctly and all was well, right?&lt;/p&gt;

&lt;p&gt;Unfortunately not. You can also use &lt;code&gt;NumberFormat&lt;/code&gt; to parse strings and in a few places of the code, we did just this. When we were using only &lt;code&gt;NumberFormat.getNumberInstance(locale)&lt;/code&gt; without any customization, this worked exactly as it was supposed to. Once we started to do customization of the formatting, things took a dangerous turn that was not picked up by any of our unit tests.&lt;/p&gt;

&lt;p&gt;If you take a value formatted by the customized formatter and asks a non-customized formatter to parse it, like this, what do you get?&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;formatted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000000&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "1 000 000"&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;NumberFormat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getNumberInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;locale&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;formatted&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ??&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It turns out, the &lt;code&gt;parsed&lt;/code&gt; variable above will not contain the value of &lt;code&gt;1000000&lt;/code&gt;, but &lt;code&gt;1&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;You see, the &lt;code&gt;NumberFormat.parse&lt;/code&gt; method only parses the beginning of the string. Once it encounters a character it does not recognize, it stops and returns the result. For example this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1000 pirates on a ship"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;will not throw an exception but return &lt;code&gt;1000&lt;/code&gt; and discard the rest of the string. I was not aware of this, even though it says so in the JavaDocs. This also happened with the parsing of the financial values, since space as a thousand separator was not a valid character from the point of view of the uncustomized formatter.&lt;/p&gt;

&lt;p&gt;Needless to say, converting one million into one is quite a serious bug. In our case, it made it all the way into production before we caught it but luckily, it had not managed to cause any damage yet.&lt;/p&gt;

&lt;p&gt;I had not expected a change of VM to have this kind of effect, but it is often the unexpected bugs that end up biting you the hardest.&lt;/p&gt;

</description>
      <category>gratitude</category>
    </item>
    <item>
      <title>Eventual Consistency Through Scheduled Jobs</title>
      <dc:creator>Petter Holmström</dc:creator>
      <pubDate>Thu, 29 Jul 2021 09:57:14 +0000</pubDate>
      <link>https://dev.to/peholmst/eventual-consistency-through-scheduled-jobs-3f34</link>
      <guid>https://dev.to/peholmst/eventual-consistency-through-scheduled-jobs-3f34</guid>
      <description>&lt;p&gt;In my last &lt;a href="https://dev.to/peholmst/handling-domain-events-with-spring-2bmm"&gt;blog post&lt;/a&gt;, I left you with a cliffhanger: how to recover from situations where individual domain event handlers fail or the entire system crashes after a transaction has committed, but before all domain event handlers have processed the event.&lt;/p&gt;

&lt;p&gt;Like with most (if not all?) problems in software, there is no silverbullet-one-size-fits-all-solution here. Instead, you have to find the solution that best meets the requirements of your particular system. In this blog post, we are going to look at an easy(ish) approach of guaranteeing eventual consistency even if we miss a domain event now and then. The examples assume we are using Spring and Java, but the principles apply to other frameworks and languages as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  The General Idea
&lt;/h2&gt;

&lt;p&gt;The idea behind this approach is to use scheduled jobs instead of (or in addition to) domain events to synchronise state between aggregates or even between bounded contexts. The jobs run automatically at different intervals or times of day, but can also be triggered by domain event handlers. This means that if all goes well, the data will become consistent across the system &lt;em&gt;within seconds&lt;/em&gt; of the domain event firing. On the other hand, if something goes wrong, the data will become consistent &lt;em&gt;after the next successful scheduled run&lt;/em&gt;.&lt;/p&gt;

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

&lt;p&gt;A system like this is not difficult to implement, but also not as trivial as it may seem at first look because of some caveats. However, you can avoid them by following these guidelines:&lt;/p&gt;

&lt;h3&gt;
  
  
  Make Your Jobs Accept All or Some Inputs
&lt;/h3&gt;

&lt;p&gt;When you run a scheduled job, it is typically some kind of batch operation that works on all applicable inputs. However, in this particular case, you also want to be able to run the job on just one particular input or a small set of inputs. This allows for a lot of flexibility and is quite easy to do if you design the job in this way from the start.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;

&lt;p&gt;Let's say you have a job that will create an invoice for an order that has been shipped. The class would have the following methods:&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;@Component&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;InvoiceCreationJob&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Transactional&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;propagation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;REQUIRES_NEW&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;    
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;createInvoiceForOrders&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderId&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//...&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Transactional&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;propagation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;REQUIRES_NEW&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;    
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;createInvoiceForAllOrders&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//...&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The first method creates invoices for the orders whose IDs have been passed as method parameters (provided, of course, that those orders have been shipped and not invoiced yet; more about that later).&lt;/li&gt;
&lt;li&gt;The second method is a batch job that creates invoices for &lt;em&gt;all&lt;/em&gt; orders that have been shipped and not invoiced yet.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Decouple the Job and the Triggering of the Job
&lt;/h3&gt;

&lt;p&gt;When you design your jobs, think about when and how they will be triggered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When the system starts up?&lt;/li&gt;
&lt;li&gt;Manually by a user?&lt;/li&gt;
&lt;li&gt;In response to a domain event?&lt;/li&gt;
&lt;li&gt;As a scheduled job?&lt;/li&gt;
&lt;li&gt;Through JMX?&lt;/li&gt;
&lt;li&gt;In some other way you are not aware of yet? &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I would recommend a design that looks like this:&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;The job itself is a separate object that does its thing when told to by other objects.&lt;/li&gt;
&lt;li&gt;The application service starts the job in response to human user actions.&lt;/li&gt;
&lt;li&gt;The domain event handler starts the job in response to a domain event.&lt;/li&gt;
&lt;li&gt;The worker handles scheduled job executions (such as once per hour, every ten minutes or every day at midnight).&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;

&lt;p&gt;Let's continue with the invoice generation example. We start with a domain event handler that generates an invoice as soon as an order has been shipped:&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;@DomainEventHandler&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;InvoiceGenerationOnShipmentTrigger&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;InvoiceCreationJob&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;InvoiceGenerationOnShipmentTrigger&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="nc"&gt;InvoiceCreationJob&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;job&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@TransactionalEventListener&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onInvoiceShipped&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;InvoiceShippedEvent&lt;/span&gt; &lt;span class="n"&gt;evt&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createInvoiceForOrders&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;evt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOrderId&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;Next, we want to trigger the job every day at midnight:&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;@Component&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;InvoiceGenerationWorker&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;InvoiceCreationJob&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;InvoiceGenerationWorker&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;InvoiceCreationJob&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;job&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Scheduled&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cron&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0 0 0 1/1 * ? *"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;atMidnight&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createInvoiceForAllOrders&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;Finally, we want administrators to be able to trigger the job at any time through an application service:&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;@Service&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;InvoiceGenerationService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;InvoiceCreationJob&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;InvoiceGenerationService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;InvoiceCreationJob&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;job&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Secured&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ROLE_ADMIN"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@Async&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;createInvoiceForAllOrders&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createInvoiceForAllOrders&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Make Your Jobs Idempotent
&lt;/h3&gt;

&lt;p&gt;When you write a job, you know what the intended end state of the system is going to be. However, you should never make any assumptions about this nor should you make assumptions about what the start state is. Your job should always &lt;em&gt;check&lt;/em&gt; what the start state is, and then figure out what actions it needs to take in order to get to the desired end state. If the system is already in the desired state, your job &lt;em&gt;should do nothing&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If your job is implemented like this, you can run it as many times as you want with the same inputs and it will not cause any side effects (like generating multiple invoices for the same order). If a job execution fails because of e.g. a network error or power outage, you can just re-run it later.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;

&lt;p&gt;Let's again continue with the invoice generation example. In the initial design, the states an order will traverse through are the following:&lt;/p&gt;

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

&lt;p&gt;The first step on our road to idempotence is therefore to check the state of the order and only take action if that state is &lt;code&gt;SHIPPED&lt;/code&gt;. For each shipped order, the job will then perform the following:&lt;/p&gt;

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

&lt;p&gt;However, there is a problem here: what happens if the second transaction fails for some reason? That would mean that the next time the job runs, there is already an invoice even though the state is &lt;code&gt;SHIPPED&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Thus, the next step on our road to idempotence is to detect whether an invoice has already been create for a particular order. We can do this by adding an &lt;code&gt;OrderId&lt;/code&gt; field to the &lt;code&gt;Invoice&lt;/code&gt; aggregate and use this to check that no invoices have been created before creating a new one. If an invoice already exists, the job will just proceed to setting the state to &lt;code&gt;INVOICED&lt;/code&gt; (you will need some database constraints or pessimistic locking to implement this properly, but that is outside the scope of this article)&lt;/p&gt;

&lt;p&gt;In more complex situations, you may have to add some intermediate states (such as &lt;code&gt;INVOICE_GENERATION_IN_PROGRESS&lt;/code&gt;) to be able to pick up where you left off in case of failures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Avoid Simultaneous Executions of the Same Job
&lt;/h3&gt;

&lt;p&gt;Since your job can be started in many different ways, there is a risk that it will be started while it is already running. If the job is idempotent, this should not cause any data consistency problems, but you may end up with transaction deadlocks or other concurrency issues. Also it is a waste of resources and may slow down other parts of the system.&lt;/p&gt;

&lt;p&gt;If simultaneous executions of the same job is a rare occurrence, you may choose to just live with it and let the idempotence handle it. However, if it happens frequently, you should deal with it in some way. The action you take depends on the use case, but typically it is one of the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let the current job finish, do not start the new job at all.&lt;/li&gt;
&lt;li&gt;Cancel the current job, then start the new job.&lt;/li&gt;
&lt;li&gt;Let the current job finish, then start the new job.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;

&lt;p&gt;I could write an entire blogpost only about this particular problem so for this example, we are going to narrow down the scope quite a bit and continue to use the invoice generation case.&lt;/p&gt;

&lt;p&gt;Let's say we are dealing with a small application that is only deployed as a single instance so we do not need to worry about situations where the same job runs at the same time on different machines.&lt;/p&gt;

&lt;p&gt;The first thing we want to do is to make sure that only one instance of the batch operation can run at a time. The easiest way of doing this is with an &lt;code&gt;AtomicBoolean&lt;/code&gt; (because &lt;code&gt;InvoiceCreationJob&lt;/code&gt; is a singleton):&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;@Component&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;InvoiceCreationJob&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;AtomicBoolean&lt;/span&gt; &lt;span class="n"&gt;working&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;AtomicBoolean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;@Transactional&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;propagation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;REQUIRES_NEW&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;    
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;createInvoiceForAllOrders&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;working&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;compareAndSet&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// Do the work&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;working&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;set&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&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;ul&gt;
&lt;li&gt;If the &lt;code&gt;working&lt;/code&gt; variable is &lt;code&gt;false&lt;/code&gt;, if till be set to &lt;code&gt;true&lt;/code&gt; and the work is allowed to start. Once finished, the &lt;code&gt;working&lt;/code&gt; variable is set back to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If the &lt;code&gt;working&lt;/code&gt; variable is &lt;code&gt;true&lt;/code&gt;, the method will do nothing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is good enough since the batch operation is only used as a fallback solution in case we would fail to properly handle some &lt;code&gt;InvoiceShippedEvent&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;What about the &lt;code&gt;createInvoiceForOrders&lt;/code&gt; method then? This method is likely to run simultaneously for different &lt;code&gt;Order&lt;/code&gt;s but that is not a problem so we do not want to prevent that. &lt;/p&gt;

&lt;p&gt;The method is unlikely to run simultaneously for the same &lt;code&gt;Order&lt;/code&gt; although it still &lt;em&gt;can&lt;/em&gt; happen. In this case, we can rely on the idempotence of the operation. The same applies to the case where &lt;code&gt;createInvoiceForOrders&lt;/code&gt; and &lt;code&gt;createInvoiceForAllOrders&lt;/code&gt; are running simultaneously.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Threads Wisely
&lt;/h3&gt;

&lt;p&gt;When you implement a job, you should think about which thread it is going to run in. Will it always run inside of its own thread regardless of how it was started, or inside the thread that started it, or a combination of both?&lt;/p&gt;

&lt;p&gt;Let's have a look an some examples to illustrate why this is important:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let's say a job is scheduled to be continuously executed by a worker with a five minute delay. This means that a new job should start five minutes after the previous one has finished. Now, if the job runs inside its own thread, the worker will think it has finished as soon as the job thread has started. If the job was to take longer than five minutes, the worker would start a new job even though the old one is still running. In this case, it is better to let the job run in the thread that started it.&lt;/li&gt;
&lt;li&gt;Another job is started by the user through an application service. This is also a long running job. Now, if the job runs inside the thread that started it, it would block the UI until the job is finished. In this case, it is better to let the job run in its own thread.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now let's say the jobs mentioned above are actually the same job. In order to keep your options open, &lt;em&gt;you should always implement your jobs to run inside the calling thread&lt;/em&gt; and then &lt;em&gt;let the callers worry about which thread to use&lt;/em&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;

&lt;p&gt;Scroll back up to the example that demonstrates different ways of triggering the job. Note that the application service uses the &lt;code&gt;@Async&lt;/code&gt; annotation whereas the domain event handler and the worker do not. Why? Let's have a look at each case:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The application service is invoked through a UI and is used by administrators to manually trigger the batch job. This job can take some time to complete and we do not want this to block the UI. Therefore, we run it asynchronously inside a background thread.&lt;/li&gt;
&lt;li&gt;The domain event handler is invoked when an event arrives and is a bit of an edge case: when you have a small number of event handlers that return quickly you can run them in the calling thread. However, if you have a large number of handlers or some of them take time to complete, you may want to run them in a background thread.&lt;/li&gt;
&lt;li&gt;The worker is already invoked by a background thread so we can continue to use that.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use Upper Limits in Your Queries
&lt;/h3&gt;

&lt;p&gt;Your jobs will perform different queries to determine the state of the system. The amount of data that needs to be processed depends on many factors, such as how heavily the system has been used or when the job was last run.&lt;/p&gt;

&lt;p&gt;Because of this, whenever you write a query, you should stick to the good ol' rule of thumb: &lt;em&gt;Any query will return either no records, exactly one record, or a huge load of records&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Unless you know for sure that the query falls in the first two categories, you should always add an upper limit to your query. You can either implement the job to run in batches until there is no more data to process, or just process the first N records and then wait for the next run.&lt;/p&gt;

&lt;h3&gt;
  
  
  Schedule Jobs Wisely
&lt;/h3&gt;

&lt;p&gt;When you schedule a job, you typically have the following alternatives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Fixed rate&lt;/em&gt;: the job is started at a fixed rate, such as once every 60 minutes.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Fixed delay&lt;/em&gt;: the job is started with a fixed delay after the previous execution finished.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Cron&lt;/em&gt;: the job is started at a particular time of the day, or day of the week, such as five minutes past every hour, or 2 o'clock in the morning on Sundays.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Picking the correct schedule for your job may require some trial and error. If you run too often, you could end up starting new jobs before the old ones have finished, slowing the entire system down and causing transaction deadlocks in other parts of the system. If you run too rarely, the users are unhappy. You may have to try out different schedules to find the best balance.&lt;/p&gt;

&lt;p&gt;Finally remember to look at all your jobs as a whole: is there a risk of running into conflicts between different jobs working on the same data? Are different heavy-weight jobs running simultaneously? Do some jobs need to run before others?&lt;/p&gt;

&lt;h2&gt;
  
  
  Architectural Considerations
&lt;/h2&gt;

&lt;p&gt;Now when we have familiarised ourself with the general idea, we need to look at how it fits into the system architecture (which is assumed to be &lt;a href="https://dev.to/peholmst/domain-driven-design-and-the-hexagonal-architecture-2o87"&gt;hexagonal&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Application services and domain event handlers we already know, but where would the workers and the job go? Let's start with the worker, because it is the easiest one.&lt;/p&gt;

&lt;p&gt;A worker is a component that triggers actions in response to events generated by a timer. It can control its own transactions and threads if needed. This puts it into the &lt;em&gt;orchestrator&lt;/em&gt; category, together with e.g. domain event handlers, and thus it belongs in the application layer.&lt;/p&gt;

&lt;p&gt;But what about the job itself? The answer to that is: it depends. Read on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Single Bounded Context
&lt;/h3&gt;

&lt;p&gt;When the job is about propagating changes inside the same bounded context, the job is most likely implemented as a &lt;em&gt;domain service&lt;/em&gt;. The domain event handler, worker and application service live in the application layer and invoke the domain service as needed (and also control the transactions).&lt;/p&gt;

&lt;h3&gt;
  
  
  Multiple Bounded Contexts
&lt;/h3&gt;

&lt;p&gt;When the job is about propagating changes from one bounded context to another, we are talking about &lt;a href="https://dev.to/peholmst/strategic-domain-driven-design-3e87"&gt;context mapping&lt;/a&gt;. The implementation and location of the job depends on the integration pattern you end up choosing. Let's look at three examples (there are more solutions than that but we have to draw the line somewhere).&lt;/p&gt;

&lt;h4&gt;
  
  
  Customer-Supplier and Conformist
&lt;/h4&gt;

&lt;p&gt;In this case, there is a one-directional relationship between both contexts where the &lt;em&gt;downstream&lt;/em&gt; context wants the &lt;em&gt;upstream&lt;/em&gt; context to either perform some action (push) or return something (pull). This typically leads to the following architecture:&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;The upstream context provides an adapter that the downstream context can use to access the system. 

&lt;ul&gt;
&lt;li&gt;In a customer-supplier relationship, the upstream team is required to design this adapter according to the needs of the downstream team. &lt;/li&gt;
&lt;li&gt;In a conformist relationship, the downstream team will use whatever the upstream team chooses to put into the adapter without having any say.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;The job itself is an application service delegate. This means that it lives in the application layer, but it is not a pure application service as it does not perform any security checks at all.&lt;/li&gt;

&lt;li&gt;If the contexts are running inside the same monolithic application, the job can be triggered by domain events coming from both contexts.&lt;/li&gt;

&lt;li&gt;If the contexts are running inside separate applications, the job can only be triggered by domain events coming from the downstream context because we have no way of distributing the events. Then again, that is one of the reasons why we are using scheduled jobs instead.&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  Anticorruption Layer
&lt;/h4&gt;

&lt;p&gt;In this case, there is again a one-directional relationship between the contexts, but in this case, the downstream team has decided to completely shield the application from the upstream context:&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;The downstream context provides an adapter (the anticorruption layer) that adapts the upstream context to an API that has been declared by the downstream team.&lt;/li&gt;
&lt;li&gt;The job is still an application service delegate, but it talks to the upstream context through the API.&lt;/li&gt;
&lt;li&gt;If the anti-corruption layer includes support for propagating events from the upstream context to the downstream context, then the job can be triggered by events coming from both contexts. Otherwise, it is limited to events coming from the downstream context only.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Middleware
&lt;/h4&gt;

&lt;p&gt;A middleware solution may come in handy in cases where you have no control over any of the involved contexts, or where the relationship is bidirectional even though the contexts themselves are not aware of each others' existence:&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;The job, the workers, any domain event handlers and other components are moved out from the bounded context and into a separate &lt;em&gt;middleware&lt;/em&gt; component.&lt;/li&gt;
&lt;li&gt;The middleware is responsible for moving data back and fourth between the contexts, without the contexts even knowing about it.&lt;/li&gt;
&lt;li&gt;This works both for monoliths and for distributed systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pros and Cons
&lt;/h2&gt;

&lt;p&gt;Now it is time to wrap things up by looking at the pros and cons of using scheduled jobs to achieve eventual consistency.&lt;/p&gt;

&lt;p&gt;The main advantages with this approach are the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It works out of the box with &lt;code&gt;@TransactionalEventListener&lt;/code&gt; and all the other Spring-based building blocks and tools we have covered in this blog post series so far.&lt;/li&gt;
&lt;li&gt;You do not need to introduce any new moving parts (like a message broker) or write any infrastructure code for persisting and distributing domain events.&lt;/li&gt;
&lt;li&gt;It is quite easy to implement and its complexity can be tweaked according to the use cases.&lt;/li&gt;
&lt;li&gt;When done right it leads to a system that is resilient and robust.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, it also has several drawbacks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your system is not actually event driven. Some events are used to trigger jobs early, but the jobs themselves are data-driven.&lt;/li&gt;
&lt;li&gt;Additional state may have to be stored in the aggregates to direct the jobs (for example in order to achieve idempotence).&lt;/li&gt;
&lt;li&gt;The coupling increases as the jobs must be fully aware of all the aggregates involved.&lt;/li&gt;
&lt;li&gt;Not useful when changes need to be propagated quickly.&lt;/li&gt;
&lt;li&gt;For every job you add, the more work your database will have to do. This increases the risk of transaction deadlocks and performance problems.&lt;/li&gt;
&lt;li&gt;Scaling out or introducing redundancy need some special attention: you do not want multiple servers to start running the same job on the same data at the same time (even though idempotent jobs should make sure the data does not get corrupted).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Clearly there are systems that are suitable for this approach and I have successfully used it myself in customer projects. However, there are also lots of systems out there for which this approach would not be appropriate. In a future blogpost (or possibly blogposts) we are going to look at other ways of making sure our domain events are not missed and how we can distribute them between systems. Stay tuned!&lt;/p&gt;

</description>
      <category>domaindrivendesign</category>
      <category>ddd</category>
      <category>spring</category>
      <category>eventualconsistency</category>
    </item>
    <item>
      <title>Handling Domain Events with Spring</title>
      <dc:creator>Petter Holmström</dc:creator>
      <pubDate>Fri, 18 Jun 2021 13:05:54 +0000</pubDate>
      <link>https://dev.to/peholmst/handling-domain-events-with-spring-2bmm</link>
      <guid>https://dev.to/peholmst/handling-domain-events-with-spring-2bmm</guid>
      <description>&lt;p&gt;In my last blog post, with looked at how to &lt;a href="https://dev.to/peholmst/publishing-domain-events-with-spring-data-53m2"&gt;publish domain events using Spring Data&lt;/a&gt;. However, there is no use in publishing events unless you can also receive and handle them so that is what we are going to look at in this blog post.&lt;/p&gt;

&lt;p&gt;We recall that Spring Data publishes domain events using the standard &lt;code&gt;ApplicationEventPublisher&lt;/code&gt;. This means that we can also handle events in the standard Spring way using &lt;code&gt;@EventListener&lt;/code&gt; so let's have a look at that first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling Events with &lt;code&gt;@EventListener&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;A domain event handler (I sometimes also use the term &lt;em&gt;domain event listener&lt;/em&gt; - they mean the same thing) using &lt;code&gt;@EventListener&lt;/code&gt; looks 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;@Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyDomainEventHandler&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@EventListener&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onMyDomainEvent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MyDomainEvent&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Handler code here.&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The domain event handler is a Spring bean, which means you can inject other beans into it.&lt;/p&gt;

&lt;p&gt;Once an event is published using the &lt;code&gt;ApplicationEventPublisher&lt;/code&gt;, it will by default be handed over to the &lt;code&gt;ApplicationEventMulticaster&lt;/code&gt;. The default implementation of this - &lt;code&gt;SimpleApplicationEventMulticaster&lt;/code&gt; - will just loop through all applicable listeners and call them one at a time. Unless a task executor and an error handler have been explicitly specified, the listeners will be called inside the same thread that published the event and if any one of the listeners throws an exception, it will halt the process and the remaining listeners will not be notified at all.&lt;/p&gt;

&lt;p&gt;This means that if you use the default configuration of the event multicaster and use &lt;code&gt;@EventListener&lt;/code&gt; for your domain event handlers, they will participate in the same transaction that published the event. This also means that if you throw an exception from an event handler, you will rollback the entire transaction.&lt;/p&gt;

&lt;p&gt;In some use cases, this may be desired behaviour, in which case using &lt;code&gt;@EventListener&lt;/code&gt; is the way to go. However, this also violates the &lt;a href="https://dev.to/peholmst/tactical-domain-driven-design-17dp"&gt;third guideline of aggregate design&lt;/a&gt; which states that you should only edit one aggregate in one transaction.&lt;/p&gt;

&lt;p&gt;There is a reason for this guideline and I've been bitten by it myself when we used &lt;code&gt;@EventListener&lt;/code&gt; for our domain event handlers. The thing is, handling domain events in the same transaction that published them works fine as long as you have a small number of domain handlers that are lightweight and that &lt;em&gt;you are aware of&lt;/em&gt;. Problems start to show up when other developers attach more heavy-weight domain handlers that themselves may trigger domain events, which are handled in the same transaction, and so on. This leads to two significant problems:&lt;/p&gt;

&lt;p&gt;First, this leads to longer running transactions which may timeout or run into different locking issues, such as deadlocks or optimistic locking failures.&lt;/p&gt;

&lt;p&gt;Second, if any one of the domain event handlers in the chain fails, that domain event handler will have the power to rollback the entire transaction, essentially undoing all the events. Do you really want to give the power to change the past to a single domain event handler? After all, a domain event is published because something &lt;em&gt;has&lt;/em&gt; happened, not because something &lt;em&gt;will&lt;/em&gt; or &lt;em&gt;might&lt;/em&gt; happen.&lt;/p&gt;

&lt;p&gt;So how do we then make sure our domain event handlers run inside their own transactions?&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing &lt;code&gt;@TransactionalEventListener&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Spring has an alternative annotation for event handlers that need to be transaction aware and that is &lt;code&gt;@TransactionalEventListener&lt;/code&gt;. The annotation is used exactly the same way as &lt;code&gt;@EventListener&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

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

    &lt;span class="nd"&gt;@TransactionalEventListener&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onMyDomainEvent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MyDomainEvent&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Handler code here.&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These event listeners are not invoked directly when an event is published. Instead, they are tied to the lifecycle of the current active transaction (and because of this, they do not work if you use a reactive transaction manager).&lt;/p&gt;

&lt;p&gt;The default behaviour of a &lt;code&gt;@TransactionalEventListener&lt;/code&gt; is to execute after the current transaction has been &lt;em&gt;successfully committed&lt;/em&gt;. If the transaction is rolled back, or there is no active transaction to begin with, nothing happens.&lt;/p&gt;

&lt;p&gt;You can change this behaviour by passing different parameters to the annotation. The annotation can be configured in several ways but we will only look at two parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;phase&lt;/code&gt;: The transaction phase to bind the event to. Default is &lt;code&gt;AFTER_COMMIT&lt;/code&gt;, but other options are &lt;code&gt;BEFORE_COMMIT&lt;/code&gt;, &lt;code&gt;AFTER_ROLLBACK&lt;/code&gt; and &lt;code&gt;AFTER_COMPLETION&lt;/code&gt; (event handler is executed regardless of whether the transaction was committed or rolled back).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fallbackExecution&lt;/code&gt;: Whether the event handler should be executed even if there is no active transaction. Default is &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you use &lt;code&gt;AFTER_COMMIT&lt;/code&gt; or &lt;code&gt;AFTER_COMPLETION&lt;/code&gt;, it is very important that any transactional code that you may invoke from within the event handler &lt;em&gt;starts its own transaction&lt;/em&gt; (in other words, they should use the &lt;code&gt;REQUIRES_NEW&lt;/code&gt; transaction propagation and not &lt;code&gt;REQUIRED&lt;/code&gt;). You can read about why in &lt;a href="https://dev.to/peholmst/knee-deep-in-spring-boot-transactional-event-listeners-and-cglib-proxies-1il9"&gt;this&lt;/a&gt; blog post.&lt;/p&gt;

&lt;p&gt;So now all of our problems are solved, right? Not quite. When  our events were handled inside the same transaction, either all the changes were committed or none were. The data would always be in a consistent state after the transaction was complete. &lt;/p&gt;

&lt;p&gt;With the &lt;code&gt;@TransactionalEventListener&lt;/code&gt; this is no longer the case. What if some of the event listeners fail and others succeed? Or what if the entire system goes down after the first transaction has committed, but before any event listener gets executed? This could put our data into an inconsistent state. How do we recover from this?&lt;/p&gt;

&lt;p&gt;I'm going to leave you with a cliffhanger now, because that will be the subject of a future blogpost.&lt;/p&gt;

</description>
      <category>domaindrivendesign</category>
      <category>spring</category>
      <category>ddd</category>
    </item>
    <item>
      <title>Publishing Domain Events with Spring Data</title>
      <dc:creator>Petter Holmström</dc:creator>
      <pubDate>Sat, 29 May 2021 07:40:58 +0000</pubDate>
      <link>https://dev.to/peholmst/publishing-domain-events-with-spring-data-53m2</link>
      <guid>https://dev.to/peholmst/publishing-domain-events-with-spring-data-53m2</guid>
      <description>&lt;p&gt;In my last two posts about domain-driven design, we looked at how to &lt;a href="https://dev.to/peholmst/building-repositories-with-spring-data-1mbd"&gt;build repositories&lt;/a&gt; and how to &lt;a href="https://dev.to/peholmst/using-value-objects-as-aggregate-identifiers-with-hibernate-a2e"&gt;use value objects as aggregate IDs&lt;/a&gt;. Now we are going to have a closer look at domain events.&lt;/p&gt;

&lt;p&gt;From Spring's point of view, a domain event is just another application event that can be published using the built-in &lt;code&gt;ApplicationEventPublisher&lt;/code&gt;. In other words, we do not need to worry about building an event bus or some other infrastructure for publishing domain events: you inject the event publisher into your domain service and publish the event. However, in most cases you want to publish domain events directly from the aggregate without having to go via a domain service just for that purpose. Fortunately, we can do just that.&lt;/p&gt;

&lt;p&gt;Spring Data provides a mechanism for publishing domain events directly from within aggregates without having to get a hold of the event publisher. We already &lt;a href="https://dev.to/peholmst/building-aggregates-with-spring-data-2iig"&gt;touched on this mechanism&lt;/a&gt; when we looked at &lt;code&gt;BaseAggregateRoot&lt;/code&gt; and now we are going to take a closer look at it.&lt;/p&gt;

&lt;p&gt;Under the hood, Spring Boot will register a method interceptor for all repository methods whose names start with &lt;em&gt;save&lt;/em&gt;, such as &lt;code&gt;save&lt;/code&gt; and &lt;code&gt;saveAndFlush&lt;/code&gt;. This interceptor will look for two methods in your aggregate: one annotated with &lt;code&gt;@DomainEvents&lt;/code&gt; and another annotated with &lt;code&gt;@AfterDomainEventPublication&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The method annotated with &lt;code&gt;@DomainEvents&lt;/code&gt; is expected to return a list of events to publish. The interceptor will publish these events using the Spring application event publisher. Once the events have been published, the method annotated with &lt;code&gt;@AfterDomainEventPublication&lt;/code&gt; is invoked. This method is expected to clear the list of events, to prevent them from being published again the next time the aggregate is saved.&lt;/p&gt;

&lt;p&gt;There is a caveat to keep in mind when designing and publishing domain events in this way and it has to do with events that include a reference to the aggregate root itself, for example like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PotentiallyProblematicDomainEvent&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;MyAggregate&lt;/span&gt; &lt;span class="n"&gt;myAggregate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;PotentiallyProblematicDomainEvent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@NotNull&lt;/span&gt; &lt;span class="nc"&gt;MyAggregate&lt;/span&gt; &lt;span class="n"&gt;myAggregate&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;myAggregate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;myAggregate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;@NotNull&lt;/span&gt; &lt;span class="nc"&gt;MyAggregate&lt;/span&gt; &lt;span class="nf"&gt;getMyAggregate&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;myAggregate&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;Whenever you design events like this, you have to be aware of how Spring Data and JPA work under the hood. &lt;/p&gt;

&lt;p&gt;When you save an existing entity (and here I'm talking about the JPA entity concept, not the DDD one), Spring Data will end up calling &lt;code&gt;EntityManager.merge&lt;/code&gt;. If the entity is detached, JPA will retrieve the managed entity, copy all the attributes from the detached entity to the managed one, save it and return it. The managed entity will get its optimistic locking version incremented while the detached entity remains untouched.&lt;/p&gt;

&lt;p&gt;However, since the domain event was registered on the detached entity, the domain event listeners will get a reference to the &lt;em&gt;detached&lt;/em&gt; entity. This can lead to optimistic locking errors if a listener tries to perform any operations directly on the entity and then save it.&lt;/p&gt;

&lt;p&gt;Here are a few examples of cases where the listeners will end up getting a stale entity with an incorrect optimistic locking version:&lt;br&gt;
&lt;/p&gt;

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

    &lt;span class="nd"&gt;@Transactional&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;firstProblematicMethod&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@NotNull&lt;/span&gt; &lt;span class="nc"&gt;MyAggregate&lt;/span&gt; &lt;span class="n"&gt;aggregate&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;1&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;aggregate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;performAnOperationThatRegistersAProblematicDomainEvent&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;myAggregateRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;saveAndFlush&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;aggregate&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;secondProblematicMethod&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@NotNull&lt;/span&gt; &lt;span class="nc"&gt;MyAggregateId&lt;/span&gt; &lt;span class="n"&gt;aggregateId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;2&amp;gt;&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;aggregate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;myAggregateRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;aggregateId&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;aggregate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;performAnOperationThatRegistersAProblematicDomainEvent&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;myAggregateRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;saveAndFlush&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;aggregate&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;ol&gt;
&lt;li&gt;This method accepts an aggregate as a parameter and performs operations on it directly. This means the aggregate is detached and will become stale once saved.&lt;/li&gt;
&lt;li&gt;This method accepts the aggregate ID as a parameter and looks up the aggregate before performing operations on it. However, the method is not &lt;code&gt;@Transactional&lt;/code&gt; which means that both calls to the repository will run inside their own transactions, detaching the aggregate in between.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now how do we address this? The second method is quite easy to fix: just make the entire method &lt;code&gt;@Transactional&lt;/code&gt;. That way, the aggregate will still be managed when it is saved and the domain event listeners will get the correct instance.&lt;/p&gt;

&lt;p&gt;But what about the first method? An obvious solution would be to use the aggregate ID instead of the aggregate itself in the event. However, this has a problem of its own: if the event is registered before the aggregate has been persisted, the aggregate has no ID. If you never publish any events from unpersisted aggregates, this is not a problem. If you do, however, you can fix it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SaferDomainEvent&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;MyAggregate&lt;/span&gt; &lt;span class="n"&gt;myAggregate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;SaferDomainEvent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@NotNull&lt;/span&gt; &lt;span class="nc"&gt;MyAggregate&lt;/span&gt; &lt;span class="n"&gt;myAggregate&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;1&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;myAggregate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;myAggregate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;@NotNull&lt;/span&gt; &lt;span class="nc"&gt;MyAggregateId&lt;/span&gt; &lt;span class="nf"&gt;getMyAggregateId&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;2&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;myAggregate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getIdentifier&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;ol&gt;
&lt;li&gt;We still store a reference to the aggregate inside the event...&lt;/li&gt;
&lt;li&gt;... but we only expose its ID to the outside world, forcing any listeners to fetch a fresh copy of the aggregate from the repository if they want to do anything with it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is yet again an example of the underlying technology silently sneaking into your domain model - your choice of persistence technology can even affect the design of your domain events. Fortunately in this case it is not a big deal, but it is still something that may come back and bite you later if you base your early designs on assumptions that later turn out to be incorrect (I've been there and done that, especially when it comes to JPA). The bottomline is that you need to know your tools well - not only how to &lt;em&gt;use&lt;/em&gt; them but also how they &lt;em&gt;work&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In a future post, we are going to look at how to catch the domain events we have published and some caveats related to that.&lt;/p&gt;

</description>
      <category>domaindrivendesign</category>
      <category>spring</category>
      <category>jpa</category>
      <category>ddd</category>
    </item>
    <item>
      <title>Event Pitfalls (and How to Avoid Them)</title>
      <dc:creator>Petter Holmström</dc:creator>
      <pubDate>Tue, 18 May 2021 13:34:29 +0000</pubDate>
      <link>https://dev.to/peholmst/event-pitfalls-and-how-to-avoid-them-4d31</link>
      <guid>https://dev.to/peholmst/event-pitfalls-and-how-to-avoid-them-4d31</guid>
      <description>&lt;p&gt;During my time as a software engineer, I've dealt with different kinds of event-driven systems. Some were using events in the UI, others were using events in the backend. In both classes of systems, I've managed to shoot myself in the foot. Let's look at what happened and how it could have been avoided.&lt;/p&gt;

&lt;h1&gt;
  
  
  Using events as commands
&lt;/h1&gt;

&lt;p&gt;An event bus is a nice way of decoupling communication between components, regardless of whether this is happening in the backend or in the UI. This makes it really easy and compelling to use the event bus as a way of &lt;em&gt;telling&lt;/em&gt; other components what to do - i.e. using the events as commands.&lt;/p&gt;

&lt;p&gt;This is one of those things that may seem like a good idea at the time but may later come back and haunt you. There are multiple reasons for this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your commands typically cannot return any results to the caller. You'd have to use exceptions and return events to indicate the outcome of the command. &lt;/li&gt;
&lt;li&gt;It leads to logic that is difficult to understand and debug. Depending on how the event bus is implemented, it may not be obvious to see where the event was sent and where it ended up being handled.&lt;/li&gt;
&lt;li&gt;If the event bus itself is changed in the future, e.g. from being a synchronous bus to an asynchronous bus where each event handler runs in its own thread, you may run into some strange side effects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When building event-driven applications, think of an event as something that &lt;em&gt;has already happened&lt;/em&gt; (and name it accordingly). If the application is command-driven as well (which can be really useful in certain use cases), it should use a separate, dedicated infrastructure for routing and handling the commands.&lt;/p&gt;

&lt;h1&gt;
  
  
  Not isolating consumers from producers
&lt;/h1&gt;

&lt;p&gt;In the previous section, we concluded that an event is  something that has happened. Event consumers (or handlers, listeners, observers or whatever you want to call them) should typically not be allowed to change this.&lt;/p&gt;

&lt;p&gt;With a simple event bus implementation that just loops through all the consumers and calls them synchronously, you may end up doing exactly that. If one of the consumers ends up throwing an exception, you may end up rolling back the entire transaction and also stopping the remaining consumers from even getting the event.&lt;/p&gt;

&lt;p&gt;In some cases where you have a small number of consumers and you are in control of all of them, this may be the desired behaviour and so there is not anything inherently bad about this design. However, if the events are intended to be used by consumers outside your direct control (by other developers for instance), you may want to think twice about your design. If you want the event consumers to be able to affect the producer or other consumers in some way, this should happen explicitly through an API designed for that purpose and not by mistake because of incorrect use of an event bus.&lt;/p&gt;

&lt;p&gt;There is also another issue that you can run into by not isolating your event consumers and producers properly. If you are using some kind of security context that is bound to the current thread, the simple event bus implementation mentioned above would invoke each consumer using the producer's security context. This can lead to unintended security breaches, e.g. if the consumers have been registered by different users.&lt;/p&gt;

&lt;h1&gt;
  
  
  Assuming all event consumers will always succeed
&lt;/h1&gt;

&lt;p&gt;In the previous section, we concluded that event producers and consumers should be isolated from each other. However, this may lead to a situation where some consumers succeed in processing an event and others fail. &lt;/p&gt;

&lt;p&gt;Depending on the type of event this may or may not be a big deal. If we are talking about events that are short lived, such as a mouse move event or a GPS-position update of a portable device, we can probably live with a missed event or two as new events would render the old events obsolete anyway. &lt;/p&gt;

&lt;p&gt;However, if we are talking about one-off events, you may end up with inconsistent data in your database. For example, in an order processing system, you may have received, processed and shipped an order but failed to generate an invoice because the event consumer that was supposed to handle that failed.&lt;/p&gt;

&lt;p&gt;Addressing this problem is not really trivial and the solution would vary from system to system, but in principle it consists of three steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Realise that your system is vulnerable to this issue. If the system works most of the time, you may not even notice this until it is too late.&lt;/li&gt;
&lt;li&gt;Make sure you can easily detect when an event has been missed, either manually or automatically.&lt;/li&gt;
&lt;li&gt;Make sure you can either replay the missed event or retrigger the needed actions in some way, either manually or automatically. If you are not familiar with the concept of &lt;a href="https://dev.to/t/eventsourcing"&gt;event sourcing&lt;/a&gt;, I would recommend you to have a look at it.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Assuming all events will occur exactly once
&lt;/h1&gt;

&lt;p&gt;In the previous section, we concluded that one of the ways of dealing with failed event consumers is to replay the event at a later time until all consumers have succeeded. But what would then happen with all the consumers that did succeed on the first try? We typically don't want them to process the same event more than once.&lt;/p&gt;

&lt;p&gt;One way of doing this is to somehow keep track of which consumers have successfully handled an event and which ones have not. However, this can become complicated really fast.&lt;/p&gt;

&lt;p&gt;A better approach is to make sure all your event consumers are &lt;em&gt;idempotent&lt;/em&gt; by design. &lt;/p&gt;

&lt;p&gt;In software, an idempotent operation is an operation that can be performed multiple times without changing the state of the system. &lt;/p&gt;

&lt;p&gt;An idempotent event consumer would be a consumer that only changes the state of the system the &lt;em&gt;first&lt;/em&gt; time an event is received. If the same event is received more than once, the system state remains unchanged. If all your consumers are implemented like this, you can replay your events as many times as needed without side effects. It also makes your system more resilient if you are receiving your events from a remote message queue that cannot guarantee that all events will be delivered exactly once 100% of the time.&lt;/p&gt;

&lt;h1&gt;
  
  
  Assuming all event streams will be calm and even
&lt;/h1&gt;

&lt;p&gt;On paper, your event-driven design may look nice, clean and simple. Your initial testing on your own workstation may confirm that perception. Then you release your software to production, and things start to go wrong.&lt;/p&gt;

&lt;p&gt;It turns out some event consumers are a lot slower than others, and some event producers are producing more events than the consumers can keep up with. Also some event consumers are in turn producing events on their own, further increasing the load on the event bus.&lt;/p&gt;

&lt;p&gt;Your first attempt at fixing this is to introduce thread pools for the event consumers, but it only helps for a little while. Soon, the thread pools' queues are full and they start to reject jobs (which means you are essentially throwing away events without handling them).&lt;/p&gt;

&lt;p&gt;Event-driven systems are dynamic by their nature. However, it is very easy to only look at the static aspects when you design a software system because they are easier to grasp and reason about. Especially in multi-user systems and systems that respond to events coming from outside the system, it is important to think about event dynamics from the start:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How long will it take for a particular event consumer to process a single event?&lt;/li&gt;
&lt;li&gt;Will an event consumer emit new events? What will that lead to?&lt;/li&gt;
&lt;li&gt;What is the estimated event throughput during normal load and peaks?&lt;/li&gt;
&lt;li&gt;What is the highest event throughput your system should be able to handle and what should happen if the system can't keep up?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a &lt;a href="https://dev.to/t/backpressure"&gt;back pressure&lt;/a&gt; problem that you will run into in any system where you have a producer that is producing data faster than a consumer can process it. There is no one-stop solution to it and discussing it in more detail is way of out scope of this post. However, here are a few things to get you started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you can use a ready-made, battle tested product for solving the problem, use it.&lt;/li&gt;
&lt;li&gt;If events arrive in bursts, you can store them in a queue. Please note that this won't work if there is never time to empty the queue between bursts.&lt;/li&gt;
&lt;li&gt;If the events can be aggregated, you can store them in a queue and then have the consumer process them in groups rather than one by one.&lt;/li&gt;
&lt;li&gt;If you are in control of emitting the events in the first place, you may want to do that in sequence instead of in parallel.&lt;/li&gt;
&lt;li&gt;If your system and environment allows it, you could automatically scale out the number of event consumers as the load increases and then scale back in when it decreases (this typically requires a message broker that is able to dynamically route messages to different queues).&lt;/li&gt;
&lt;li&gt;If you can control the event producer in some way (either by asking it to slow down or stop until further notice), do it. And if you are the one implementing the event producer, consider adding this feature.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>lessonslearned</category>
      <category>eventdriven</category>
      <category>pitfalls</category>
    </item>
    <item>
      <title>Knee-deep in Spring Boot, Transactional Event Listeners and CGLIB proxies</title>
      <dc:creator>Petter Holmström</dc:creator>
      <pubDate>Fri, 07 May 2021 15:40:42 +0000</pubDate>
      <link>https://dev.to/peholmst/knee-deep-in-spring-boot-transactional-event-listeners-and-cglib-proxies-1il9</link>
      <guid>https://dev.to/peholmst/knee-deep-in-spring-boot-transactional-event-listeners-and-cglib-proxies-1il9</guid>
      <description>&lt;p&gt;A colleague and I spent two hours tracking down a strange bug in our Spring Boot application today. The cause was so interesting that I have to write about it here. Since I obviously can't write about customer projects here, I'm presenting the problem using a sample application instead. So here we go.&lt;/p&gt;

&lt;p&gt;Let's say we have a domain-driven application with two aggregates: &lt;code&gt;Order&lt;/code&gt; and &lt;code&gt;Invoice&lt;/code&gt;. We also have an orchestrator that automatically should create new invoices once an order transitions into the &lt;code&gt;SHIPPED&lt;/code&gt; state.&lt;/p&gt;

&lt;p&gt;We start with the following application service for creating new orders:&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;@Service&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;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;OrderRepository&lt;/span&gt; &lt;span class="n"&gt;orderRepository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderRepository&lt;/span&gt; &lt;span class="n"&gt;orderRepository&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orderRepository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;orderRepository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Transactional&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="nf"&gt;createOrder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;order&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;Order&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;orderRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;saveAndFlush&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Transactional&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;shipOrder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;orderId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;orderRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orderId&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;ifPresent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ship&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;orderRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;saveAndFlush&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;});&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Order.ship()&lt;/code&gt; method will change the state of the order to &lt;code&gt;SHIPPED&lt;/code&gt; and publish an &lt;code&gt;OrderStateChangedEvent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then we need another application service for creating new invoices:&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;@Service&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;InvoiceService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;InvoiceRepository&lt;/span&gt; &lt;span class="n"&gt;invoiceRepository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;InvoiceService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;InvoiceRepository&lt;/span&gt; &lt;span class="n"&gt;invoiceRepository&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;invoiceRepository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;invoiceRepository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Transactional&lt;/span&gt;
    &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="nf"&gt;createInvoiceForOrder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;invoice&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;Invoice&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;invoiceRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;saveAndFlush&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;getId&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;Finally, we need an orchestrator that creates the invoice when the order is shipped:&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;@Component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvoiceCreationOrchestrator&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;OrderRepository&lt;/span&gt; &lt;span class="n"&gt;orderRepository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;InvoiceService&lt;/span&gt; &lt;span class="n"&gt;invoiceService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;InvoiceCreationOrchestrator&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderRepository&lt;/span&gt; &lt;span class="n"&gt;orderRepository&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;InvoiceService&lt;/span&gt; &lt;span class="n"&gt;invoiceService&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orderRepository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;orderRepository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;invoiceService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;invoiceService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@TransactionalEventListener&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onOrderStateChangedEvent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderStateChangedEvent&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getNewOrderState&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderState&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SHIPPED&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;orderRepository&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOrderId&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ifPresent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;invoiceService:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;createInvoiceForOrder&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;There! Now we just run the application, create a new order, ship it and... no invoice gets created. There are no exceptions in the log either. So what went wrong?&lt;/p&gt;

&lt;p&gt;It turns out the problem is in the &lt;code&gt;@TransactionalEventListener&lt;/code&gt;. It is by default configured to run after the transaction has been committed. This is exactly what we want, but there is a caveat in how Spring actually implements this.&lt;/p&gt;

&lt;p&gt;Domain events are published using the ordinary application event publisher. Spring will actually catch them using an ordinary &lt;code&gt;@EventListener&lt;/code&gt; as well. However, instead of invoking the transactional event listener directly, Spring will register a &lt;code&gt;TransactionSynchronization&lt;/code&gt; with the &lt;code&gt;TransactionSynchronizationManager&lt;/code&gt;. This will invoke the transactional event listener after the transaction has successfully committed, but before the transaction synchronization manager has cleaned itself up.&lt;/p&gt;

&lt;p&gt;Now, our event listener is invoking the &lt;code&gt;createInvoiceForOrder&lt;/code&gt; method, which has the &lt;code&gt;@Transactional&lt;/code&gt; annotation. The default propagation for &lt;code&gt;@Transactional&lt;/code&gt; is &lt;code&gt;REQUIRED&lt;/code&gt;. This means that if there already is an active transaction, the method should participate in it; otherwise it should create its own transaction. &lt;/p&gt;

&lt;p&gt;Because this method is being invoked inside a &lt;code&gt;TransactionSynchronization&lt;/code&gt;, there actually is an "active" transaction but it has already been committed. Thus, the call to &lt;code&gt;saveAndFlush&lt;/code&gt; will result in a &lt;code&gt;TransactionRequiredException&lt;/code&gt;. This exception is swallowed by &lt;code&gt;TransactionSynchronizationUtils&lt;/code&gt; (another Spring class) and logged using the DEBUG level. Thus, the only way to detect this exception is by having DEBUG logging turned on for the &lt;code&gt;org.springframework.transaction.support&lt;/code&gt; package.&lt;/p&gt;

&lt;p&gt;The solution to this problem is to make sure that the &lt;code&gt;InvoiceService&lt;/code&gt; always runs inside its own transaction. So we change the method 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;@Service&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;InvoiceService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Transactional&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;propagation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;REQUIRES_NEW&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="nf"&gt;createInvoiceForOrder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Rest of the method omitted&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;It is anyway a good practice to configure all your application services to &lt;em&gt;always&lt;/em&gt; use &lt;code&gt;REQUIRES_NEW&lt;/code&gt; since they are responsible for &lt;a href="https://dev.to/peholmst/domain-driven-design-and-the-hexagonal-architecture-2o87"&gt;controlling the transactions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now we run the application again and... it still does not work. The application behaves exactly the same. What's wrong now?&lt;/p&gt;

&lt;p&gt;It turns out that &lt;code&gt;createInvoiceForOrder&lt;/code&gt; is not actually running inside a transaction at all. The transaction is started and committed by the call to &lt;code&gt;saveAndFlush()&lt;/code&gt; in the repository, and that method still uses &lt;code&gt;REQUIRED&lt;/code&gt; transaction propagation. How come?&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;InvoiceService&lt;/code&gt; is not implementing any interfaces, so Spring is using a CGLIB proxy to add the transaction interceptors. However, the method &lt;code&gt;createInvoiceForOrder&lt;/code&gt; happens to have package visibility and the transaction interceptor is only applied to public methods. So we need to change the method to be public:&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;@Service&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;InvoiceService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Transactional&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;propagation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;REQUIRES_NEW&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;Long&lt;/span&gt; &lt;span class="nf"&gt;createInvoiceForOrder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Rest of the method omitted&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we run the application once more and it finally works!&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>lessonslearned</category>
      <category>developerstories</category>
      <category>java</category>
    </item>
    <item>
      <title>Java Pitfalls (and How to Avoid Them)</title>
      <dc:creator>Petter Holmström</dc:creator>
      <pubDate>Thu, 29 Apr 2021 14:16:35 +0000</pubDate>
      <link>https://dev.to/peholmst/stories-from-the-trenches-java-pitfalls-3a6i</link>
      <guid>https://dev.to/peholmst/stories-from-the-trenches-java-pitfalls-3a6i</guid>
      <description>&lt;p&gt;I've been coding in Java since 2004, professionally since 2009. During these years I've come across several pitfalls that could have easily been avoided upfront - if you had thought of them. In this post, I'm going to list some of them (or more specifically, how to avoid them), in no particular order.&lt;/p&gt;

&lt;h1&gt;
  
  
  Validate and Sanitise Your Input Data
&lt;/h1&gt;

&lt;p&gt;Input data can be coming from your users, another component within the system or from another system. This means that data validation and sanitation must be done on multiple levels.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Difference Between Validation and Sanitation
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Validation&lt;/em&gt; means that you check that your input data is correct. The result of this operation is essentially a boolean: either the input data is correct, or it is not.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sanitation&lt;/em&gt; means that you take the input data and transform it until it becomes valid. The result of this operation is either valid input data or an exception. Let's take a simple example: phone numbers. People write phone numbers in very different ways, using all kinds of separation characters and groupings. However, writing a function that will remove all other characters except the &lt;code&gt;+&lt;/code&gt; sign and the numbers &lt;code&gt;0-9&lt;/code&gt; from a string is very easy. In addition, it lets the users enter phone numbers in their preferred format and guarantees that the numbers are stored in a consistent format in your system.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Validate
&lt;/h2&gt;

&lt;p&gt;What you should validate depends on the use case and the specifications but here is a list to get you started (it is by no means exhaustive):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Empty values and &lt;code&gt;null&lt;/code&gt;s &lt;/li&gt;
&lt;li&gt;String max lengths (for example: JPA defaults to 255 characters for string fields)&lt;/li&gt;
&lt;li&gt;Allowed and forbidden characters and patterns (such as e-mail addresses, phone numbers, postal codes and filenames)&lt;/li&gt;
&lt;li&gt;Checksums (such as social security numbers and bank account numbers)&lt;/li&gt;
&lt;li&gt;Numerical limits (such as maximum value, minimum value and number of decimals)&lt;/li&gt;
&lt;li&gt;The decimal point character (are you using &lt;code&gt;.&lt;/code&gt; or &lt;code&gt;,&lt;/code&gt; or both?)&lt;/li&gt;
&lt;li&gt;Script injection attacks (such as JavaScript and SQL)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When and Where to Validate
&lt;/h2&gt;

&lt;p&gt;Data should be sanitised and validated whenever and wherever it enters the system. Bad data should be stopped at the gates. Doing validation and sanitation in the user interface is great for improving the user experience, but it should not be the only place where this is done. The real validation and sanitation must always be done in the backend. &lt;/p&gt;

&lt;h2&gt;
  
  
  Dealing With Bad Legacy Data
&lt;/h2&gt;

&lt;p&gt;Unfortunately it is not always possible to stop bad data at the gates. If you are dealing with a legacy system, the data may already be inside. A typical example could be a date column that used to be a &lt;code&gt;varchar&lt;/code&gt; (yes, that happens) and now needs to be changed into a &lt;code&gt;date&lt;/code&gt;, or an e-mail column that did not use any kind of validation at all and now contains all kinds of garbage.&lt;/p&gt;

&lt;p&gt;You can deal with this in several ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fix the bad data while you migrate it from the old database to the new one&lt;/li&gt;
&lt;li&gt;Use double columns, one for bad values that could not be automatically migrated and another for correct values&lt;/li&gt;
&lt;li&gt;Use a custom value object that can distinguish between bad data and good data (read more about it &lt;a href="https://dev.to/peholmst/using-value-objects-with-jpa-27mi"&gt;here&lt;/a&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In any case you should never let bad legacy data be an excuse not to properly validate and sanitise new data!&lt;/p&gt;

&lt;h1&gt;
  
  
  Design By Contract
&lt;/h1&gt;

&lt;p&gt;I would guess most programmers that have received some kind of formal training are familiar with the &lt;em&gt;design by contract&lt;/em&gt; principle. Let's recap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Preconditions&lt;/em&gt; state what must be true in order for the operation to succeed&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Postconditions&lt;/em&gt; state what will be true once the operation has finished successfully&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Invariants&lt;/em&gt; state what conditions remain unchanged before and after the operation has been performed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You should clearly define and document contracts for &lt;em&gt;all&lt;/em&gt; your public APIs. This does not mean only the methods you write but also the input and output data (such as DTOs) and any exceptions. You can use JavaDocs and ordinary language for this; there is no need to go formal unless you want to.&lt;/p&gt;

&lt;p&gt;A fellow developer (or yourself in six months) should never need to make assumptions of how to use your method or how to interpret its result. For example: I don't know how many times I've had to dig into the source code (sometimes quite deep) just to figure out whether certain output values can be &lt;code&gt;null&lt;/code&gt; or not. Which brings me to the next pitfall...&lt;/p&gt;

&lt;h1&gt;
  
  
  NPEs Can Be Avoided, So Avoid Them!
&lt;/h1&gt;

&lt;p&gt;We have all run into those pesky &lt;code&gt;NullPointerException&lt;/code&gt;s in production and that is embarrassing. We really should not do that. New programming languages such as Kotlin are doing a great job in combatting them, but even in vanilla Java there are a few simple things you can do to greatly reduce the number of NPEs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validate never-&lt;code&gt;null&lt;/code&gt; parameters using &lt;code&gt;Objects.requireNonNull()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;Optional&lt;/code&gt;s for return values that can be empty or &lt;code&gt;null&lt;/code&gt; (and never use them for values that are never empty nor &lt;code&gt;null&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Never assume an &lt;code&gt;Optional&lt;/code&gt; will always contain a value (it wouldn't be an &lt;code&gt;Optional&lt;/code&gt; if it could not also be empty in some cases)&lt;/li&gt;
&lt;li&gt;Document your code carefully and &lt;em&gt;read&lt;/em&gt; the documentation that others (or yourself six months ago) wrote&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;@NotNull&lt;/code&gt; and &lt;code&gt;@Nullable&lt;/code&gt; annotations if your IDE supports them - your IDE may be able to warn you about potential NPEs even before you compile your code&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  If Possible: Reuse by Composition, Not by Inheritance
&lt;/h1&gt;

&lt;p&gt;We programmers are lazy. If we can write something only once and reuse later, we very much try to do it (otherwise we copy-paste it). Especially in my earlier programming days my go-to method for doing this was through inheritance. Now I know better.&lt;/p&gt;

&lt;p&gt;When I was a child, I loved to play with LEGOs. My cousin had a Playmobile castle and I loved to play with it as well. I could build all kinds of castles with it - but only castles. With my LEGOs I could build whatever I wanted to: castles, fire engines, space ships, boats, and so on. &lt;/p&gt;

&lt;p&gt;In the software world, Playmobile would be reuse by inheritance and LEGO reuse by composition.&lt;/p&gt;

&lt;p&gt;Reusing code by inheritance assumes that &lt;em&gt;all&lt;/em&gt; future use cases will fit into a specific mold. In my experience this is rarely the case and if you find yourself making changes to your base class in order to support a requirement in a subclass, you are in trouble. If this happens, you probably did not have the correct level of abstraction in your base class (google the &lt;em&gt;Single Level of Abstraction&lt;/em&gt; principle for more details).&lt;/p&gt;

&lt;p&gt;If you instead go for reuse by composition, you build reusable building blocks that can be combined and used as needed. This is often a far more extendable and future proof approach than inheritance and still allows you to reuse code and not repeat yourself.&lt;/p&gt;

&lt;p&gt;Getting the reuse approach right is especially important if you are building a platform or a framework. And if you are doing that, you should ask yourself if you actually need to do that or if you are accidentally over-engineering (been there, done that).&lt;/p&gt;

</description>
      <category>lessonslearned</category>
      <category>java</category>
      <category>pitfalls</category>
    </item>
    <item>
      <title>Using Value Objects as Aggregate Identifiers with Hibernate</title>
      <dc:creator>Petter Holmström</dc:creator>
      <pubDate>Wed, 28 Apr 2021 05:33:21 +0000</pubDate>
      <link>https://dev.to/peholmst/using-value-objects-as-aggregate-identifiers-with-hibernate-a2e</link>
      <guid>https://dev.to/peholmst/using-value-objects-as-aggregate-identifiers-with-hibernate-a2e</guid>
      <description>&lt;p&gt;In &lt;a href="https://dev.to/peholmst/tactical-domain-driven-design-17dp"&gt;Tactical Domain-Driven Design&lt;/a&gt;, we learned that that we should refer to other aggregates by ID and use value objects to distinguish between different aggregate types (second aggregate design guideline).&lt;/p&gt;

&lt;p&gt;This is perfectly possible to do with JPA and &lt;a href="http://hibernate.org/" rel="noopener noreferrer"&gt;Hibernate&lt;/a&gt;, but requires some additional work as it goes against the design principles of JPA where you should not have to care about the IDs at all and just work with your entity objects directly. Let's have a look at how. We will be building on the code and principles laid out in my posts about &lt;a href="https://dev.to/peholmst/using-value-objects-with-jpa-27mi"&gt;value objects&lt;/a&gt; and &lt;a href="https://dev.to/peholmst/building-aggregates-with-spring-data-2iig"&gt;aggregates&lt;/a&gt; so please read those first if you haven't already.&lt;/p&gt;

&lt;p&gt;If you are using another JPA implementation than Hibernate, you have to check that implementation's documentation for how to create custom types.&lt;/p&gt;

&lt;h1&gt;
  
  
  Attribute Converters Won't Do
&lt;/h1&gt;

&lt;p&gt;The first thought may be to use a simple value object and an attribute converter. Unfortunately this is not possible as JPA does not support using attribute converters for &lt;code&gt;@Id&lt;/code&gt; fields. You can make a compromise and use "raw" IDs for your &lt;code&gt;@Id&lt;/code&gt; fields and simple value objects to refer to them from other aggregates, but I do not personally like this approach as you have to move back and forth between the value objects and their wrapped raw IDs, making it more difficult to write queries. A better, more consistent approach is to create custom Hibernate types.&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating a Custom Hibernate Type
&lt;/h1&gt;

&lt;p&gt;When you create custom Hibernate types for your ID value objects, they become available for use inside your entire persistence context without any additional annotations anywhere. This involves the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Decide what kind of raw ID type you are going to use inside your value object: &lt;code&gt;UUID&lt;/code&gt;, &lt;code&gt;String&lt;/code&gt;, or &lt;code&gt;Long&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create a type descriptor for your value object. This descriptor knows how to convert another value into an instance of your value object (wrap) and vice versa (unwrap).&lt;/li&gt;
&lt;li&gt;Create a custom type that ties together your type descriptor with the JDBC column type you want to use for your ID.&lt;/li&gt;
&lt;li&gt;Register your custom type with Hibernate.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's have a look at a code example to better illustrate this. We are going to create a value object ID called &lt;code&gt;CustomerId&lt;/code&gt; that wraps a &lt;code&gt;UUID&lt;/code&gt;. The value object looks 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="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;foo.bar.domain.model&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Imports omitted&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;CustomerId&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;ValueObject&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Serializable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;1&amp;gt;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="no"&gt;UUID&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;CustomerId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@NotNull&lt;/span&gt; &lt;span class="no"&gt;UUID&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;uuid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;@NotNull&lt;/span&gt; &lt;span class="no"&gt;UUID&lt;/span&gt; &lt;span class="nf"&gt;unwrap&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;2&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Implementation of equals() and hashCode() omitted.&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;You have to implement the &lt;code&gt;Serializable&lt;/code&gt; interface because &lt;code&gt;Persistable&lt;/code&gt; assumes the ID type is persistable. I sometimes create a new marker interface called &lt;code&gt;DomainObjectId&lt;/code&gt; that extends &lt;code&gt;ValueObject&lt;/code&gt; and &lt;code&gt;Serializable&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You need a way of getting the underlying &lt;code&gt;UUID&lt;/code&gt; when you implement the type descriptor.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Next, we will create the type descriptor. I typically place this in a subpackage called &lt;code&gt;.hibernate&lt;/code&gt; to keep the domain model itself nice and clean.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;foo.bar.domain.model.hibernate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Imports omitted&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;CustomerIdTypeDescriptor&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AbstractTypeDescriptor&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CustomerId&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;1&amp;gt;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;CustomerIdTypeDescriptor&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CustomerId&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CustomerId&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;2&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;UUIDTypeDescriptor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToStringTransformer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INSTANCE&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;unwrap&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt; 
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="no"&gt;ID&lt;/span&gt; &lt;span class="nf"&gt;fromString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;3&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;CustomerId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UUIDTypeDescriptor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToStringTransformer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INSTANCE&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt; 
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="nd"&gt;@SuppressWarnings&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"unchecked"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;X&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;X&lt;/span&gt; &lt;span class="nf"&gt;unwrap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CustomerId&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;X&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;WrapperOptions&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;4&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&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="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;getJavaType&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;isAssignableFrom&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&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="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;X&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isAssignableFrom&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&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="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;X&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;UUIDTypeDescriptor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;PassThroughTransformer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INSTANCE&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;unwrap&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isAssignableFrom&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&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="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;X&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;UUIDTypeDescriptor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToStringTransformer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INSTANCE&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;unwrap&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[].&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isAssignableFrom&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&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="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;X&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;UUIDTypeDescriptor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToBytesTransformer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INSTANCE&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;unwrap&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nf"&gt;unknownUnwrap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;X&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;CustomerId&lt;/span&gt; &lt;span class="nf"&gt;wrap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;X&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;WrapperOptions&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;5&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&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="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;getJavaType&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;isInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;getJavaType&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;cast&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="no"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;CustomerId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UUIDTypeDescriptor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;PassThroughTransformer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INSTANCE&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;CustomerId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UUIDTypeDescriptor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToStringTransformer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INSTANCE&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;CustomerId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UUIDTypeDescriptor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ToBytesTransformer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INSTANCE&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nf"&gt;unknownWrap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getClass&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;CustomerIdTypeDescriptor&lt;/span&gt; &lt;span class="no"&gt;INSTANCE&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;CustomerIdTypeDescriptor&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;6&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;AbstractTypeDescriptor&lt;/code&gt; is a Hibernate base class that resides in the &lt;code&gt;org.hibernate.type.descriptor.java&lt;/code&gt; package.&lt;/li&gt;
&lt;li&gt;This method converts our value object to a string. We use a helper class from Hibernate's built-in &lt;code&gt;UUIDTypeDescriptor&lt;/code&gt; (also from the &lt;code&gt;org.hibernate.type.descriptor.java&lt;/code&gt; package) to perform the conversion.&lt;/li&gt;
&lt;li&gt;This method constructs a value object from a string. Again, we use a helper class from &lt;code&gt;UUIDTypeDescriptor&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;This method converts a value object into a &lt;code&gt;UUID&lt;/code&gt;, a string or a byte array. Again, we use helper classes from &lt;code&gt;UUIDTypeDescriptor&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;This method converts a &lt;code&gt;UUID&lt;/code&gt;, a string or a byte array into a value object. The helper classes are used here as well.&lt;/li&gt;
&lt;li&gt;We can access this type descriptor as a singleton since it does not contain any changeable state.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So far we have only dealt with Java types. Now it is time to bring SQL and JDBC into the mix and create our custom type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;foo.bar.domain.model.hibernate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Imports omitted&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;CustomerIdType&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AbstractSingleColumnStandardBasicType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CustomerId&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;1&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;ResultSetIdentifierConsumer&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;2&amp;gt;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;CustomerIdType&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BinaryTypeDescriptor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INSTANCE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;CustomerIdTypeDescriptor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INSTANCE&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;3&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Serializable&lt;/span&gt; &lt;span class="nf"&gt;consumeIdentifier&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ResultSet&lt;/span&gt; &lt;span class="n"&gt;resultSet&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resultSet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBytes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;4&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;getJavaTypeDescriptor&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;wrap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;5&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SQLException&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;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalStateException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Could not extract ID from ResultSet"&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="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;getJavaTypeDescriptor&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getJavaType&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getSimpleName&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;6&amp;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;ol&gt;
&lt;li&gt;
&lt;code&gt;AbstractSingleColumnStandardBasicType&lt;/code&gt; is a Hibernate base class that resides in the &lt;code&gt;org.hibernate.type&lt;/code&gt; package.&lt;/li&gt;
&lt;li&gt;In order for the custom type to work properly in &lt;code&gt;@Id&lt;/code&gt; fields, we have to implement this extra interface from the &lt;code&gt;org.hibernate.id&lt;/code&gt; package.&lt;/li&gt;
&lt;li&gt;Here we pass in the SQL type descriptor (in this case binary as we are going to store the UUID in a 16 byte binary column) and our Java type descriptor.&lt;/li&gt;
&lt;li&gt;Here, we retrieve the ID from a JDBC result set as a byte array...&lt;/li&gt;
&lt;li&gt;... and convert it to a &lt;code&gt;CustomerId&lt;/code&gt; using our Java type descriptor.&lt;/li&gt;
&lt;li&gt;A custom type needs a name so we use the name of the Java Type.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Finally, we just have to register our new type with Hibernate. We will do this inside a &lt;code&gt;package-info.java&lt;/code&gt; file that resides in the same package as our &lt;code&gt;CustomerId&lt;/code&gt; class:&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;@TypeDef&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;defaultForType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CustomerId&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;typeClass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CustomerIdType&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="c1"&gt;// &amp;lt;1&amp;gt;&lt;/span&gt;
&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;foo.bar.domain.model&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.hibernate.annotations.TypeDef&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;2&amp;gt;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;foo.bar.domain.model.hibernate.CustomerIdType&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;This Hibernate annotation tells Hibernate to use &lt;code&gt;CustomerIdType&lt;/code&gt; whenever it encounters a &lt;code&gt;CustomerId&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Note that the imports are coming after the annotations in a &lt;code&gt;package-info.java&lt;/code&gt; file and not before as they do in a class file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Phew! Now we can use &lt;code&gt;CustomerId&lt;/code&gt; both to identify &lt;code&gt;Customer&lt;/code&gt; aggregates and to refer to them from other aggregates. Please keep in mind, though, that if you let Hibernate generate your SQL schema for you and you use IDs to refer to aggregates instead of &lt;code&gt;@ManyToOne&lt;/code&gt; associations, Hibernate will not create foreign key constraints. You will have to do that yourself, for example using &lt;a href="https://flywaydb.org/" rel="noopener noreferrer"&gt;Flyway&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you have many different ID value object types, you will want to create abstract base classes for your type descriptors and custom types to avoid having to repeat yourself. I'm going to leave this as an exercise to the reader.&lt;/p&gt;

&lt;p&gt;But wait, haven't we forgotten something? How are we actually going to generate new &lt;code&gt;CustomerID&lt;/code&gt; instances when we persist newly created &lt;code&gt;Customer&lt;/code&gt; aggregate roots? Let's find out.&lt;/p&gt;

&lt;h1&gt;
  
  
  Generating Value Object IDs
&lt;/h1&gt;

&lt;p&gt;Once you have your ID value objects and custom types in place, you need a way of generating new IDs. You can create your IDs and assign them manually before persisting your entities (this is really easy if you use UUIDs) or you can configure Hibernate to automatically generate IDs for you when they are needed. The latter approach is more difficult to set up but easier to work with once it is done so let's have a look at that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Refactoring Your Base Classes
&lt;/h2&gt;

&lt;p&gt;JPA has support for different ID generators. If you look at the &lt;code&gt;@GeneratedValue&lt;/code&gt; annotation, you can specify the name of the &lt;code&gt;generator&lt;/code&gt; to use. Here we run into the first caveat. If you declare your ID field inside a mapped superclass (such as &lt;code&gt;AbstractPersistable&lt;/code&gt;), there is no way for you to override the &lt;code&gt;@GeneratedValue&lt;/code&gt; annotation for that field. In other words, you are stuck using the same ID generator for all of your aggregate roots and entities that extend this base class. If you find yourself in a situation like this, you have to remove your ID field from the base class and have every aggregate root and entity declare its own ID field. &lt;/p&gt;

&lt;p&gt;Thus, the &lt;code&gt;BaseEntity&lt;/code&gt; class (we originally defined this class &lt;a href="https://dev.to/peholmst/building-aggregates-with-spring-data-2iig"&gt;here&lt;/a&gt;) changes to 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;@MappedSuperclass&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Id&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Serializable&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Persistable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;1&amp;gt;&lt;/span&gt;

    &lt;span class="nd"&gt;@Version&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="nd"&gt;@Transient&lt;/span&gt; 
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="nd"&gt;@Nullable&lt;/span&gt; &lt;span class="no"&gt;ID&lt;/span&gt; &lt;span class="nf"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;2&amp;gt;&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="nd"&gt;@Transient&lt;/span&gt; 
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;isNew&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;3&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;@NotNull&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getVersion&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;Optional&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setVersion&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Nullable&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;4&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s{id=%s}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;getClass&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getSimpleName&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;5&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;obj&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="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;obj&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="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;getClass&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ProxyUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUserClass&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;)))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;6&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BaseEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&amp;gt;)&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;that&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;hashCode&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;7&amp;gt;&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hashCode&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hashCode&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;ol&gt;
&lt;li&gt;We no longer extend &lt;code&gt;AbstractPersistable&lt;/code&gt; but we do implement the &lt;code&gt;Persistable&lt;/code&gt; interface.&lt;/li&gt;
&lt;li&gt;This method comes from the &lt;code&gt;Persistable&lt;/code&gt; interface and will have to be implemented by the subclasses.&lt;/li&gt;
&lt;li&gt;This method also comes from the &lt;code&gt;Persistable&lt;/code&gt; interface.&lt;/li&gt;
&lt;li&gt;Since we no longer extend &lt;code&gt;AbstractPersistable&lt;/code&gt; we have to override &lt;code&gt;toString&lt;/code&gt; ourselves to return something useful. I sometimes also include the object identity hash code to make it clear whether we are dealing with different instances of the same entity.&lt;/li&gt;
&lt;li&gt;We also have to override &lt;code&gt;equals&lt;/code&gt;. Remember that two entities of the same type with the same ID are considered the same entity.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ProxyUtils&lt;/code&gt; is a Spring utility class that is useful for cases where the JPA implementation has made bytecode changes to the entity class, resulting in &lt;code&gt;getClass()&lt;/code&gt; not necessarily returning what you think it may return.&lt;/li&gt;
&lt;li&gt;Since we have overridden &lt;code&gt;equals&lt;/code&gt;, we also have to override &lt;code&gt;hashCode&lt;/code&gt; in the same manner.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now when we have made the necessary changes to &lt;code&gt;BaseEntity&lt;/code&gt;, we can add the ID field to our aggregate root:&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;@Entity&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;Customer&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseAggregateRoot&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CustomerId&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;1&amp;gt;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;ID_GENERATOR_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"customer-id-generator"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;2&amp;gt;&lt;/span&gt;

    &lt;span class="nd"&gt;@Id&lt;/span&gt;
    &lt;span class="nd"&gt;@GeneratedValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ID_GENERATOR_NAME&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;3&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;CustomerId&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;@Nullable&lt;/span&gt; &lt;span class="nc"&gt;CustomerId&lt;/span&gt; &lt;span class="nf"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;4&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;id&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;ol&gt;
&lt;li&gt;We extend &lt;code&gt;BaseAggregateRoot&lt;/code&gt;, which in turn extends our refactored &lt;code&gt;BaseEntity&lt;/code&gt; class.&lt;/li&gt;
&lt;li&gt;We declare the name of the ID generator in a constant. We will be using this when we register our custom generator with Hibernate.&lt;/li&gt;
&lt;li&gt;Now we are no longer stuck with whatever annotation was used in the mapped superclass.&lt;/li&gt;
&lt;li&gt;We implement the abstract &lt;code&gt;getId()&lt;/code&gt; method from &lt;code&gt;Persistable&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Implementing the ID Generator
&lt;/h2&gt;

&lt;p&gt;Next, we have to implement our custom ID generator. Since we are using UUIDs this is going to be almost trivial. For other ID generation strategies, I suggest you pick an existing Hibernate generator and build on that (start looking &lt;a href="https://github.com/hibernate/hibernate-orm/tree/main/hibernate-core/src/main/java/org/hibernate/id" rel="noopener noreferrer"&gt;here&lt;/a&gt;). The ID generator will look 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="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;foo.bar.domain.model.hibernate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomerIdGenerator&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;IdentifierGenerator&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;1&amp;gt;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;STRATEGY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"foo.bar.domain.model.hibernate.CustomerIdGenerator"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;2&amp;gt;&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Serializable&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SharedSessionContractImplementor&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;HibernateException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;CustomerId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;randomUUID&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;3&amp;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;ol&gt;
&lt;li&gt;
&lt;code&gt;IdentifierGenerator&lt;/code&gt; is an interface that resides in the &lt;code&gt;org.hibernate.id&lt;/code&gt; package.&lt;/li&gt;
&lt;li&gt;Because of how new generators are registered with Hibernate, we need the full name of the class as a string. We store it in a constant to make future refactoring easier - and minimize the risk of bugs caused by typos.&lt;/li&gt;
&lt;li&gt;In this example we use &lt;code&gt;UUID.randomUUID()&lt;/code&gt; to create new UUIDs. Please note that you have access to the Hibernate session if you need to do something more advanced, like retrieving a numeric value from a database sequence.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Finally, we have to register our new ID generator with Hibernate. Like with the custom type, this happens in &lt;code&gt;package-info.java&lt;/code&gt;, which becomes:&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;@TypeDef&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;defaultForType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CustomerId&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;typeClass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CustomerIdType&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="nd"&gt;@GenericGenerator&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Customer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ID_GENERATOR_NAME&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CustomerIdGenerator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;STRATEGY&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;1&amp;gt;&lt;/span&gt;
&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;foo.bar.domain.model&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.hibernate.annotations.GenericGenerator&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.hibernate.annotations.TypeDef&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;foo.bar.domain.model.hibernate.CustomerIdType&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;foo.bar.domain.model.hibernate.CustomerIdGenerator&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;This annotation tells Hibernate to use &lt;code&gt;CustomerIdGenerator&lt;/code&gt; whenever it encounters a generator named &lt;code&gt;customer-id-generator&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Double-phew! Now our domain model should just work as we expect it to, with auto-generated value objects as IDs. &lt;/p&gt;

&lt;h1&gt;
  
  
  A Note on Composite Keys
&lt;/h1&gt;

&lt;p&gt;Before we leave the subject of IDs, I just want to mention one thing. By moving the ID field from the mapped superclass (&lt;code&gt;BaseEntity&lt;/code&gt;) to the concrete entity class (&lt;code&gt;Customer&lt;/code&gt; in the example above), we also opened up the possibility to use composite keys in our entities (either using &lt;code&gt;@EmbeddedId&lt;/code&gt; or &lt;code&gt;@IdClass&lt;/code&gt;). You may for example have a situation where the composite key consists of the ID of another aggregate root and an enum constant.&lt;/p&gt;

</description>
      <category>domaindrivendesign</category>
      <category>jpa</category>
      <category>hibernate</category>
      <category>ddd</category>
    </item>
    <item>
      <title>Building Repositories with Spring Data</title>
      <dc:creator>Petter Holmström</dc:creator>
      <pubDate>Tue, 27 Apr 2021 06:38:00 +0000</pubDate>
      <link>https://dev.to/peholmst/building-repositories-with-spring-data-1mbd</link>
      <guid>https://dev.to/peholmst/building-repositories-with-spring-data-1mbd</guid>
      <description>&lt;p&gt;Yesterday, we learned &lt;a href="https://dev.to/peholmst/building-aggregates-with-spring-data-2iig"&gt;how to build aggregates&lt;/a&gt; with &lt;a href="https://spring.io/projects/spring-data" rel="noopener noreferrer"&gt;Spring Data&lt;/a&gt;. Now when we have our aggregates in place, we need to build repositories for storing and retrieving them. &lt;/p&gt;

&lt;p&gt;Building repositories with Spring Data is very easy. All you need to do is declare your repository interface and have it extend the Spring Data interface &lt;code&gt;JpaRepository&lt;/code&gt;. However, this also makes it easy to accidentally create repositories for local entities (which may happen if you have developers unfamiliar with DDD but familiar with JPA). Therefore, I always declare my own base repository interface like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@NoRepositoryBean&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;1&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;BaseRepository&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Aggregate&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseAggregateRoot&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="no"&gt;ID&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Serializable&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;2&amp;gt;&lt;/span&gt;
        &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;JpaRepository&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Aggregate&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// &amp;lt;3&amp;gt;&lt;/span&gt;
                &lt;span class="nc"&gt;JpaSpecificationExecutor&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Aggregate&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;4&amp;gt;&lt;/span&gt;

    &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nd"&gt;@NotNull&lt;/span&gt; &lt;span class="nc"&gt;Aggregate&lt;/span&gt; &lt;span class="nf"&gt;getById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@NotNull&lt;/span&gt; &lt;span class="no"&gt;ID&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;5&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;findById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;orElseThrow&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EmptyResultDataAccessException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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;ol&gt;
&lt;li&gt;This annotation tells Spring Data not to try to instantiate this interface directly.&lt;/li&gt;
&lt;li&gt;We limit the entities served by the repository to aggregate roots only.&lt;/li&gt;
&lt;li&gt;We extend &lt;code&gt;JpaRepository&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;I personally prefer specifications to query methods. We'll return to why in a little bit.&lt;/li&gt;
&lt;li&gt;The built in &lt;code&gt;findById&lt;/code&gt; method returns an &lt;code&gt;Optional&lt;/code&gt;. In many cases when you fetch an aggregate by its ID you assume it will exist. Having to deal with the &lt;code&gt;Optional&lt;/code&gt; every single time is a waste of time and code so you might as well do that in the repository directly.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With this base interface in place, the repository for a &lt;code&gt;Customer&lt;/code&gt; aggregate root could look 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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;CustomerRepository&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseRepository&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Customer&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;CustomerId&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// No need for additional methods&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is all you need for retrieving and saving aggregates. Now let us have a look at how to implement queries.&lt;/p&gt;

&lt;h1&gt;
  
  
  Query Methods and Specifications
&lt;/h1&gt;

&lt;p&gt;The most straightforward way to create queries in Spring Data is by defining carefully named &lt;code&gt;findBy&lt;/code&gt;-methods (if you are not familiar with this then check the &lt;a href="https://docs.spring.io/spring-data/jpa/docs/2.5.0/reference/html/#reference" rel="noopener noreferrer"&gt;Spring Data reference documentation&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;I find these useful for simple queries that look for aggregates based on one or two keys only; for example, in a &lt;code&gt;PersonRepository&lt;/code&gt; you could have a method called &lt;code&gt;findBySocialSecurityNumber&lt;/code&gt; and in a &lt;code&gt;CustomerRepository&lt;/code&gt; you could have a method called &lt;code&gt;findByCustomerNumber&lt;/code&gt;. However, for more advanced or complex queries I try to avoid using &lt;code&gt;findBy&lt;/code&gt;-methods. &lt;/p&gt;

&lt;p&gt;I do this mainly for two reasons: First, the method names tend to become very long and pollute the code wherever they are used. &lt;/p&gt;

&lt;p&gt;Second, very specific needs from application services may sneak into the repository and after a while your repositories are full of query methods that do almost the same thing but with small variations. I want to keep my domain model as clean as possible. Instead, I like to construct my queries using &lt;em&gt;specifications&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;When you query by specification, you start by building a specification object that describes the result you want from your query. Specification objects can also be combined using the logical operators &lt;em&gt;and&lt;/em&gt; and &lt;em&gt;or&lt;/em&gt;. For maximum flexibility, I try to keep my specifications as small as possible. If needed, I create composite specifications for commonly used specification combinations.&lt;/p&gt;

&lt;p&gt;Spring Data has built in support for specifications. To create a specification, you have to implement the &lt;code&gt;Specification&lt;/code&gt; interface. This interface relies on the JPA Criteria API so you need to familiarize yourself with that if you have not used it before (&lt;a href="https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#criteria" rel="noopener noreferrer"&gt;here&lt;/a&gt; is Hibernate's documentation about it).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Specification&lt;/code&gt; interface contains a single method that you have to implement. It produces a JPA Criteria predicate and takes as input all the necessary objects you need to create said predicate.&lt;/p&gt;

&lt;p&gt;The easiest way of creating specifications is by making a specification factory. This is best illustrated with an example:&lt;br&gt;
&lt;/p&gt;

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

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;@NotNull&lt;/span&gt; &lt;span class="nc"&gt;Specification&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Customer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;byName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@NotNull&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;criteriaBuilder&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;criteriaBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;like&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;1&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Customer_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;2&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;@NotNull&lt;/span&gt; &lt;span class="nc"&gt;Specification&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Customer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;byLastInvoiceDateAfter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@NotNull&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;criteriaBuilder&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;criteriaBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;greaterThan&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Customer_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lastInvoiceDate&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;@NotNull&lt;/span&gt; &lt;span class="nc"&gt;Specification&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Customer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;byLastInvoiceDateBefore&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@NotNull&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;criteriaBuilder&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;criteriaBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lessThan&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Customer_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lastInvoiceDate&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;@NotNull&lt;/span&gt; &lt;span class="nc"&gt;Specification&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Customer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;activeOnly&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="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;criteriaBuilder&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;criteriaBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isTrue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Customer_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;active&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;ol&gt;
&lt;li&gt;Here I'm just doing a simple &lt;code&gt;like&lt;/code&gt; query, but in a real-world specification you would probably want to be more thorough, paying attention to wildcards, case matching and so on.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Customer_&lt;/code&gt; is a metamodel class generated by the JPA implementation (such as &lt;a href="https://hibernate.org/orm/tooling/" rel="noopener noreferrer"&gt;Hibernate&lt;/a&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You would then use the specifications in the following way:&lt;br&gt;
&lt;/p&gt;

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

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;CustomerRepository&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;CustomerSpecifications&lt;/span&gt; &lt;span class="n"&gt;specifications&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;CustomerService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CustomerRepository&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;CustomerSpecifications&lt;/span&gt; &lt;span class="n"&gt;specifications&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;repository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;specifications&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;specifications&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Page&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Customer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;findActiveCustomersByName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Pageable&lt;/span&gt; &lt;span class="n"&gt;pageable&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;1&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findAll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;specifications&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;byName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;and&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;specifications&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;activeOnly&lt;/span&gt;&lt;span class="o"&gt;()),&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;2&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;pageable&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;ol&gt;
&lt;li&gt;Never ever write methods that return a result set without an upper bound (at least in production code). Either use pagination (like I do here) or use a finite and reasonable limit on how many records the query can return.&lt;/li&gt;
&lt;li&gt;Two specifications are here combined together using the &lt;code&gt;and&lt;/code&gt; operator.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A Note About Repositories and QueryDSL
&lt;/h2&gt;

&lt;p&gt;Spring Data also supports &lt;a href="http://www.querydsl.com/" rel="noopener noreferrer"&gt;QueryDSL&lt;/a&gt;. In this case you are not working with specifications but with QueryDSL predicates directly. The design principle is pretty much the same so if you feel more comfortable with QueryDSL than with the JPA Criteria API there is no reason for you to change.&lt;/p&gt;

&lt;h1&gt;
  
  
  Specifications and Testing
&lt;/h1&gt;

&lt;p&gt;There is one noticeable drawback with using specifications in favor of query methods and that has to do with unit testing. Since the specifications are using the JPA Criteria API under the hood, there is no easy way of making assertions on the contents of a given &lt;code&gt;Criteria&lt;/code&gt; object without constructing and analysing its JPA predicate - a nontrivial process. &lt;/p&gt;

&lt;p&gt;However, there are ways around this. The most obvious way is to just ignore checking the incoming specifications when mocking repositories in your unit tests and use separate integration tests to test your specifications, for example with an in-memory H2 database. In many cases this may be just good enough.&lt;/p&gt;

&lt;p&gt;There is also another way that avoids the use of integration tests but requires some extra work upfront. If you take a closer look at the specifications factory, you will see that the factory methods are not static but instance methods and the class itself is not final. This means that you can mock or stub the entire factory. Also, since the factory methods only return objects that implement the &lt;code&gt;Specification&lt;/code&gt; interface, you can mock or stub that interface as well. This means that as long as you avoid using the static helper methods on the &lt;code&gt;Specification&lt;/code&gt; interface (which use the JPA Criteria API), you can build a mock specification factory that returns mock specifications that can then be analyzed and used as the basis for test assertions. Unfortunately this post is not the right place to dig deeper into this so I'll just leave it as an exercise to the reader.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/peholmst/using-value-objects-as-aggregate-identifiers-with-hibernate-a2e"&gt;next post&lt;/a&gt;, we are going to look at how to use value objects as aggregate IDs. Stay tuned!&lt;/p&gt;

</description>
      <category>domaindrivendesign</category>
      <category>spring</category>
      <category>jpa</category>
      <category>ddd</category>
    </item>
    <item>
      <title>Building Aggregates with Spring Data</title>
      <dc:creator>Petter Holmström</dc:creator>
      <pubDate>Mon, 26 Apr 2021 11:00:25 +0000</pubDate>
      <link>https://dev.to/peholmst/building-aggregates-with-spring-data-2iig</link>
      <guid>https://dev.to/peholmst/building-aggregates-with-spring-data-2iig</guid>
      <description>&lt;p&gt;In my &lt;a href="https://dev.to/peholmst/using-value-objects-with-jpa-27mi"&gt;last post&lt;/a&gt; we learned how to build value objects that an be persisted with JPA. Now it is time to move on to the objects that will actually contain your value objects: entities and aggregates. &lt;/p&gt;

&lt;p&gt;JPA has its own &lt;code&gt;@Entity&lt;/code&gt; concept, but it is far less restrictive than the entity concept from DDD. This is both an advantage and a disadvantage. The advantage is that it is quite easy to implement entities and aggregates with JPA. The disadvantage is that is is equally easy to do things that is not allowed in DDD. This may be especially problematic if you are working with developers that have used JPA extensively before but who are new to DDD.&lt;/p&gt;

&lt;p&gt;Whereas value objects just implemented an empty marker interface, entities and aggregate roots will need more extensive base classes. Getting your base classes right from the start is important as it will be quite difficult to change them later, especially if your domain model has grown big. To help us with this task, we are going to use &lt;a href="https://spring.io/projects/spring-data" rel="noopener noreferrer"&gt;Spring Data&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Spring Data provides some base classes out of the box that you can use if you like, so let's start by looking at them.&lt;/p&gt;

&lt;h1&gt;
  
  
  Using &lt;code&gt;Persistable&lt;/code&gt;, &lt;code&gt;AbstractPersistable&lt;/code&gt; and &lt;code&gt;AbstractAggregateRoot&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;Spring Data provides an interface out-of-the-box called &lt;code&gt;Persistable&lt;/code&gt;. This interface has two methods, one for getting the ID of the entity and another for checking whether the entity is new or persisted. If an entity implements this interface, Spring Data will use it to decide whether to call &lt;code&gt;persist&lt;/code&gt; (new entities) or &lt;code&gt;merge&lt;/code&gt; (persisted entities) when saving it. You are, however, not required to implement this interface. Spring Data can also use the optimistic locking version to determine whether the entity is new or not: if there is a version, it is persisted; if there is none, it is new. You need to be aware of this when you decide how you are going to generate your entity IDs.&lt;/p&gt;

&lt;p&gt;Spring Data also provides an abstract base class that implements the &lt;code&gt;Persistable&lt;/code&gt; interface: &lt;code&gt;AbstractPersistable&lt;/code&gt;. It is a generic class that takes the type of the ID as its single generic parameter. The ID field is annotated with &lt;code&gt;@GeneratedValue&lt;/code&gt; which means that a JPA implementation such as Hibernate will try to auto-generate the ID when the entity is first persisted. The class considers entities with a non-null ID as persisted and entities with null IDs as new. Finally, it overrides &lt;code&gt;equals&lt;/code&gt; and &lt;code&gt;hashCode&lt;/code&gt; so that only the class and the ID are taken into account when checking for equality. This is in line with DDD - two entities are considered the same if they have the same ID.&lt;/p&gt;

&lt;p&gt;If you are fine with using ordinary Java types (such as &lt;code&gt;Long&lt;/code&gt; or &lt;code&gt;UUID&lt;/code&gt;) for your entity IDs and letting your JPA implementation generate them for you when the entity is first persisted, then this base class is an excellent starting point for your entities and aggregate roots. But wait, there is more.&lt;/p&gt;

&lt;p&gt;Spring Data also provides an abstract base class called &lt;code&gt;AbstractAggregateRoot&lt;/code&gt;. This is a class that - you guessed it - is designed to be extended by aggregate roots. However, it does &lt;em&gt;not&lt;/em&gt; extend &lt;code&gt;AbstractPersistable&lt;/code&gt; nor does it implement the &lt;code&gt;Persistable&lt;/code&gt; interface. Then why would you want to use this class? Well, it provides methods that allow your aggregate to register domain events that are then published once the entity is saved. This is really useful and we will return to this subject in a later post. Also, there are some benefits to not declaring the ID field in the base class and having your aggregate roots declare their own IDs. We will also return to this subject in a later post.&lt;/p&gt;

&lt;p&gt;In practice, you want your aggregate roots to be &lt;code&gt;Persistable&lt;/code&gt; and so you end up implementing either the methods of &lt;code&gt;AbstractAggregteRoot&lt;/code&gt; or &lt;code&gt;AbstractPersistable&lt;/code&gt; in your own base class. Let's have a look at how to do that next.&lt;/p&gt;

&lt;h1&gt;
  
  
  Building Your Own Base Classes
&lt;/h1&gt;

&lt;p&gt;In virtually all projects that I work on, both at work and in private, I start by creating my own base classes. Most of my domain models are build from aggregate roots and value objects; I rarely use so called local entities (entities that belong to an aggregate but are not roots).&lt;/p&gt;

&lt;p&gt;I often start with a base class called &lt;code&gt;BaseEntity&lt;/code&gt; and it looks 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;@MappedSuperclass&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;1&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Id&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Serializable&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AbstractPersistable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;2&amp;gt;&lt;/span&gt;

    &lt;span class="nd"&gt;@Version&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;3&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;@NotNull&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getVersion&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;Optional&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setVersion&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Nullable&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;4&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;version&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;ol&gt;
&lt;li&gt;Even though the class is named &lt;code&gt;BaseEntity&lt;/code&gt;, it is not a JPA &lt;code&gt;@Entity&lt;/code&gt; but a &lt;code&gt;@MappedSuperclass&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Serializable&lt;/code&gt; bound comes directly from &lt;code&gt;AbstractPersistable&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;I use optimistic locking for all my entities. We will return to this later in this post.&lt;/li&gt;
&lt;li&gt;There are very few, if any, situations where you want to set the optimistic locking version manually. However, to be on the safe side, I provide a protected method that makes this possible. I think most Java developers with some years under their belts have experienced situations where they would really have needed to set an attribute or call a method in a super class only to find that it was private.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once I have the &lt;code&gt;BaseEntity&lt;/code&gt; class in place, I move on to &lt;code&gt;BaseAggregateRoot&lt;/code&gt;. This is essentially a copy of Spring Data's &lt;code&gt;AbstractAggregateRoot&lt;/code&gt;, but it extends &lt;code&gt;BaseEntity&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@MappedSuperclass&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;1&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseAggregateRoot&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Id&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Serializable&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nd"&gt;@Transient&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;domainEvents&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;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;2&amp;gt;&lt;/span&gt;

    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;registerEvent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@NotNull&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;3&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;domainEvents&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@AfterDomainEventPublication&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;4&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;clearDomainEvents&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;domainEvents&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;clear&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@DomainEvents&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;5&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="nc"&gt;Collection&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;domainEvents&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;Collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;unmodifiableList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;domainEvents&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;ol&gt;
&lt;li&gt;This base class is also a &lt;code&gt;@MappedSuperclass&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;This list will contain all domain events we want to publish when the aggregate is saved. It is &lt;code&gt;@Transient&lt;/code&gt; because we don't want to store them in the database.&lt;/li&gt;
&lt;li&gt;When you want to publish a domain event from within your aggregate, you register it using this protected method. We will have a closer look at this later in this article.&lt;/li&gt;
&lt;li&gt;This is a Spring Data annotation. Spring Data will call this method after the domain events have been published.&lt;/li&gt;
&lt;li&gt;This is also a Spring Data annotation. Spring Data will call this method to get the domain events to publish.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Like I said, I rarely use local entities. However, when that need arises, I often create a &lt;code&gt;BaseLocalEntity&lt;/code&gt; class that extends &lt;code&gt;BaseEntity&lt;/code&gt; but does not provide any additional functionality (except, maybe a reference to the aggregate root that owns it). I will leave this as an exercise to the reader.&lt;/p&gt;

&lt;h1&gt;
  
  
  Optimistic Locking
&lt;/h1&gt;

&lt;p&gt;We already added a &lt;code&gt;@Version&lt;/code&gt; field for optimistic locking to &lt;code&gt;BaseEntity&lt;/code&gt; but we did not yet discuss why. In &lt;a href="https://dev.to/peholmst/tactical-domain-driven-design-17dp"&gt;Tactical Domain-DrivenDesign&lt;/a&gt;, the fourth guideline for aggregate design was to use optimistic locking. But why did we add the &lt;code&gt;@Version&lt;/code&gt; field to &lt;code&gt;BaseEntity&lt;/code&gt; and not to &lt;code&gt;BaseAggregateRoot&lt;/code&gt;? After all, isn't it the aggregate root that is responsible for maintaining the integrity of the aggregate at all times?&lt;/p&gt;

&lt;p&gt;The answer to this question is yes, but here, the underlying persistence technology (JPA and its implementtions) is again sneaking into our domain design. Let's assume we are using Hibernate as our JPA implementation.&lt;/p&gt;

&lt;p&gt;Hibernate does not know what an aggregate root is - it only deals with entities and embeddables. Hibernate also keeps track of which entities have actually been changed and only flushes those changes to the database. In practice this means that even though you explicitly ask Hibernate to save an entity, no changes may actually be written to the database and the optimistic version number may remain the same.&lt;/p&gt;

&lt;p&gt;As long as you only deal with aggregate roots and value objects, this is not a problem. For Hibernate, a change to an embeddable is always a change to its owning entity and so the optimistic version of the entity - in this case the aggregate root - will be incremented as expected. However, things change as soon as you add local entities to the mix. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Entity&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;Invoice&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseAggregateRoot&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;InvoiceId&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;1&amp;gt;&lt;/span&gt;

    &lt;span class="nd"&gt;@OneToMany&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cascade&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CascadeType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ALL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;orphanRemoval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;InvoiceItem&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;2&amp;gt;&lt;/span&gt;

    &lt;span class="c1"&gt;// The rest of the methods and fields are omitted&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Invoice&lt;/code&gt; is the aggregate root and so it extends the &lt;code&gt;BaseAggregateRoot&lt;/code&gt; class.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;InvoiceItem&lt;/code&gt; is a local entity and so it either extends the &lt;code&gt;BaseEntity&lt;/code&gt; class or a &lt;code&gt;BaseLocalEntity&lt;/code&gt; class depending on your base class hierarchy. The implementation of this class is not important so we are leaving it out, but please note the cascading options in the &lt;code&gt;@OneToMany&lt;/code&gt; annotation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A local entity is owned by its aggregate root and so is persisted through cascading. However, if a change has been made only to the local entity and not to the aggregate root, saving the aggregate root will only result in the local entity being flushed to the database. In the example above, if we made a change only to an invoice item and then saved the entire invoice, the invoice version number would remain unchanged. If another user had made changes to the same item just before we saved our invoice, we would silently overwrite the other user's changes with ours. &lt;/p&gt;

&lt;p&gt;By adding the optimistic locking version field to &lt;code&gt;BaseEntity&lt;/code&gt;, we protect against situations like this. Both the aggregate root and the local entities will be optimistically locked and it will not be possible to accidentally overwrite somebody else's changes.&lt;/p&gt;

&lt;p&gt;In the next post, we are going to look at how to &lt;a href="https://dev.to/peholmst/building-repositories-with-spring-data-1mbd"&gt;build repositories with Spring Data&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>domaindrivendesign</category>
      <category>spring</category>
      <category>jpa</category>
      <category>ddd</category>
    </item>
  </channel>
</rss>
