Annotate your domain model once; Project Equilibrium’s annotation processor generates matching transfer types so names, packages, and structure stay aligned. You still map data however you like (constructors, MapStruct, hand-written code) — this project focuses on generating the shapes with compile-time validation and optional Jakarta constraints on generated members.
If you find this project useful, consider supporting me ☕
Hand-maintained DTOs and cousins often mean:
- 😩 Boilerplate and copy-paste types that drift from the domain
- 💥 Surprises at runtime** when something no longer lines up
- 🔧 Refactors that sprawl across many files
Project Equilibrium pushes that work to compilation: generated Java sources, consistent defaults, and errors when configuration is impossible — not when a user hits an edge case.
✔ No reflection for generation
✔ No extra runtime library for creating those type definitions
✔ Full type safety on the processor’s configuration surface
✔ Clean model: annotate the domain, consume generated types
Deeper rationale, trade-offs, and “when not to use it”: Why Project Equilibrium?.
1. Add the dependency (version from Maven Central):
<dependency>
<groupId>io.github.soulcodingmatt</groupId>
<artifactId>equilibrium</artifactId>
<version><!-- latest --></version>
</dependency>2. Register the processor and set defaults (packages / postfixes). Full pom.xml snippet: Build tooling.
3. Mark the domain class:
import io.github.soulcodingmatt.equilibrium.annotations.dto.GenerateDto;
@GenerateDto
public class User {
private String name;
private int age;
// getters / setters
}4. Compile — use the generated UserDto (or your configured package/postfix).
👉 Extended copy-paste flow: Quickstart.
🧪 Working example project: equilibrium-test — a ready-to-clone project that demonstrates how the annotations work in practice.
Project Equilibrium runs as a standard Java annotation processor: it emits plain source files during javac, so builds stay predictable and debuggable. Details: How it works.
Use Project Equilibrium alongside mappers and frameworks — for example MapStruct for field-to-field mapping between types you already have. Summary and build notes: Ecosystem.
Index of all guides: docs/README.md
| Topic | Guide |
|---|---|
| Why / when / benefits | Why Project Equilibrium? |
| Quickstart | docs/quickstart.md |
| Maven, IDE, Lombok, Gradle | docs/build-tooling.md |
Compiler -A options |
docs/configuration.md |
| All annotations (generate / ignore / nest / validate) | docs/annotations-reference.md |
| MapStruct and complements | docs/ecosystem.md |
| DTO builder + Lombok | docs/dto-builder-pattern.md |
| Experimental Jakarta validation | docs/experimental-validation.md |
| DTOs + interfaces (wrapper pattern) | docs/dto-interface-pattern.md |
| Custom fields and methods on generated DTOs | docs/custom-fields-and-methods.md |
| Troubleshooting and pitfalls | docs/troubleshooting-and-pitfalls.md |
You can use this annotation processor in commercial or closed-source projects when it runs only at compile time and is not shipped inside your artifacts. In that typical setup, GPL-3.0 does not require you to open-source your own application code.
- Java 21 or higher (the processor targets the Java 21 language level)
- A build tool that can resolve dependencies from Maven Central (or your repository) and run annotation processing (for example Maven 3.x or Gradle 8.x)
Older tool versions may work but are not validated. Building Project Equilibrium uses Maven in this repository; consuming projects do not need to run this project’s pom.xml.
- Generation of DTOs, records, and VOs with
@GenerateDto,@GenerateRecord, and@GenerateVo(including multiple generations per source class viaid,pkg, andname) - Global defaults via compiler options (
-Aequilibrium.*), with per-annotation overrides where supported - Field exclusion with
@IgnoreDto,@IgnoreRecord,@IgnoreVo, and@IgnoreAll, including selective exclusion withidswhen you generate several variants from one class - Nested DTO wiring with
@NestedMapping(class reference) and@NestedDtoMapping(string class names, including per–DTO-id mappings when you use multiple@GenerateDtoids) - Optional Lombok
@SuperBuilderon generated DTOs (@GenerateDto(builder=true)), plus@DtoBuilderDefaultfor builder default values where applicable - Field type preservation (including generics) and inheritance: generated types include fields from superclasses
- Optional experimental compile-time validation helpers (
@ValidateDto,@ValidateRecord,@ValidateVo) that emit Jakarta Bean Validation constraints on generated members - Compile-time summary output: optional banner and statistics — see Configuration (compile output)
In your application: add the published Maven dependency (artifactId equilibrium), put the processor on annotationProcessorPaths, and pass -Aequilibrium.* flags (or rely on annotation parameters) for packages and postfixes. Any tool that resolves Maven artifacts and runs Java annotation processing can consume the JAR.
From this repository: build with Maven (mvn verify or mvn install) to compile, run tests, and produce the same artifact layout this project publishes — including metadata stamped from the POM. Porting that to another build system means replicating dependency scopes, processor path, and resource packaging.
AI tools were used throughout the development of this project — including prototyping, testing, bug fixing, and refactoring. The primary author has over 25 years of experience with Java and more than 10 years as a professional software developer. AI was used as a productivity tool, not as a substitute for expertise. All architectural decisions, design, and final validation were carried out by a human. AI assisted the process, but responsibility and ownership remain human.
Using tools that improve efficiency is a natural part of modern software development.
Contributions are welcome — issues, ideas, and pull requests.
See CHANGELOG.
This project is licensed under the GNU General Public License v3.0 — see the LICENSE file.
For questions or issues, please use the repository’s issue tracker.
Dependency names, how they are used (for example provided, test, or tooling scopes), and license families are documented in NOTICE. The published JAR includes the same text as META-INF/NOTICE. For exact artifact versions, see pom.xml.
