<?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: Jose Manuel Castellano Jiménez</title>
    <description>The latest articles on DEV Community by Jose Manuel Castellano Jiménez (@jmcastellanojimenez).</description>
    <link>https://dev.to/jmcastellanojimenez</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%2F1847964%2Ffd44cc30-9ce9-4eb6-9229-3c8933934310.jpeg</url>
      <title>DEV Community: Jose Manuel Castellano Jiménez</title>
      <link>https://dev.to/jmcastellanojimenez</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jmcastellanojimenez"/>
    <language>en</language>
    <item>
      <title>Best hexagonal course ever</title>
      <dc:creator>Jose Manuel Castellano Jiménez</dc:creator>
      <pubDate>Mon, 25 Aug 2025 18:06:24 +0000</pubDate>
      <link>https://dev.to/jmcastellanojimenez/best-hexagonal-course-ever-5ceb</link>
      <guid>https://dev.to/jmcastellanojimenez/best-hexagonal-course-ever-5ceb</guid>
      <description>&lt;p&gt;&lt;strong&gt;Excellent choice! This repository is a very well-structured **production architecture reference.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jmcastellanojimenez/ecotrack" rel="noopener noreferrer"&gt;ecotrack Java Application Repo&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Suggested Study Plan
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Start with the Documentation&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docs/
├── learn_hexagonal/learn_hexagonal.md    # START HERE!
├── architecture/C4-containers.md         # High-level view
└── runbook.md                            # Operations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why&lt;/strong&gt;: The &lt;code&gt;learn_hexagonal&lt;/code&gt; documentation will map out exactly how the concepts we discussed are implemented.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Analyze the Structure of ONE Service First&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I recommend starting with &lt;strong&gt;&lt;code&gt;user-service&lt;/code&gt;&lt;/strong&gt; because it is the simplest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services/user-service/
├── src/main/java/com/ecotrack/user/
│   ├── domain/          # ← CORE: Entities, Value Objects, Domain Services
│   ├── application/     # ← USE CASES: Application Services, Ports
│   ├── infrastructure/  # ← ADAPTERS: REST, JPA, Config
│   └── UserServiceApplication.java
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. &lt;strong&gt;Practical Hexagonal Mapping&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Domain (Center of the Hexagon):&lt;/strong&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="c1"&gt;// services/user-service/src/main/java/com/ecotrack/user/domain/&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;              &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nc"&gt;Main&lt;/span&gt; &lt;span class="n"&gt;entity&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nc"&gt;Port&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt; &lt;span class="err"&gt;-&lt;/span&gt; &lt;span class="nc"&gt;NO&lt;/span&gt; &lt;span class="n"&gt;implementation&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nc"&gt;Email&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;             &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nc"&gt;Value&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nc"&gt;UserDomainService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nc"&gt;Complex&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt; &lt;span class="n"&gt;logic&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Application (Use Cases):&lt;/strong&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="c1"&gt;// services/user-service/src/main/java/com/ecotrack/user/application/&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nc"&gt;CreateUserUseCase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;     &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nc"&gt;Use&lt;/span&gt; &lt;span class="k"&gt;case&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nc"&gt;FindUserUseCase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;       &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nc"&gt;Another&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="k"&gt;case&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;ports&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;                    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nc"&gt;Input&lt;/span&gt; &lt;span class="nf"&gt;ports&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;what&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt; &lt;span class="n"&gt;exposes&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;                   &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nc"&gt;Output&lt;/span&gt; &lt;span class="nf"&gt;ports&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;what&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt; &lt;span class="n"&gt;needs&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Infrastructure (Adapters):&lt;/strong&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="c1"&gt;// services/user-service/src/main/java/com/ecotrack/user/infrastructure/&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;web&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nc"&gt;UserController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="no"&gt;REST&lt;/span&gt; &lt;span class="nf"&gt;Adapter&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;IN&lt;/span&gt; &lt;span class="nc"&gt;Port&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;persistence&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nc"&gt;JpaUserRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="no"&gt;JPA&lt;/span&gt; &lt;span class="nf"&gt;Adapter&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;OUT&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
    &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nc"&gt;BeanConfiguration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nc"&gt;Dependency&lt;/span&gt; &lt;span class="n"&gt;injection&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. &lt;strong&gt;Data Flow to Follow&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;HTTP Request&lt;/strong&gt; → &lt;code&gt;UserController&lt;/code&gt; (Adapter)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Controller&lt;/strong&gt; → &lt;code&gt;CreateUserUseCase&lt;/code&gt; (Application)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Case&lt;/strong&gt; → &lt;code&gt;UserDomainService&lt;/code&gt; (Domain) &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain&lt;/strong&gt; → &lt;code&gt;UserRepository&lt;/code&gt; interface (Port)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interface&lt;/strong&gt; → &lt;code&gt;JpaUserRepository&lt;/code&gt; (Adapter)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JPA&lt;/strong&gt; → PostgreSQL&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  5. &lt;strong&gt;Key Concepts to Look For&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Dependency Injection:&lt;/strong&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;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreateUserUseCase&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;UserRepository&lt;/span&gt; &lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Port, not implementation&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;CreateUserUseCase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="n"&gt;userRepository&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;userRepository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userRepository&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;&lt;strong&gt;Configuration (Composition Root):&lt;/strong&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;@Configuration&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;BeanConfiguration&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Bean&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="nf"&gt;userRepository&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;JpaUserRepository&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Here the adapter connects to the port&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;
  
  
  6. &lt;strong&gt;Compare with the CQRS Diagram&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The project probably implements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Commands&lt;/strong&gt;: &lt;code&gt;CreateUserUseCase&lt;/code&gt;, &lt;code&gt;UpdateUserUseCase&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Queries&lt;/strong&gt;: &lt;code&gt;FindUserUseCase&lt;/code&gt;, &lt;code&gt;GetUserProfileUseCase&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Events&lt;/strong&gt;: See &lt;code&gt;tracking-service&lt;/code&gt; using Kafka&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  7. &lt;strong&gt;Layered Learning Approach&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Week 1&lt;/strong&gt;: A single service (&lt;code&gt;user-service&lt;/code&gt;)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Folder structure&lt;/li&gt;
