AI Unified Process plugin for the Angular/JPA stack
92
91%
Does it follow best practices?
Impact
99%
0.99xAverage score across 3 eval scenarios
Low
Low-risk findings worth noting
This is a lookup used by /implement, /flyway-migration, and /spring-boot-test before
writing any backend code. Its job is to answer one question: does this Spring Boot
backend split hexagonal layers across separate Maven modules, or is it one flat module?
Never assume — always run this detection first, because generating flat-style code into a
hexagonal reactor (or vice versa) breaks the project's module dependency direction (e.g. a
JPA @Entity accidentally placed in a domain module that has zero framework
dependencies).
Read the backend's root pom.xml. If it is a thin aggregator — <packaging>pom</packaging>,
a <modules> list pointing at sibling directories, no Java source of its own (this is common
when a repo's outermost pom.xml aggregates both a frontend placeholder module and a backend
directory) — descend into whichever listed module itself declares further <modules>, and
treat that nested pom.xml's module list as the candidate reactor. Don't stop at the
outermost aggregator if it's just a wrapper.
Match each module's directory name / artifactId (case-insensitive substring, after
stripping any common project-name prefix) against these buckets:
| Bucket | Keywords |
|---|---|
| Domain | domain |
| Business/Application | business, application, service, core |
| Persistence adapter | postgres, jpa, persistence, db, infra*, data |
| Inbound adapter | api, web, rest, controller |
| Composition root | app, bootstrap, launcher, main, runner |
Classify as Hexagonal Multi-Module only if a Domain-bucket module is present and at least two of {Business/Application, Persistence adapter, Inbound adapter} are also present. Never switch pattern on a single keyword match alone.
Otherwise → Flat Single-Module. Say so explicitly in your response ("found N modules
but couldn't confidently classify them as a layered split — implementing as a flat pattern
into <module>; let me know if this project follows a different layered convention") rather
than silently picking one.
Find one already-implemented entity/feature across the classified modules and copy its exact shape — don't generate purely from this heuristic in isolation:
port/port.out subpackage? Match
whichever exists.@Service class directly from the controller, matching the existing
asymmetric convention.XxxDTO.fromBusiness(domainObject)), or a separate mapper class? Match whichever exists.
It's normal for the request-side and response-side to use different approaches — copy
each side's own convention rather than unifying them into one.If the reactor is classified as Hexagonal Multi-Module but has no existing feature to copy, fall back to this documented default rather than inventing textbook full hexagonal:
port
subpackage).<Feature>Controller (inbound adapter module)
→ <Feature>Service (business module, concrete class — no interface)
→ <Feature>Factory / mapper (business module — request DTO → domain, if the project uses one)
→ <Feature>Repository (interface) (business module — the one real port)
→ <Feature>RepositoryImpl (persistence adapter module, implements the port)
→ <Feature>EntityConverter (persistence adapter module — domain → JPA entity)
→ <Feature>JpaRepository (persistence adapter module — Spring Data JpaRepository<Entity, ID>)
→ <Feature>Converter (persistence adapter module — JPA entity → domain, back-conversion)
→ <Feature>DTO.fromBusiness(...) (business module — domain → response DTO)
← ResponseEntity<...DTO>Never let a JPA @Entity, Spring annotation, or persistence import leak into the domain
module — that module's whole purpose is to have zero framework dependencies.