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 based on the well-known 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.
We are really 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 existing knowledge base in the
DDD community as an invaluable resource on further details on DDD as
it applies to this code base. 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.
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.
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.
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.
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.
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 |