| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="utf-8"> |
| <meta name="viewport" content="width=device-width,initial-scale=1"> |
| <title>Modules :: Apache Isis</title> |
| <link rel="canonical" href="https://isis.apache.org/userguide/2.0.0-M3/fun/overview/modules.html"> |
| <meta name="generator" content="Antora 2.2.0"> |
| <link rel="stylesheet" href="../../../../_/css/site.css"> |
| <link rel="stylesheet" href="../../../../_/css/site-custom.css"> |
| <link href="https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,700,700i|Raleway:300,400,500,700,800|Montserrat:300,400,700" rel="stylesheet"> |
| <link rel="home" href="https://isis.apache.org" title="Apache Isis"> |
| </head> |
| <body class="article"> |
| <header class="header"> |
| <nav class="navbar"> |
| <div class="navbar-brand"> |
| <a class="navbar-item" href="https://isis.apache.org"> |
| <span class="icon"> |
| <img src="../../../../_/img/isis-logo-48x48.png"></img> |
| </span> |
| <span>Apache Isis</span> |
| </a> |
| <button class="navbar-burger" data-target="topbar-nav"> |
| <span></span> |
| <span></span> |
| <span></span> |
| </button> |
| </div> |
| <div id="topbar-nav" class="navbar-menu"> |
| <a class="navbar-end"> |
| <div class="navbar-item has-dropdown is-hoverable"> |
| <a class="navbar-link" href="#">Quick Start</a> |
| <div class="navbar-dropdown"> |
| <span class="navbar-item navbar-heading">Starter Apps</span> |
| <a class="navbar-item" href="../../../../docs/latest/starters/helloworld.html">Hello World</a> |
| <a class="navbar-item" href="../../../../docs/latest/starters/simpleapp.html">Simple App</a> |
| <hr class="navbar-divider"/> |
| <span class="navbar-item navbar-heading">Demos & Tutorials</span> |
| <a class="navbar-item" href="../../../../docs/latest/demo/about.html">Demo App</a> |
| <a class="navbar-item" href="https://danhaywood.gitlab.io/isis-petclinic-tutorial-docs/petclinic/1.16.2/intro.html">Petclinic (tutorial)</a> |
| <hr class="navbar-divider"/> |
| <span class="navbar-item navbar-heading">Resources</span> |
| <a class="navbar-item" href="../../../../docs/latest/resources/cheatsheet.html">Cheatsheet</a> |
| <a class="navbar-item" href="../../../../docs/latest/resources/icons.html">Icons</a> |
| </div> |
| </div> |
| <div class="navbar-item has-dropdown is-hoverable"> |
| <a class="navbar-link" href="#">Guides</a> |
| <div class="navbar-dropdown"> |
| <span class="navbar-item navbar-heading">Development</span> |
| <a class="navbar-item" href="../../../../setupguide/latest/about.html">Setup Guide</a> |
| <hr class="navbar-divider"/> |
| <span class="navbar-item navbar-heading">Core</span> |
| <a class="navbar-item" href="../../../../userguide/latest/about.html">User Guide</a> |
| <a class="navbar-item" href="../../../../refguide/latest/about.html">Reference Guide</a> |
| <a class="navbar-item" href="../../../../testing/latest/about.html">Testing Guide</a> |
| </div> |
| </div> |
| <div class="navbar-item has-dropdown is-hoverable"> |
| <a class="navbar-link" href="#">Libraries</a> |
| <div class="navbar-dropdown"> |
| <span class="navbar-item navbar-heading">For Use in Apps</span> |
| <a class="navbar-item" href="../../../../subdomains/latest/about.html">Subdomain Libraries</a> |
| <a class="navbar-item" href="../../../../valuetypes/latest/about.html">Value Types</a> |
| <hr class="navbar-divider"/> |
| <span class="navbar-item navbar-heading">Integrate between Apps</span> |
| <a class="navbar-item" href="../../../../mappings/latest/about.html">Bounded Context Mapping Libraries</a> |
| <hr class="navbar-divider"/> |
| <span class="navbar-item navbar-heading">Other</span> |
| <a class="navbar-item" href="../../../../incubator/latest/about.html">Incubator</a> |
| <a class="navbar-item" href="../../../../legacy/latest/about.html">Legacy</a> |
| </div> |
| </div> |
| <div class="navbar-item has-dropdown is-hoverable"> |
| <a class="navbar-link" href="#">Components</a> |
| <div class="navbar-dropdown"> |
| <span class="navbar-item navbar-heading">Viewers</span> |
| <a class="navbar-item" href="../../../../vw/latest/about.html">Wicket UI</a> |
| <a class="navbar-item" href="../../../../vro/latest/about.html">Restful Objects (REST)</a> |
| <hr class="navbar-divider"/> |
| <span class="navbar-item navbar-heading">Security</span> |
| <a class="navbar-item" href="../../../../security/latest/about.html">Security Guide</a> |
| <hr class="navbar-divider"/> |
| <span class="navbar-item navbar-heading">Persistence</span> |
| <a class="navbar-item" href="../../../../pjdo/latest/about.html">DataNucleus (JDO)</a> |
| <hr class="navbar-divider"/> |
| <span class="navbar-item navbar-heading">Extensions</span> |
| <a class="navbar-item" href="../../../../extensions/latest/about.html">Extensions Catalog</a> |
| </div> |
| </div> |
| <div class="navbar-item has-dropdown is-hoverable"> |
| <a class="navbar-link" href="#">Support</a> |
| <div class="navbar-dropdown"> |
| <span class="navbar-item navbar-heading">Contact</span> |
| <a class="navbar-item" href="../../../../docs/latest/support/slack-channel.html">Slack</a> |
| <a class="navbar-item" href="../../../../docs/latest/support/mailing-list.html">Mailing Lists</a> |
| <a class="navbar-item" href="https://issues.apache.org/jira/browse/ISIS">JIRA</a> |
| <a class="navbar-item" href="https://stackoverflow.com/questions/tagged/isis">Stack Overflow</a> |
| <hr class="navbar-divider"/> |
| <span class="navbar-item navbar-heading">Releases</span> |
| <a class="navbar-item" href="../../../../docs/latest/downloads/how-to.html">Downloads</a> |
| <a class="navbar-item" href="../../../../relnotes/latest/about.html">Release Notes</a> |
| <a class="navbar-item" href="../../../../docs/latest/archive/1-x.html">Archive (1.x)</a> |
| <hr class="navbar-divider"/> |
| <span class="navbar-item navbar-heading">Framework</span> |
| <a class="navbar-item" href="../../../../conguide/latest/about.html">Contributors' Guide</a> |
| <a class="navbar-item" href="../../../../comguide/latest/about.html">Committers' Guide</a> |
| <a class="navbar-item" href="../../../../core/latest/about.html">Core Design</a> |
| </div> |
| </div> |
| <div class="navbar-item has-dropdown is-hoverable"> |
| <a class="navbar-link" href="#">ASF</a> |
| <div class="navbar-dropdown"> |
| <a class="navbar-item" href="http://www.apache.org/">Apache Homepage</a> |
| <a class="navbar-item" href="https://www.apache.org/events/current-event">Events</a> |
| <a class="navbar-item" href="https://www.apache.org/licenses/">Licenses</a> |
| <a class="navbar-item" href="https://www.apache.org/security/">Security</a> |
| <a class="navbar-item" href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a> |
| <a class="navbar-item" href="https://www.apache.org/foundation/thanks.html">Thanks</a> |
| <hr class="navbar-divider"/> |
| <a class="navbar-item" href="https://whimsy.apache.org/board/minutes/Isis.html">PMC board minutes</a> |
| </div> |
| </div> |
| <a class="navbar-item" href="../../../../docs/latest/about.html"> |
| <span class="icon"> |
| <img src="../../../../_/img/home.png"></img> |
| </span> |
| </a> |
| </div> |
| </div> |
| </nav> |
| </header> |
| <div class="body "> |
| <div class="nav-container" data-component="userguide" data-version="2.0.0-M3"> |
| <aside class="nav"> |
| <div class="panels"> |
| <div class="nav-panel-pagination"> |
| <a class="page-previous disabled" rel="prev" href="" title=""><span></span></a> |
| <a class="page-next disabled" rel="next" |
| href="" title=""><span></span></a> |
| <!-- |
| page.parent doesn't seem to be set... |
| <a class="page-parent disabled" rel="prev" href="" title=""><span></span></a> |
| --> |
| </div> |
| <div class="nav-panel-menu is-active" data-panel="menu"> |
| <nav class="nav-menu"> |
| <h3 class="title"><a href="../../about.html">User Guide</a></h3> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="0"> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../concepts-patterns.html">Concepts & Patterns</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../overview.html">Overview</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../domain-entities-and-services.html">Domain Entities & Services</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../object-members.html">Object Members</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../ui.html">UI Layout & Hints</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../business-rules.html">Business Rules</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../drop-downs-and-defaults.html">Drop downs and Defaults</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../meta-annotations.html">Meta-annotations</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../view-models.html">View Models</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../mixins.html">Mixins</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <a class="nav-link" href="../modules.html">Modules</a> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <button class="nav-item-toggle"></button> |
| <a class="nav-link" href="../../btb/about.html">Beyond the Basics</a> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../btb/i18n.html">i18n</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../btb/headless-access.html">Headless Access</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../btb/hints-and-tips.html">Hints-n-Tips</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../btb/programming-model.html">Programming Model</a> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="1"> |
| <button class="nav-item-toggle"></button> |
| <span class="nav-text">Extensions</span> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../flyway/about.html">Flyway</a> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </nav> |
| </div> |
| <div class="nav-panel-explore" data-panel="explore"> |
| <div class="context"> |
| <span class="title">User Guide</span> |
| <span class="version">2.0.0-M3</span> |
| </div> |
| <ul class="components"> |
| <li class="component"> |
| <span class="title"> </span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../../docs/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">BC Mappings Catalog</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../../mappings/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Committers' Guide</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../../comguide/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Contributors' Guide</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../../conguide/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Design Docs</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../../core/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Extensions Catalog</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../../extensions/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Incubator Catalog</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../../incubator/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">JDO/DataNucleus</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../../pjdo/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Legacy Catalog</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../../legacy/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Reference Guide</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../../refguide/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Release Notes</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../../relnotes/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Restful Objects Viewer</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../../vro/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Security Guide</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../../security/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Setup Guide</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../../setupguide/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Subdomains Catalog</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../../subdomains/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Testing Guide</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../../testing/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component is-current"> |
| <span class="title">User Guide</span> |
| <ul class="versions"> |
| <li class="version is-current is-latest"> |
| <a href="../../about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Value Types Catalog</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../../valuetypes/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| <li class="component"> |
| <span class="title">Wicket Viewer</span> |
| <ul class="versions"> |
| <li class="version is-latest"> |
| <a href="../../../../vw/2.0.0-M3/about.html">2.0.0-M3</a> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </aside> |
| </div> |
| <main role="main"> |
| <div class="toolbar" role="navigation"> |
| <button class="nav-toggle"></button> |
| <a href="../../../../docs/2.0.0-M3/about.html" class="home-link"></a> |
| <nav class="breadcrumbs" aria-label="breadcrumbs"> |
| <ul> |
| <li><a href="../../about.html">User Guide</a></li> |
| <li><a href="modules.html">Modules</a></li> |
| </ul> |
| </nav> |
| <div class="edit-this-page"><a href="https://github.com/apache/isis/edit/2.0.0-M3/api/adoc/userguide/modules/fun/pages/overview/modules.adoc">Edit</a></div> |
| </div> |
| <article class="doc"> |
| <a name="section-top"></a> |
| <h1 class="page">Modules</h1> |
| <div id="preamble"> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>Enabling and ensuring modularity is a <a href="../concepts-patterns.html#modular" class="page">key principle</a> for the Apache Isis framework. |
| Modularity is the only way to ensure that a complex application domain does not over time degenerate into the infamous "big ball of mud", software that is difficult, dangerous and expensive to change.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Modules chunk up the overall application into smaller pieces, usually a pacakge and subpackages. |
| The smaller pieces can be either tiers (presentation / domain / persistence) or functional architectural layers (eg customer vs orders vs products vs invoice etc). |
| Because Apache Isis takes care of the presentation and persistence tiers, modules for us focuses just on the important bit: considering how the functionality within the domain model should be broken up into modules, and determining the dependencies between those modules.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="rules-of-thumb"><a class="anchor" href="#rules-of-thumb"></a>Rules of Thumb</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>The two main rule of thumbs for dependencies are:</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic"> |
| <li> |
| <p>there should be no cyclic dependencies (the module dependencies should form an acyclic graph), and</p> |
| </li> |
| <li> |
| <p>unstable modules should depend upon stable modules, rather than the other way around.</p> |
| </li> |
| </ol> |
| </div> |
| <div class="paragraph"> |
| <p>By "unstable" we don’t mean buggy, rather this relates to its likelihood to change its structure or behaviour over time: in other words its stability as a core set of concepts upon which other stuff can depend. |
| Reference data (calendars, tax rates, lookups etc) are generally stable, as are "golden" concept such as counterparties / legal entities or financial accounts. |
| Transactional concepts such as invoices or agreements is perhaps more likely to change. |
| But this stuff is domain specific.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="decoupling"><a class="anchor" href="#decoupling"></a>Decoupling</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>Having broken up a domain into multiple modules, there is still a need for higher level modules to use lower level modules, and the application must still appear as a coherent whole to the end-user.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The key features that Apache Isis provides to support this are:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>dependency injection of services</p> |
| <div class="paragraph"> |
| <p>Both <a href="../../../../refguide/2.0.0-M3/applib-svc/about.html" class="page">framework-defined</a> domain services and application-defined services (eg repositories and factories) are injected everywhere, using the <code>@javax.inject.Inject</code> annotation (Spring’s <code>@Autowired</code> can also be used).</p> |
| </div> |
| <div class="paragraph"> |
| <p>By "everywhere", we mean not just into domain services, but <em>also</em> injected into domain entities and view models. |
| This enables us to implement behaviourally complete domain objects (if we so wish).</p> |
| </div> |
| </li> |
| <li> |
| <p><a href="../overview.html#mixins" class="page">mixins</a> that allow functionality defined in one module to appear (in the UI) to be provided by some other module.</p> |
| <div class="paragraph"> |
| <p>For example, a <em>Document</em> module might allow <code>Document</code> objects to be attached to any arbitrary domain object (such as <code>Order</code> or <code>Customer</code>) in other modules. |
| A mixin would allow the UI for a <code>Customer</code> to also display these attached <code>Document</code>s, even though the <em>Customer</em> module would have no knowledge of/dependency on the <em>Workflow</em> module. |
| (More on this example <a href="../overview.html#inverting-dependencies" class="page">below</a>).</p> |
| </div> |
| <div class="paragraph"> |
| <p>Dependencies are also injected into mixins. |
| A common technique is to factor out from domain objects into mixins and then generalise.</p> |
| </div> |
| </li> |
| <li> |
| <p>the internal <a href="../../../../refguide/2.0.0-M3/applib-svc/EventBusService.html" class="page">event bus</a> allows modules to influence other modules.</p> |
| <div class="paragraph"> |
| <p>A subscriber in one module can subscribe to events emitted by domain objects in another module. |
| These events can affect both the UI (eg hiding or disabling <a href="../overview.html#object-members" class="page">object members</a>, or allowing or vetoing interactions).</p> |
| </div> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>A good example of this last is supporting (what in an RDBMS we would call) referential integrity. |
| Suppose the <code>customers</code> module has a <code>Customer</code> object and a <code>EmailAddress</code> object, with a customer having a collection of email addresses. |
| A <code>communications</code> module might then use those email addresses to create <code>EmailCommunication</code>s.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the <code>customers</code> module wants to delete an <code>EmailAddress</code> then the <code>communications</code> module will probably want to veto this because they are "in use" by those <code>EmailCommunication</code>s. |
| Or, it might conceivably perform a cascade delete of all associated communications. |
| Either way, the <code>communications</code> module receives an internal event representing the intention to delete the <code>EmailAddress</code>. |
| It can then act accordingly, either vetoing the interaction or performing the cascade delete. |
| The <code>customers</code> module for its part does not know anything about this other module.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="inverting-dependencies"><a class="anchor" href="#inverting-dependencies"></a>Inverting Dependencies</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>If we get the dependencies wrong (that is, our initial guess on stability is proven incorrect over time) then there are a couple of techniques we can use:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>use the <a href="https://en.wikipedia.org/wiki/Dependency_inversion_principle">dependency inversion principle</a> to introduce an abstraction representing the dependency.</p> |
| </li> |
| <li> |
| <p>move functionality, eg by factoring it out into <a href="../overview.html#mixins" class="page">mixins</a> into the other module or into a third module which depends on the other modules that had a bidirectional relationship</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Mixins in particular allow dependencies to be inverted, so that the dependencies between modules can be kept acyclic and under control.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example, suppose that we send out <code>Invoice</code>s to <code>Customer</code>s. |
| We want the invoices to know about customers, but not vice versa. |
| We could surface the set of invoices for a customer using a <code>Customer_invoices</code> mixin:</p> |
| </div> |
| <div class="imageblock plantuml"> |
| <div class="content"> |
| <img src="http://www.plantuml.com/plantuml/png/ZP9DQyCm38Rl_XKcby6WPUTIGbaEOx33RcEduTeY4V4Nbf8kZFttcJNfokQjyr5wtbUof1snIZmuApeq8C55dgG3juT4ukepve2xO4W8wj57bPIJsYeY-IPaVhTAzsqAWpTDi25jjmP8rxLi9kNBG8oSym_OTdoN07wX72xG8_g-pAHWOQ6UmTfmA7F4IJ6qKsQVEcGeKohYtm1T0j0p9A_isVUcCZagEy39hCo0P-Jf7wCQ4Guk6B2N9-Rm5VstaRqB4JEdMf3enu0QvjKUrzmCnC51UfcJ94ysPzJzh3mkBdl-bArMjQnkrjVL0c-MUlJLWPvbLEn1pjTJzb-dN669RsIbW-U4-u5paaCbTk1DFlKF" alt="diagram"> |
| </div> |
| <div class="title">Figure 1. <code>invoices</code> module contributes to <code>customers</code></div> |
| </div> |
| <div class="paragraph"> |
| <p>In the UI, when rendering a <code>Customer</code>, we would also be presented with the associated set of <code>Invoice</code>s.</p> |
| </div> |
| <div class="paragraph"> |
| <p>We can also use mixins for dependencies that are in the other direction. |
| For example, suppose we have a mechanism to attach <code>Document</code>s to arbitrary domain objects. |
| The documents module does not depend on any other modules, but provides a <code>DocumentHolder</code> marker interface. |
| We can therefore attach documents to a <code>Customer</code> by having <code>Customer</code> implement this marker interface:</p> |
| </div> |
| <div class="imageblock plantuml"> |
| <div class="content"> |
| <img src="http://www.plantuml.com/plantuml/png/ZPFBQiCm44Nt-WhXJQ5WqtK88JI5Tj55TwMRbeaqjONrCD8egIdzzuh4TXuuJhISEVEuLz8o47YAHhDAIUHe6cgvGRD67zZTBcQGAYS3Ow5MjW4FXWiD8V1VnjDv156NtaKhLquxFvzB36AnuAiMx3ZGD9JohwgiwDaZNg2Cwg4tPUjnnZkDFVM1MhljE1V80s7P9lQzKeJZ53Hg6WZN06K9lGLz9AyT9pUW8mxDnXcqfAYzmQgDmgrn4lLrnupwKVRCiZ_6ciH1YLmw4KsQsr_kJj0t2EHFNUR5QOcUzzxlgFrpE2M-3gs6gPTX809HzS792juzeBJsnOcvp1SyUoYA-soecnt4JHGMEbMUfcSy4ywIL-j863YvZ4rlVsEJmNGH0pcJFbnd-bxlgeiUwHr2UIpopxC9R8bMfe_y3m00" alt="diagram"> |
| </div> |
| <div class="title">Figure 2. <code>customers</code> depends upon contributions of <code>documents</code></div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="defining-modules"><a class="anchor" href="#defining-modules"></a>Defining Modules</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>In the context of Java applications, modularity is a rather overloaded term. |
| We have Maven modules, Java 9 modules and we also have Spring <a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Configuration.html"><code>@Configuration</code></a>s, which define a set of domain services.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In the context of Apache Isis, a module is actually the last of these, a Spring module.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <a href="../../../../docs/2.0.0-M3/starters/simpleapp.html" class="page">simpleapp starter app</a> provide some structure and illustrates the idioms. |
| To summarise:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>by convention, we have one <code>@Configuration</code> module per Maven module.</p> |
| <div class="paragraph"> |
| <p>This is at the root package of the maven module.</p> |
| </div> |
| </li> |
| <li> |
| <p>all of the domain classes (domain objects and services) are part of that Maven module.</p> |
| <div class="paragraph"> |
| <p>All are annotated or meta-annotated with Spring’s <a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/stereotype/Component.html"><code>@Component</code></a> annotation, and Spring’s <a href="https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/ComponentScan.html"><code>@ComponentScan</code></a> is used to discover these from the classpath.</p> |
| </div> |
| </li> |
| <li> |
| <p>Spring’s <a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Import.html"><code>@Import</code></a> is used to express a dependency between each "configuration" module.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>By convention, we have just one Spring module to each Maven module. |
| This means that the dependencies between Maven modules (using <code><dependency></code> are mirrored in the Spring module’s <code>@Import</code> statements). |
| We can therefore rely on Maven to ensure there are no cyclic dependencies: the application simply won’t compile if we introduce a cycle.</p> |
| </div> |
| <div class="admonitionblock tip"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-tip" title="Tip"></i> |
| </td> |
| <td class="content"> |
| <div class="paragraph"> |
| <p>Details on how to actually define modules can be found <a href="../modules.html" class="page">here</a>.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p>If the above convention is too officious,then you could choose to have multiple Spring modules per Maven module, but you will need to watch out for cycles.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In such cases (proprietary) tools such as <a href="https://structure101.com/">Structure 101</a> can be used to help detect and visualize such cycles. |
| Or, (open source) libraries such as <a href="https://www.archunit.org/">ArchUnit</a> or <a href="https://jqassistant.org/">jQAssistant</a> can help enforce architectural layering to prevent the issue arising in the first place. |
| (These tools can enforce other conventions, too, so are well worth exploring).</p> |
| </div> |
| </div> |
| </div> |
| </article> |
| <aside class="article-aside toc" role="navigation"> |
| <p class="toc-title">On this page</p> |
| <div id="article-toc"></div> |
| </aside> |
| </main> |
| </div> |
| <footer class="footer"> |
| <div class="content"> |
| <div class="copyright"> |
| <p> |
| Copyright © 2010~2020 The Apache Software Foundation, licensed under the Apache License, v2.0. |
| <br/> |
| Apache, the Apache feather logo, Apache Isis, and the Apache Isis project logo are all trademarks of The Apache Software Foundation. |
| </p> |
| </div> |
| <div class="revision"> |
| <p>Revision: SNAPSHOT</p> |
| </div> |
| </div> |
| </footer> |
| <script src="../../../../_/js/site.js"></script> |
| <script async src="../../../../_/js/vendor/highlight.js"></script> |
| <script src="../../../../_/js/vendor/jquery-3.4.1.min.js"></script> |
| <script src="../../../../_/js/vendor/jquery-ui-1.12.1.custom.widget-only.min.js"></script> |
| <script src="../../../../_/js/vendor/jquery.tocify.min.js"></script> |
| |
| <script> |
| $(function() { |
| $("#article-toc").tocify( { |
| showEffect: "slideDown", |
| hashGenerator: "pretty", |
| hideEffect: "slideUp", |
| selectors: "h2, h3", |
| scrollTo: 120, |
| smoothScroll: true, |
| theme: "jqueryui", |
| highlightOnScroll: true |
| } ); |
| }); |
| </script> |
| </body> |
| </html> |