Modeling Layered Domains with UML Class Diagrams, Stereotypes, and Interfaces in PlantUML
Learn how to express a layered domain model using UML class diagrams with <<entity>>, <<boundary>>, and <<control>> stereotypes plus interfaces in PlantUML, including a ready‑to‑render example and practical limits.
30 Aug 2025, 02:54 UTC

Why a stereotyped class diagram works for layered domain models
When a domain needs clear separation between business entities, system boundaries, and orchestration logic, a UML class diagram that combines <<entity>>, <<boundary>>, and <<control>> stereotypes with explicit interfaces gives an immediate, tool‑readable contract. The diagram becomes a single source of truth that both architects and developers can reference, and many code generators can translate the stereotypes into Java interfaces, Spring annotations, or similar artifacts.
Mechanism: stereotypes → metamodel → generated code
PlantUML (and most UML tools) maintain an internal metamodel where each stereotype is a tagged element. When a generator reads the XMI or PlantUML AST, it looks for the stereotype names and applies a mapping table—for example, <<entity>> → @Entity, <<boundary>> → @RestController, <<control>> → @Service. Interfaces declared in the diagram become Java interfaces that the generated classes implement. This mapping is configurable but works out‑of‑the‑box for the three core stereotypes.
Worked PlantUML example
Save the following snippet as domain.puml and render it with PlantUML (requires a JVM and the PlantUML JAR). No elevated permissions are needed; the command runs in the user’s working directory.
@startuml
package "com.example.order" {
interface IOrderRepository <<control>>
interface INotificationService <<boundary>>
class Order <<entity>> {
+id: UUID
+status: OrderStatus
+place()
}
class OrderService <<control>> {
+createOrder(customerId: UUID): Order
}
class EmailNotifier <<boundary>> {
+send(order: Order)
}
OrderService ..> IOrderRepository : uses
OrderService ..> INotificationService : uses
EmailNotifier ..|> INotificationService : implements
Order ..> IOrderRepository : persisted by
}
@enduml
Command to render (Linux/macOS/Windows PowerShell):
java -jar plantuml-1.2024.6.jar domain.puml
Expected check: a PNG/SVG named domain.png appears showing three packages, the stereotypes rendered as guillemets, and the interface realization arrows. If the file is missing, verify Java is on PATH and the JAR version matches the PlantUML syntax used.
Stereotype‑to‑annotation mapping table (example)
| Stereotype | Typical Java annotation | Generator hint |
|---|---|---|
<<entity>> | @Entity (JPA) | Generates a persistent class with an @Id field. |
<<boundary>> | @RestController or @Component | Marks a class that exposes an external API. |
<<control>> | @Service or @Component | Denotes orchestration logic, often transactional. |
Limits you should plan for
- Non‑executable artifact – the diagram cannot be run; it only documents intent.
- Tool lock‑in – PlantUML‑specific syntax (e.g.,
<<entity>>) may not import cleanly into Enterprise Architect, Visual Paradigm, or other UML suites. - Readability ceiling – diagrams exceeding ~20 classes become cluttered. Split into sub‑diagrams per bounded context or use
packagenesting as shown above. - Generator drift – if the code generator’s mapping table changes, the diagram may no longer reflect the produced code unless regenerated.
Common mistakes and how to avoid them
- Over‑decorating – adding stereotypes to every utility class (e.g.,
<<control>>on a simple validator). Reserve stereotypes for architectural roles only. - Ignoring multiplicities – omit
1..*or0..1on associations; generators may assume default 1..1 and produce incorrect collections. - Diagram‑code drift – update the diagram in the same pull request that changes the corresponding source files. Enforce with a CI step that runs a diff between the model XMI and the generated sources.
Practical verification checklist
- Open
domain.pumlin the PlantUML online server or local JAR and confirm the visual output matches the intended layers. - If a generator (e.g.,
uml-to-javaMaven plugin) is configured, runmvn generate-sourcesand inspect the producedOrder.java,OrderService.java, andEmailNotifier.javafor the expected annotations. - Run the project’s unit tests to ensure the generated interfaces compile and the dependency arrows (uses, implements) are satisfied.
When to split the diagram
If the package count grows beyond three or the class count per package exceeds ten, create separate .puml files per bounded context (e.g., order.puml, payment.puml) and include them with !include in a master diagram. This keeps each file under the readability threshold and lets teams own their sub‑models independently.
Bottom line
A UML class diagram enriched with <<entity>>, <<boundary>>, <<control>> stereotypes and explicit interfaces gives a concise, generator‑friendly contract for layered domain models. The PlantUML snippet above renders instantly, maps cleanly to common Java annotations, and stays maintainable as long as you respect the ~20‑class readability limit and keep the diagram synchronized with the code base.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.