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.
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 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 Eclipse 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 8/Java SE 11 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/.
The project currently runs on Jakarta EE 8, Payara 5 and Java SE 8/Java SE 11. 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 so this should be pretty easy to do).
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|