Eclipse Cargo Tracker

Applied Domain-Driven Design Blueprints for Jakarta EE


    Overview


    This project demonstrates how you can develop applications with the Jakarta EE platform using widely adopted architectural best practices like Domain-Driven Design (DDD). The code is intended to mirror a non-trivial application that developers in the real work would work on. It attempts to demonstrate first-hand how you can use Jakarta EE to effectively meet practical enterprise concerns such as productivity, agility, testability, flexibility, maintainability, scalability and security.

    The project is directly based on the well known original Java DDD sample application developed by DDD pioneer Eric Evans' company Domain Language and the Swedish software consulting company Citerus. The cargo example actually comes from Eric Evans' seminal book. That project uses older versions of Spring, Hibernate and Jetty whereas we focus on vanilla Jakarta EE.

    In the same vein as that project, we certainly are not in the business of prescribing how you should write Jakarta EE applications. The code simply demonstrates ideas that you could adopt if you think they are right for you. We have also tried to show you just some of the many different approaches that you could take to interpret and implement DDD concepts. You are of course warmly welcomed to provide feedback and contribute to this Open Source project.

    As such, we will continue to rely heavily on the original DDD sample application as well as the existing knowledge base in the DDD community as invaluable resources on further details on DDD as it applies to this code base (please see the DDD Sample pages for vital details). We also highly recommend you read the Jakarta EE and DDD section. It is perhaps best to skim it, explore the application/code and revisit the section.

    This effort is very grateful for the kind blessings and guidance of the good folks behind the original DDD sample application.

    Goals


    • Demonstrate well established architectural patterns/blueprints for enterprise development with Jakarta EE using pretty close to a real world application.
    • Demonstrate a concrete implementation of DDD concepts.
    • Showcase some core Jakarta EE technologies.
    • Contrary to beliefs held by some, Jakarta EE does not attempt to be a walled garden. Like all open standards, the goal of Jakarta EE is to provide a reliable core standard foundation that a vibrant ecosystem of implementations, plug-ins and extensions can be built around. In that spirit, we will incorporate a select set of representative tools that complement Jakarta EE well such as Maven, JUnit, Cargo, JMeter, soapUI, Arquillian, and PrimeFaces.

    ~


    • Comparison with other technologies such as Spring or .NET. We suggest you do your own research using the plethora of good information already available. This project is squarely about showing you how you could write good Jakarta EE applications and nothing else.
    • Attempting to demonstrate the very wide gamut of Jakarta EE APIs and features. While we do incorporate a pretty representative set of Jakarta EE APIs and features, it is not our goal to serve as a kitchen sink of comprehensive Jakarta EE samples. The official Jakarta EE Examples project serves that purpose far better than us.
    • While it is certainly possible to learn certain aspects of Jakarta EE (primarily how to architect decent Jakarta EE applications), this project is not intended to teach you the basics of Jakarta EE. The official Jakarta EE Tutorial is intended as a basic learning tool for Jakarta EE.

    Non Goals


    Getting Started


    Before exploring the code, it may be helpful to view a demo of the application functionality. You can do that through the video on the Getting Started section of the documentation that covers most of the major functionality for Eclipse Cargo Tracker.

    If you simply wish to explore the code, download it as a zip or browse the GitHub repository.

    The source is a Maven project, so you should be able to easily build it or set it up in your favorite IDE. We currently have instructions for Visual Studio Code as part of our documentation. We welcome contributions showing how to use the project with other IDEs.

    You can also run the application directly from the Maven command line using Apache Cargo. All you need to do is navigate to the project source root and type the following (please make sure you have Java SE 11/Java SE 17 and JAVA_HOME set up):

    mvn clean package cargo:run

    Once the application starts up, just open up a browser and navigate to http://localhost:8080/cargo-tracker/.

    This will run the application with Payara Server by default. The project also has Maven profiles to support GlassFish and Open Liberty. For example you can run using GlassFish using the following command:

    mvn clean package -Pglassfish cargo:run

    Similarly you can run using Open Liberty using the following command:

    mvn clean package -Popenliberty liberty:run

    The project currently runs on Jakarta EE 10, Payara/GlassFish/Open Liberty, and Java SE 11/Java SE 17. We welcome contributions for running the application on other Jakarta EE implementations (as you will see in the source code, there are few dependencies on Payara/GlassFish/Open Liberty so this should be pretty easy to do).

    Eclipse Cargo Tracker is deployed to Kubernetes on the cloud using GitHub Actions workflows. You can find the demo deployment on the Scaleforce cloud (https://cargo-tracker.j.scaleforce.net). This project is very thankful to our sponsors Jelastic and Scaleforce for hosting the demo! The deployment and all data is refreshed nightly.

    Background


    Many of you might have at least heard of the J2EE Blue Prints/PetStore. In many ways, the J2EE Blue Prints/PetStore was far ahead of it's time. It helped establish some degree of order out of the chaos of mid-nineties enterprise development. It brought to the mainstream many architectural patterns like separation of concerns, layering, MVC, DAO, DTO and the like that we now mostly take for granted. It also helped catapult J2EE itself. The PetStore of course was not without its own fair share of problems. The most significant of these problems is the fact that many patterns in the PetStore were either motivated or encumbered by the problems of the then relatively new J2EE and EJB 2 technologies and EJB 2 entity beans did not support OO well.

    DDD provided concrete solutions to the weaknesses in the PetStore with the help of emergent concepts of POJO programming, ORM and lightweight frameworks. It is no accident that DDD is now widely adopted by the Spring and .NET communities. As Jakarta EE has now fully embraced concepts like POJO programming, lightweight programming models, annotations, ORM, rich domain models, agility and testability, this project brings things full circle. It demonstrates first hand how you can utilize the best of the breed in enterprise software development practices using the power and simplicity of the standard, vendor-neutral Jakartra EE platform. Notably unlike the J2EE Blue Prints/PetStore, we will not invent new patterns here but simply adopt the proven, mature ideas in the DDD community.

    Jakarta EE and DDD


    As the name implies, Domain-Driven Design is an approach to software design and development that focuses on the core domain and domain logic. The domain is implemented through a careful focus on traditional OOAD (Object Oriented Analysis and Design) and modeling the real world problem the software is trying to solve as closely as possible.

    Wikipedia does a surprisingly good job at overviewing DDD. Aslam Khan's DDD Ref Card on DZone is a brief read and does a great job of explaining the core concepts of DDD. For a bit more detail, you could read the free DDD eBook on InfoQ. Finally, you can of course read Eric Evans' book itself. However, we recommend not starting with the book until you get a bit of your bearings around this application first.

    The basic building blocks of the domain are entities, value objects, aggregates, services, repositories and factories. The Characterization section of our documentation overviews how these concepts are implemented in the application using Jakarta EE. Logical layers partitioning distinct concerns are super-imposed on the core concept of the domain. These layers generally consist of the UI/interface layer, the application layer, the domain layer (of course!) and the infrastructure layer respectively. The Layers section of our documentation explains the architectural layers in the application and how they relate to various Jakarta EE APIs. The DDD community also fully embraces practices like automated testing, agile, emergent design, refactoring and Continuous Integration. We have incorporated all these practices into the application in a pragmatic fashion. DDD is a very useful concept in pragmatic microservices development, particularly ideas such as the bounded context. We have incorporated some of these ideas. Some DDD related concepts we have not tackled are CQRS and Event Sourcing.


    (Diagram credited to Domain-Driven Design Quickly)

    One of the primary principles of DDD is that design should be focused on the business domain, not technology. The role of technology is to empower software developers to implement readable, productive, maintainable systems that mirror the real world, not place constraints on design choices. Most mainstream technology stacks today have matured enough to make this principle a reality, Jakarta EE is no exception. In fact, with a single-minded focus on simplicity, POJOs, Java/OO centric strong typing, annotations and intelligent defaults that minimize system configuration and lets developers focus on solving the business problem, we think Jakarta EE is one of the best platforms to support DDD. Jakarta EE makes it possible to quickly and effectively produce a working system by annotating domain and application classes and implementing interface and infrastructure code. In the Characterization and Layers sections of our documentation we have overviewed how some key Jakarta EE APIs map to DDD concepts and pointed you to some of the most important bits of implementation code in the application. In the figure below, we have summarized how this mapping looks like visually as a handy cross reference.



    Note, the diagram above is most certainly not intended to be comprehensive. For example, besides Jakarta Faces, REST, WebSocket and Batch, some other technologies that are very useful in implementing interfaces are CDI (for Faces backing beans), Bean Validation, Enterprise Beans (e.g. messaging end-points), JSON Processing and JSON Binding. Similarly, you can choose to implement application services as transactional CDI beans as opposed to Enterprise Beans and you can use Interceptors, Jakarta Transactions, Jakarta Concurrency and Jakarta Security in the application layer. Value Objects can be implemented as either Jakarta Persistence embeddables or entities. In addition to Jakarta Persistence, Messaging, Mail and REST clients it is very likely you may use CDI and Bean Validation to implement infrastructure components. The DeltaSpike Data module is very helpful in implementing repositories. The point really is that Jakarta EE APIs are there to help you implement elegantly designed systems as needed.

    Jakarta EE Features


    The following table shows some of the Jakarta EE features we have used in the application. This is by no means a comprehensive list, just the primary ones worth mentioning.

    Faces Facelets, templates, view parameters, view actions, message bundles, CDI compatible view scope, flows, HTML 5 pass-though attributes, HTML 5 pass-though elements
    CDI Basic injection, scopes, named beans, qualifiers, events, observers
    Enterprise Beans Transactions, stateless session bean, message driven bean, startup singleton, CRON style scheduling, application exceptions, XML deployment descriptors, portable activation configuration
    Persistence Generated ID, basic mapping, embeddables, many-to-one, one-to-many, enumerations, temporal types, named queries, managed persistence context, portable data source definition, schema generation, data loading, locking, second-level caching
    REST REST endpoint, MIME types, client API, JSON processing, content-type negotiation, Server-Sent Events/broadcasting
    JSON Binding Integration with REST endpoints, default Java-JSON mapping
    Bean Validation Basic validation annotations, method level validation for REST endpoints, method level validation for local Enterprise Beans application services
    Messaging Simplified API message send, portable resource definition
    Batch Job operator, job XML, job properties, job context, job listener, skip listener, reader, writer, skippable exceptions, checkpointing, chunking
    Transactions @Transactional interceptor