&lt;li&gt;HTTP flow → Domain → DB&lt;/li&gt;
&lt;li&gt;Testing each layer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Week 2&lt;/strong&gt;: Communication between services&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;tracking-service&lt;/code&gt; → Kafka → &lt;code&gt;notification-service&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Events and asynchronous messaging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Week 3&lt;/strong&gt;: Infrastructure &amp;amp; DevOps&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker Compose setup&lt;/li&gt;
&lt;li&gt;Kubernetes manifests&lt;/li&gt;
&lt;li&gt;Observability (metrics, logs)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  8. &lt;strong&gt;Suggested Practical Exercises&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Map the complete flow&lt;/strong&gt; of creating a user&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add a new endpoint&lt;/strong&gt; following the same pattern&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write tests&lt;/strong&gt; for each layer separately&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modify the implementation&lt;/strong&gt; of persistence (change from JPA to something else)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  9. &lt;strong&gt;Questions to Ask Yourself&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Where are the business rules?&lt;/li&gt;
&lt;li&gt;How are dependencies injected?&lt;/li&gt;
&lt;li&gt;What would happen if I replaced PostgreSQL with MongoDB?&lt;/li&gt;
&lt;li&gt;How is each layer tested independently?&lt;/li&gt;
&lt;li&gt;How do services communicate with each other?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  10. &lt;strong&gt;Red Flags to Avoid&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Don't copy code without understanding why it's there&lt;/li&gt;
&lt;li&gt;Don't implement all services at once&lt;/li&gt;
&lt;li&gt;Don't ignore tests—they reveal a lot about the architecture&lt;/li&gt;
&lt;li&gt;Don't skip the &lt;code&gt;learn_hexagonal&lt;/code&gt; documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tip&lt;/strong&gt;: After you understand a service well, try to &lt;strong&gt;recreate the structure from scratch&lt;/strong&gt; with a different domain (e.g., a library, a simple e-commerce site). This will confirm that you really understood the patterns.&lt;/p&gt;

&lt;p&gt;Which service would you like to start with? I strongly recommend &lt;code&gt;user-service&lt;/code&gt; because it is the most straightforward for understanding the fundamentals.&lt;/p&gt;

&lt;p&gt;Translated with DeepL.com (free version)&lt;/p&gt;

</description>
      <category>hexagonal</category>
      <category>ddd</category>
      <category>spring</category>
      <category>java</category>
    </item>
  </channel>
</rss>
