One of Apache Isis' most powerful features is the ability for the UI to combine functionality from domain services into the representation of an entity. The effect is similar to traits or mix-ins in other languages, however the "mixing in" is done at runtime, within the Apache Isis metamodel. In Apache Isis' terminology, we say that the domain service action is contributed to the entity.
Any action of a domain service that has a domain entity type as one of its parameter types will (by default) be contributed. If the service action takes more than one argument, or does not have safe semantics, then it will be contributed as an entity action. If the service action has precisely one parameter type (that of the entity) and has safe semantics then it will be contributed either as a collection or as a property (dependent on whether it returns a collection of a scalar).
Why are contributions so useful? Because the service action will match not on the entity type, but also on any of the entity’s supertypes (all the way up to java.lang.Object
). That means that you can apply the dependency inversion principle to ensure that the modules of your application have acyclic dependencies; but in the UI it can still appear as if there are bidirectional dependencies between those modules. The lack of bidirectional dependencies can help save your app degrading into a big ball of mud.
Finally, note that the layout of contributed actions/collections/properties can be specified using the .layout.json
file (and it is highly recommended that you do so).
26.1. Contributed Actions
26.2. Contributed Collections
-
Write a new domain service (or update the one previously)
-
Write a query-only action accepting exactly 1 arg (a domain entity)
-
returning a collection, list or set
-
For this action:
-
use .layout.json
to position as required
26.3. Contributed Properties
-
As for contributed collections, write a new domain service with a query-only action accepting exactly 1 arg (a domain entity); except:
-
For this action:
-
should be rendered in the UI "as if" a property of the entity
-
use .layout.json
to position as required