[[documentation]]
= Documenting Application Modules

The application module model created via `ApplicationModules` can be used to create documentation snippets for inclusion into developer documentation written in Asciidoc.
Spring Modulith's `Documenter` abstraction can produce two different kinds of snippets:

* C4 and UML component diagrams describing the relationships between the individual application modules
* A so-called __Application Module Canvas__, a tabular overview about the module and the most relevant elements in those (Spring beans, aggregate roots, events published and listened to as well as configuration properties).

Additionally, `Documenter` can produce an aggregating Asciidoc file that includes all existing component diagrams and canvases.

[[component-diagrams]]
== Generating Application Module Component diagrams

The documentation snippets can be generated by handing the `ApplicationModules` instance into a `Documenter`.

.Generating application module component diagrams using `Documenter`
[tabs]
======
Java::
+
[source, java, role="primary"]
----
class DocumentationTests {

  ApplicationModules modules = ApplicationModules.of(Application.class);

  @Test
  void writeDocumentationSnippets() {

    new Documenter(modules)
      .writeModulesAsPlantUml()
      .writeIndividualModulesAsPlantUml();
  }
}
----
Kotlin::
+
[source, kotlin, role="secondary"]
----
class DocumentationTests {
    private val modules = ApplicationModules.of(Application::class.java)

    @Test
    fun writeDocumentationSnippets() {
        Documenter(modules)
            .writeModulesAsPlantUml()
            .writeIndividualModulesAsPlantUml()
    }
}
----
======

The first call on `Documenter` will generate a C4 component diagram containing all modules within the system.

.All modules and their relationships rendered as C4 component diagram
[plantuml, c4-all-modules, svg]
....
top to bottom direction

!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4.puml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Context.puml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml

Container_Boundary("Modulith.Application_boundary", "Application") {
  Component(Modulith.Application.core, "core", "Module", "", $tags="")
  Component(Modulith.Application.catalog, "catalog", "Module", "", $tags="")
  Component(Modulith.Application.inventory, "inventory", "Module", "", $tags="")
  Component(Modulith.Application.order, "order", "Module", "", $tags="")
  Component(Modulith.Application.customer, "customer", "Module", "", $tags="")
}

Rel_D(Modulith.Application.order, Modulith.Application.core, "depends on", $tags="")
Rel_D(Modulith.Application.order, Modulith.Application.customer, "uses", $tags="")
Rel_D(Modulith.Application.catalog, Modulith.Application.core, "depends on", $tags="")
Rel_D(Modulith.Application.inventory, Modulith.Application.order, "listens to", $tags="")
Rel_D(Modulith.Application.inventory, Modulith.Application.catalog, "uses", $tags="")
Rel_D(Modulith.Application.inventory, Modulith.Application.order, "uses", $tags="")
Rel_D(Modulith.Application.inventory, Modulith.Application.core, "uses", $tags="")
Rel_D(Modulith.Application.order, Modulith.Application.catalog, "depends on", $tags="")

SHOW_LEGEND()
....

The second call will create additional diagrams that only include the individual module and the ones they directly depend on the canvas.

.A subset of application modules and their relationships starting from the order module rendered as C4 component diagram
[plantuml, c4-individual-modules, svg]
....
top to bottom direction

!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4.puml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Context.puml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml

Container_Boundary("Modulith.Application_boundary", "Application") {
  Component(Modulith.Application.core, "core", "Module", "", $tags="")
  Component(Modulith.Application.catalog, "catalog", "Module", "", $tags="")
  Component(Modulith.Application.order, "order", "Module", "", $tags="")
  Component(Modulith.Application.customer, "customer", "Module", "", $tags="")
}

Rel_D(Modulith.Application.order, Modulith.Application.core, "depends on", $tags="")
Rel_D(Modulith.Application.order, Modulith.Application.customer, "uses", $tags="")
Rel_D(Modulith.Application.catalog, Modulith.Application.core, "depends on", $tags="")
Rel_D(Modulith.Application.order, Modulith.Application.catalog, "depends on", $tags="")

SHOW_LEGEND()
....

[[component-diagrams.uml]]
=== Using Traditional UML Component Diagrams

If you prefer the traditional UML style component diagrams, tweak the `DiagramOptions` to rather use that style as follows:
[tabs]
======
Java::
+
[source, java, role="primary"]
----
DiagramOptions.defaults()
  .withStyle(DiagramStyle.UML);
----
Kotlin::
+
[source, kotlin, role="secondary"]
----
DiagramOptions.defaults()
  .withStyle(DiagramStyle.UML)
----
======
This will cause the diagrams to look like this:

