English | 中文
jfoundry is a practical DDD framework for Java, built on jMolecules and designed to fit well-known Hexagonal Architecture and Onion Architecture styles.
Its goal is straightforward: help business projects make domain modeling, architecture boundaries, and reliable integration executable in code, while keeping the core independent of runtime frameworks. DDD concepts, architecture semantics, application contracts, domain events, Outbox/Inbox, persistence SPI, and messaging SPI do not depend on Spring, Spring Boot, Quarkus, Helidon, or Micronaut.
Spring is the first runtime integration and lives under jfoundry-spring. Future Quarkus, Helidon, Micronaut, or other runtime integrations should be added as peer integration modules on top of the same core SPI, instead of pushing runtime dependencies into the core.
Many DDD projects fail not because they lack concepts, but because those concepts never become engineering boundaries. The domain layer gets polluted by Spring, ORM, or MQ APIs; application transaction boundaries become unclear; repositories gradually become generic query interfaces; domain events cannot be externalized reliably; architecture rules remain only in documents.
jfoundry addresses these practical problems:
- Express DDD, Hexagonal, Onion, and CQRS semantics with jMolecules.
- Use Maven modules, starters, and SPI to preserve dependency direction across domain, application, infrastructure, and runtime integration boundaries.
- Turn architecture constraints into executable tests with ArchUnit.
- Provide production-oriented building blocks such as Outbox/Inbox, messaging SPI, persistence SPI, and application transaction boundary contracts.
The domain model is the center. Aggregates, value objects, domain events, repository contracts, and domain exceptions do not depend on Spring, ORM, HTTP, MQ, or database clients.
DDD is not Hexagonal Architecture, and it is not Onion Architecture. They are design tools at different levels. jfoundry provides first-class support for Hexagonal Architecture and Onion Architecture so projects can explicitly choose an architecture style and enforce dependency direction with rules.
Core modules only express business modeling, application orchestration, and external capability contracts. Spring Boot auto-configuration, Spring transactions, Spring events, Web MVC, JobRunr, and similar concerns belong to outer runtime integration modules.
The framework includes Transactional Outbox, consumer-side Inbox idempotency, application transaction boundaries, messaging SPI, payload serialization SPI, optional MyBatis-Plus and Jakarta Persistence adapters, and reusable architecture test rules.
| Area | Capability |
|---|---|
| DDD building blocks | Aggregate roots, entity base types, value object marker, domain events, repository contracts, domain exceptions |
| Architecture styles | jMolecules-based Hexagonal / Onion annotations and ArchUnit rules |
| Application layer | ApplicationService, application exceptions, TransactionRunner, CQRS semantics |
| Domain events | Event recording, scoped event context, dispatch contracts, Spring ApplicationEvent adapter |
| Reliable messaging | Transactional Outbox, Inbox idempotency, broker-neutral MessageSender, payload serialization SPI |
| Persistence | Runtime-neutral persistence contracts plus optional MyBatis-Plus and Jakarta Persistence adapters |
| Runtime integration | Optional Spring Framework / Spring Boot starters, auto-configuration, Web MVC ProblemDetail support |
| Verification | Reusable ArchUnit rules for business projects and internal framework module boundaries |
jfoundry makes the following boundaries explicit:
domain
DDD model, value objects, domain events, repository contracts
application
application services, transaction boundary contracts, CQRS, Outbox/Inbox SPI,
domain event orchestration, messaging SPI
infrastructure
persistence adapters, messaging adapters, serialization adapters,
background dispatch adapters
runtime integration
Spring Framework adapters, Spring Boot auto-configuration, and starters
Dependencies point inward. Runtime integration modules assemble core contracts and adapters, but core modules do not depend on runtime integrations:
runtime integration
-> application / infrastructure adapters
-> application contracts
-> domain
The same core can be assembled by Spring today, and by Quarkus, Helidon, Micronaut, or another runtime later.
Choose the BOM for your runtime first, then add starters explicitly by module responsibility.
<dependencyManagement>
<dependencies>
<!-- Runtime-neutral core: DDD, architecture semantics, application contracts, SPI. -->
<dependency>
<groupId>io.github.xfoundries</groupId>
<artifactId>jfoundry-dependencies</artifactId>
<version>${jfoundry.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>For Spring Boot applications, use the Spring BOM instead:
<dependency>
<groupId>io.github.xfoundries</groupId>
<artifactId>jfoundry-spring-dependencies</artifactId>
<version>${jfoundry.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>Typical module dependencies:
<!-- domain module -->
<dependency>
<groupId>io.github.xfoundries</groupId>
<artifactId>jfoundry-domain-starter</artifactId>
</dependency>
<!-- application module -->
<dependency>
<groupId>io.github.xfoundries</groupId>
<artifactId>jfoundry-application-starter</artifactId>
</dependency>
<!-- Spring Boot runtime assembly module, optional -->
<dependency>
<groupId>io.github.xfoundries</groupId>
<artifactId>jfoundry-spring-boot-starter</artifactId>
</dependency>Persistence, Outbox, Inbox, and broker starters should be added explicitly based on business needs. Avoid adding every starter by default. See Getting Started for Business Projects for module-level dependency guidance.
import org.jfoundry.domain.valueobject.ValueObject;
import org.jmolecules.ddd.annotation.AggregateRoot;
import java.math.BigDecimal;
public record Money(BigDecimal amount, String currency) implements ValueObject {
}
@AggregateRoot
public class Order {
private OrderId id;
private Money total;
public void changeTotal(Money total) {
this.total = total;
}
}Architecture rules should run in business project tests, not remain only in framework documentation:
import com.tngtech.archunit.junit.AnalyzeClasses;
import com.tngtech.archunit.junit.ArchTest;
import com.tngtech.archunit.junit.ArchTests;
import org.jfoundry.test.archunit.JFoundryRules;
@AnalyzeClasses(packages = "com.mycompany.myapp")
class MyAppArchitectureTest {
@ArchTest
static final ArchTests onion = JFoundryRules.onionSimple();
@ArchTest
static final ArchTests ddd = JFoundryRules.jmoleculesDdd();
}Use JFoundryRules.hexagonalStrict() when the project chooses Hexagonal Architecture. Use JFoundryRules.onionSimple() or JFoundryRules.onionClassical() when it chooses Onion Architecture.
Aggregate repositories keep their DDD identity across styles. A Hexagonal project may additionally
mark one as a @SecondaryPort without moving it out of domain.repository; an Onion project keeps
the contract in an inner ring and its implementation in the infrastructure ring.
Onion does not define Primary/Secondary Port or Adapter roles or class-name suffixes. Prefer DDD
ubiquitous language and actual responsibilities. Reader, Store, Finder, and Provider can be
useful Java project conventions, but they are not official DDD, Onion, or jfoundry patterns.
Domain events can stay in-process, or they can be externalized reliably through Outbox:
aggregate records domain event
-> application service boundary drains events
-> externalization rule selects topic/key/payload
-> Outbox row is written in the same database transaction
-> dispatcher claims and sends through MessageSender
-> consumer side uses InboxTemplate for message/consumer idempotency
Outbox is optional. Enable it only when events need cross-process delivery, retry, or reliable externalization. See Transactional Outbox for details.
| Module | Purpose |
|---|---|
jfoundry-domain |
Domain base types, value object contract, domain events, repository contracts |
jfoundry-architecture |
Hexagonal, Onion, CQRS architecture semantics and architecture test rules |
jfoundry-application |
Application service contracts, transaction boundary, domain event orchestration, messaging, Outbox/Inbox SPI |
jfoundry-infrastructure |
Technical adapters for persistence, serialization, messaging, and background dispatch |
jfoundry-starters |
Runtime-neutral dependency entry points |
jfoundry-spring |
Spring Framework adapters, Spring Boot auto-configuration, and starters |
jfoundry-verification |
Internal middleware and runtime behavior verification |
- Documentation Index
- Framework semantics: Architecture Styles, ArchUnit Rules, Framework Boundaries
- Modeling conventions: Value Objects, Repository and Read-side Contracts
- Technical integration: Getting Started, Adoption Readiness, Persistence DataMapper, Transactional Outbox and Inbox
mvn validate
mvn test
mvn clean install