Dependency boundaries
Keep domain code independent, adapters behind ports, and APIs away from persistence details.
Architecture policies as executable evidence
Import compiled classes without loading them, model their real dependency graph, evaluate deterministic rules, and publish reviewable results in tests and CI.
Five-minute quickstart
Add the published release as a test dependency and point a bounded policy file at compiled classes.
Maven Central is the public registry; Central Portal is its publisher interface. Maven and Gradle consumers resolve version 0.1.0 from Central without needing a Portal account.
repositories {
mavenCentral()
}
dependencies {
testImplementation("io.github.tristankruse:archunitjava:0.1.0")
}
<dependency>
<groupId>io.github.tristankruse</groupId>
<artifactId>archunitjava</artifactId>
<version>0.1.0</version>
<scope>test</scope>
</dependency>
A readable contract
The CLI accepts exact or glob selectors from a strict, bounded properties schema. Unknown keys, escaping paths, duplicates, and executable factories are rejected.
schema=archunitjava.cli.v1
inputs=target/classes
rules=api-boundary
emptySelection=fail
allowIncompleteAnalysis=false
rule.api-boundary.domain=types
rule.api-boundary.mode=no
rule.api-boundary.origins=glob:com.example.api.**
rule.api-boundary.targets=glob:com.example.infrastructure.**
rule.api-boundary.external=ignore
rule.api-boundary.rationale=Keep adapters behind application ports
Use cases
Keep domain code independent, adapters behind ports, and APIs away from persistence details.
Detect cycles across types, packages, slices, layers, and modules with concrete bytecode evidence.
Run policies in JUnit or the CLI and export stable JSON, SARIF, JUnit XML, and graph reports.
Capabilities
The high-level CLI exposes a deliberately bounded dependency-rule subset. The public Java API also provides the lower-level importer, selectors, projections, rules, metrics, snapshots, baselines, and renderers.
Declarations, signatures, annotations, exceptions, calls, fields, constants, lambdas, method references, JARs, and JPMS metadata.
Dependency, naming, location, inheritance, annotation, member access, cycles, layers, slices, modules, and presets.
Target classes and builds are never executed. Inputs, archives, caches, diagrams, and output paths have explicit boundaries.
Ordinary assertions, dynamic cases, and an optional JUnit Platform engine with structured analysis failures.
Console, JSON, SARIF, JUnit XML, DOT, Mermaid, D2, CSV, graph JSON, and self-contained HTML.
Source, cohesion, and dependency metrics; reviewed baselines; graph snapshots; and reproducible performance measurements.
Independent evidence
The separate RAG fixture compiles a layered Java application and consumes ArchUnitJava only as a test-scoped Maven dependency. Its tests prove both acceptance and rejection paths.
Domain code remains independent of infrastructure, and application services depend on domain ports rather than concrete adapters. Both policies must pass.
An unsafe controller reaches into infrastructure and a leaky adapter imports an API DTO. Both must fail with the concrete offending types retained as evidence.
ArchUnitEverything family
ArchUnitJava shares the goal and information structure of its Ruby, Python, and TypeScript siblings while using Java-native Maven, Gradle, JUnit, and Javadocs tooling.