.All modules and their relationships rendered as UML component diagram
[plantuml, uml-all-modules, svg]
....
skinparam {
  shadowing false
  arrowColor #707070
  actorBorderColor #707070
  componentBorderColor #707070
  rectangleBorderColor #707070
  noteBackgroundColor #ffffff
  noteBorderColor #707070
  defaultTextAlignment center
  wrapWidth 200
  maxMessageSize 100
  componentStyle uml1
}
package "Application" <<Container>> {
  component 4 <<Component: Module>> #dddddd [
    com.acme.commerce.catalog
  ]
  component 3 <<Component: Module>> #dddddd [
    com.acme.commerce.core
  ]
  component 7 <<Component: Module>> #dddddd [
    com.acme.commerce.customer
  ]
  component 5 <<Component: Module>> #dddddd [
    com.acme.commerce.inventory
  ]
  component 6 <<Component: Module>> #dddddd [
    com.acme.commerce.order
  ]
}
4 .[#707070].> 3 : depends on
5 .[#707070].> 4 : uses
5 .[#707070].> 3 : uses
5 .[#707070].> 6 : uses
5 .[#707070].> 6 : listens to
6 .[#707070].> 4 : depends on
6 .[#707070].> 3 : depends on
6 .[#707070].> 7 : uses
....

.A subset of application modules and their relationships starting from the order module rendered as UML component diagram
[plantuml,uml-individiual-module, svg]
....
skinparam {
  shadowing false
  arrowColor #707070
  actorBorderColor #707070
  componentBorderColor #707070
  rectangleBorderColor #707070
  noteBackgroundColor #ffffff
  noteBorderColor #707070
  defaultTextAlignment center
  wrapWidth 200
  maxMessageSize 100
  componentStyle uml1
}
package "Application" <<Container>> {
  component 4 <<Component: Module>> #dddddd [
    com.acme.commerce.catalog
  ]
  component 3 <<Component: Module>> #dddddd [
    com.acme.commerce.core
  ]
  component 7 <<Component: Module>> #dddddd [
    com.acme.commerce.customer
  ]
  component 6 <<Component: Module>> #dddddd [
    com.acme.commerce.order
  ]
}
4 .[#707070].> 3 : depends on
6 .[#707070].> 4 : depends on
6 .[#707070].> 3 : depends on
6 .[#707070].> 7 : uses
....

[[application-module-canvas]]
== Generating Application Module Canvases

The Application Module Canvases can be generated by calling `Documenter.writeModuleCanvases()`:

.Generating application module canvases using `Documenter`
[tabs]
======
Java::
+
[source, java, role="primary"]
----
class DocumentationTests {

  ApplicationModules modules = ApplicationModules.of(Application.class);

  @Test
  void writeDocumentationSnippets() {

    new Documenter(modules)
      .writeModuleCanvases();
  }
}
----
Kotlin::
+
[source, kotlin, role="secondary"]
----
class DocumentationTests {

  private val modules = ApplicationModules.of(Application::class.java)

  @Test
  fun writeDocumentationSnippets() {
    Documenter(modules)
        .writeModuleCanvases()
  }
}
----
======
By default, the documentation will be generated to `spring-modulith-docs` folder in your build system's build folder.
A generated canvas looks like this:

.A sample Application Module Canvas
[cols="1h,4a"]
|===
|Base package
|`com.acme.commerce.inventory`
|Spring components
|_Services_

* `c.a.c.i.InventoryManagement`

_Repositories_

* `c.a.c.i.Inventory`

_Event listeners_

* `c.a.c.i.InternalInventoryListeners` listening to `o.s.m.m.DayHasPassed`, `c.a.c.i.QuantityReduced`
* `c.a.c.i.InventoryOrderEventListener` listening to `c.a.c.o.OrderCanceled`, `c.a.c.o.OrderCompleted`

_Configuration properties_

* `c.a.c.i.InventoryProperties`

_Others_

* `c.a.c.i.InventoryItemCreationListener`
|Aggregate roots
|* `c.a.c.i.InventoryItem`
|Published events
|* `c.a.c.i.QuantityReduced` created by:
** `c.a.c.i.InventoryItem.decreaseQuantity(…)`
* `c.a.c.i.StockShort` created by:
** `c.a.c.i.InternalInventoryListeners.on(…)`

|Events listened to
|* `c.a.c.o.OrderCompleted`
* `c.a.c.o.OrderCanceled`
|Properties
|* `acme.commerce.inventory.restock-threshold` -- `c.a.c.c.Quantity`. The threshold at which a `InventoryEvents.StockShort` is supposed to be triggered during inventory updates.
|===

It consists of the following sections:

* __The application module's base package.__
* __The Spring beans exposed by the application module, grouped by stereotype.__ -- In other words, beans that are located in either the API package or any xref:fundamentals.adoc#modules.named-interfaces[named interface package].
This will detect component stereotypes defined by https://github.com/xmolecules/jmolecules/tree/main/jmolecules-architecture[jMolecules architecture abstractions], but also standard Spring stereotype annotations.
* __Exposed aggregate roots__ -- Any entities that we find repositories for or explicitly declared as aggregate via jMolecules.
* __Application events published by the module__ -- Those event types need to be demarcated using jMolecules `@DomainEvent` or implement its `DomainEvent` interface.
* __Application events listened to by the module__ -- Derived from methods annotated with Spring's `@EventListener`, `@TransactionalEventListener`, jMolecules' `@DomainEventHandler` or beans implementing `ApplicationListener`.
* __Configuration properties__ -- Spring Boot Configuration properties exposed by the application module.
Requires the usage of the `spring-boot-configuration-processor` artifact to extract the metadata attached to the properties.

[[aggregating-document]]
== Generating an Aggregating Document

When using `Documenter.writeDocumentation(…)` an `all-docs.adoc` file will be generated, linking all generated diagrams and Application Module Canvases.
We can manually generate the aggregating document by calling `Documenter.writeAggregatingDocument()`:

.Generating an aggregating document using `Documenter`
[tabs]
======
Java::
+
[source, java, role="primary"]
----
class DocumentationTests {

  ApplicationModules modules = ApplicationModules.of(Application.class);

  @Test
  void writeDocumentationSnippets() {

    new Documenter(modules)
        .writeAggregatingDocument();
  }
}
----
Kotlin::
+
[source, kotlin, role="secondary"]
----
class DocumentationTests {

  private val modules = ApplicationModules.of(Application::class.java)

  @Test
  fun writeDocumentationSnippets() {
    Documenter(modules)
        .writeAggregatingDocument()
  }
}
----
======

The aggregating document will include any existing application module component diagrams and application module canvases.
If there are none, then this method will not produce an output file.
