¶
Tentackle is a Java framework for building multi-tier applications around a single domain model. Its entities — Persistent Domain Objects — keep persistence and domain logic in separate classes, united behind one interface. They travel between JVMs as real, live objects, so you can call any of their methods on any tier — server, web, edge, or desktop — with no DTOs and no REST plumbing in between.
Two ideas carry the framework, and each makes the other possible.
Persistent Domain Objects. An Invoice is one interface backed by two
independent implementations: the persistence side — attributes, relations, finders,
persist() — generated from the model, and the domain side — approve() — written
by hand. Neither class knows the other. They are woven together at runtime into a
single object behind a dynamic proxy that behaves as if it inherited from both:
multiple inheritance, emulated. Business rules never touch SQL or a wire format,
and the generated persistence code never depends on a business rule.
Location transparency. This is not about invoking methods on objects that stay
on a server. The PDO itself travels between JVMs — physically, serialized by
TRIP, Tentackle's compact binary protocol —
and arrives with its state and its domain logic. It is neither a stub nor a DTO: its
methods run in the JVM that currently holds it, and because the persistence side is
remoting-capable, only what needs the database goes over the wire. Write
invoice.approve() once, in the domain layer, and call it from a server, an edge
node on the shop floor, a web node, or a JavaFX desktop client. Even three tiers away
from the database, it just works: the object arrives fully alive, navigates its
relations on demand, and opens a real transaction on the tier that owns the
connection. There is no DTO layer, no endpoint, no fetch plan, and no
LazyInitializationException — the exception type does not exist here.
// domain interface of the Invoice PDO — the transactional contract is part of the API
public interface InvoiceDomain extends DomainObject<Invoice> {
@Transaction
void approve();
}
// domain side of the Invoice PDO — written once, deployed everywhere
@Override
public void approve() {
Customer customer = me().getCustomer(); // me() is the whole PDO; the customer is fetched on demand, locally or over the wire
if (customer.getCreditLimit().compareTo(customer.openAmount()) < 0) {
throw new DomainException("credit limit exceeded");
}
me().setState(InvoiceState.APPROVED);
me().persist(); // validates the aggregate, then writes
}
// any client JVM, three tiers from the database — the entire call site
invoice.approve();
The domain code reaches the persistence side only through the PDO's interfaces, so which implementation answers — JDBC or a remote delegate — is not its concern. Which tier that code runs on is a connection URL in a properties file, not a decision baked into the source.
To see it running, the Quickstart generates and builds a complete multi-tier application in minutes.
Tentackle is Open Source (LGPL 2.1), available from
Maven Central, and requires
Java 25 or later (older LTS lines are maintained on the java21, java17,
java11 and java8 branches).
Why Tentackle?¶
Five things set Tentackle apart from other Java frameworks:
-
Persistent Domain Objects (PDOs), not an ORM. Persistence and domain logic stay fully independent, yet form one object — and there are no lifecycle states: no attached, detached, or half-loaded entities. See PDO and PDOs vs. Traditional ORMs.
-
Write the domain logic once, run it on any tier. The database may be local, behind a middle-tier server, or at the end of a cascade of nested servers — the topology is pure configuration. PDOs travel over TRIP, a compact binary protocol that replaces RMI and Java serialization with pluggable, SD-WAN-friendly transports (TLS, compression, pre-shared-key encryption, QUIC). See the Multi-Tier Cascade.
-
Correctness is the default, not an add-on. Optimistic (
serial) locking is always on, validation is declarative and travels with the object, aggregates are first-class citizens enforcing DDD boundaries and reverting atomically via snapshots, and shared objects can be made immutable. Whatever goes wrong fails loudly and early instead of corrupting data quietly. See Correctness First. -
One model — generated everywhere, and queryable by tools. The model lives in a comment block of the PDO interface and drives generation of the persistence layer, DDL and database migrations through the Wurbelizer. That model is not locked away in the source, though:
mvn tentackle-mcp:serveserves it relation-resolved — as the code generators see it — to coding agents over MCP, validating a candidate definition against the whole model in under a second, and the code-generation wizards also run headless. See AI Agent Tooling Support. -
True JPMS, self-contained apps. Every runtime module is a real JPMS module. Service discovery is resolved at build time by the ServiceFinder SPI — no runtime classpath scanning, fast startup, and it works in both modular and classpath mode. Applications ship as self-contained jlink/jpackage images, and desktop clients get a rich JavaFX framework and built-in auto-update.
When to use Tentackle — and when not to¶
A framework that fits everything fits nothing. Tentackle makes a specific trade: it gives up polyglot reach and ecosystem size to buy a single, coherent domain model that runs unchanged on every tier. That trade is excellent for some projects and a poor deal for others, so here is the honest filter.
Tentackle is probably a good fit if…¶
- You build both ends. Java on the client (or the edge node) and Java on the server, shipped by one team from one model. This is the central assumption.
- Your domain is rich and long-lived — invariants, aggregates, workflows, business rules that outlive three UI rewrites — rather than CRUD over a table.
- The topology is imposed on you, or simply awkward: JVMs pinned to hardware, more than two tiers, NAT or a gateway in the middle, links that are slow, lossy, or without a PKI. See Technical and Scientific Applications.
- You need a real desktop client — tables, trees, master/detail forms, keyboard
workflows, auto-update — not a web page.
tentackle-fx-rdcis a first-class citizen here, not an afterthought. In-house applications are a good candidate: the users are employees working with the system all day, not anonymous visitors who must get by without installing anything. - Being wrong is expensive. Money, materials, measurements, regulated records: domains where a quietly corrupted row costs more than a night of downtime. See Correctness First.
- You are tired of the DTO/mapper/fetch-plan layer and would rather not maintain a second, weaker copy of your model just to move it between your own processes.
Look elsewhere if…¶
- You are building a stateless web API or microservices. Use Quarkus, Spring Boot, or Micronaut. They are excellent at it, Tentackle isn't built for it, and its location-transparency machinery solves a problem you do not have.
- Your clients are browsers, mobile apps, or other teams' services. They cannot speak TRIP and should not have to. You can put a Tentackle web node behind a REST edge — but if that edge is the whole product, the framework earns little.
- You need polyglot services, or infrastructure you do not control. Tentackle assumes JVM-to-JVM communication on a network you own.
- You want to bolt it onto an existing Spring/JPA codebase. Tentackle is a programming model, not a library you add to fix a DTO layer.
- Two teams must deploy on genuinely independent schedules. A shared domain model means coordinated releases; an organizational seam wants a negotiated wire contract instead.
- It is a one-tier CRUD app, or ecosystem size and hiring familiarity outrank architectural fit. Both are legitimate reasons to choose something else.
- You need hard real-time. Tentackle runs on a standard JVM. Its sweet spot is the soft-real-time layer above hard-real-time PLCs and firmware.
If you are weighing Tentackle against the alternatives at the tier boundary, the detailed argument — with code on both sides — is in Location Transparency vs. REST, RMI and Spring Remoting.
Where to go next¶
- 🚀 Quickstart — generate, build, and run a complete multi-tier application in minutes.
- 🔔 What a Seasoned Java Developer Would Not Expect — the short version, for the impatient.
- ⚖️ Location Transparency vs. REST, RMI and Spring Remoting — what the tier boundary costs in each approach, and where each one wins.
- 🔎 Index — look up a concept and jump straight to it.
- 🤖 AI Agent Tooling — the MCP model server, the headless wizard batch modes, and the bundled agent skills.
- 🧾 Maven site — Javadoc, source cross-reference, and reports.
- 🏛️ Architecture — the design overview: the central ideas and how they depend on each other.
- 🤝 Contributing — how to report issues and submit changes.
- 📝 Changelog — the notable changes of every release since 2.0.0.