= Mixins

:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
:page-partial:


As described in the xref:userguide:fun:overview.adoc#mixins[overview], a mixin acts like a trait or extension method, allowing one module to contribute behaviour or derived state to another object.
This is a *very powerful feature*, but at the same time is  easy to use.

Under the covers, all mixins are basically actions that use the mixee as one of their arguments.

* if the mixin action takes some arguments (apart from the mixee), then it will only ever be rendered as an action
* if the mixin action is not query-only, then again it will only ever be rendered as an action
* if the mixin action is query-only and takes no arguments, then it can either be rendered as an action or as some derived state
** if as an action, then it's basically a query to find and return some related info (eg "most recent order", "last 5 orders")
** if as derived state, then it will be rendered as a property (if it returns a scalar), or as a collection (if it returns a vector).


Accordingly, a mixin can be defined using the xref:refguide:applib:index/annotation/Action.adoc[@Action], xref:refguide:applib:index/annotation/Property.adoc[@Property] or xref:refguide:applib:index/annotation/Collection.adoc[@Collection] annotations, but defined at the domain class level rather than at the method level.

The mixin is expected to follow the naming convention `SomeType_mixinName`, with the name of the contributed member being contributed is inferred from the name of the class itself, being everything after the last '_'.
For example, if the mixin is called `DocumentHolder_documents`, then the mixee is `DocumentHolder` interface, and `documents` is the name of the contributed collection.

This example also hints at why mixins are so powerful: the mixee's type is usually an interface, not a concrete class.
Thus, any class that implements `DocumentHolder`, eg `Customer` or `Order`, will be contributed to.

== Contributed Collection

The example below shows in more detail how to contribute a collection, using xref:refguide:applib:index/annotation/Collection.adoc[@Collection].
The method is expected to be called "coll":

[source,java]
----
@Collection                                     // <.>
@RequiredArgsConstructor                        // <.>
public class DocumentHolder_documents {

    private final DocumentHolder holder;

    public List<Document> coll() { /* ... */ }  // <.>
        ...
    }
    public boolean hideColl() { /* ... */ }     // <.>
}
----
<.> indicates this is a collection mixin (that contributes its method as an association) with method name 'coll'
<.> mixee is injected into the mixin
<.> method (which must be called "coll") must accept no arguments, be query-only, and return a collection
<.> supporting methods (discussed in xref:business-rules.adoc[business rules]) follow the usual naming conventions
(Because the collection is derived/read-only, the only supporting method that is relevant is `hideColl()`).

The above will result in a contributed collection "documents" for all types that implement/extend from `DocumentHolder`.



== Contributed Property

Contributed properties can likewise be defined using xref:refguide:applib:index/annotation/Property.adoc[@Property]; this implies a method called "prop":

[source,java]
----
@Property                                                       // <.>
@RequiredArgsConstructor                                        // <.>
public class DocumentHolder_mostRecentDocument {

    private final DocumentHolder holder;

    public Document prop() {                                    // <.>
        ...
    }
    public boolean hiderProp() { /* ... */ }                    // <.>
}
----
<.> indicates this is a property mixin (that contributes its method as an association) with method name 'prop'
<.> mixee is injected into the mixin
<.> method (which must be called "prop") must accept no arguments, be query-only, and return a scalar value
<.> supporting methods (discussed in xref:business-rules.adoc[business rules]) follow the usual naming conventions
(Because the property is derived/read-only, the only supporting method that is relevant is `hideProp()`).

This contributes a property called "mostRecentDocument".


[#contributed-action]
== Contributed Action

Contributed actions are defined similarly, using xref:refguide:applib:index/annotation/Action.adoc[@Action]; this implies a method called "act".
For example:

[source,java]
----
@Action                                                         // <.>
@RequiredArgsConstructor                                        // <.>
public class DocumentHolder_addDocument {

    private final DocumentHolder holder;

    public Document> act(Document doc) {                        // <.>
        ...
    }
    public boolean hideAct() { /* ... */ }                      // <.>
}
----
<.> indicates this is an action mixin (that contributes its method as an action) with method name 'act'
<.> mixee is injected into the mixin
<.> method must be called "act"
Unlike contributed properties and collections, contributed actions can accept parameters, and have any semantics.
<.> xref:business-rules.adoc[supporting methods] follow the usual naming conventions

This contributes an action called "addDocument".


[[mixins-as-nested-classes]]
== As Nested Classes

While mixins primary use case is as a means of allowing contributions from one module to the types of another module, they are also a convenient mechanism for grouping functionality/behaviour against a concrete type.
All the methods and xref:business-rules.adoc[supporting methods] end up in a single construct, and the dependency between that functionality and the rest of the object is made more explicit.

We might therefore want to use a mixin within the same module as the mixee; indeed even within the same package or class as the mixee.
In other words, we could define the mixin as nested static class of the mixee it contributes to.

In the previous examples the "_" is used as a separator between the mixin type and mixin name.
However, to support mixins as nested classes, the character "$" is also recognized as a separator.

For example, the following refactors the "updateName" action -- of the `SimpleObject` class in xref:docs:starters:simpleapp.adoc[SimpleApp] start app -- into a nested mixin:

[source,java]
----
public class SimpleObject /* ... */ {

    // ...

    @Action(semantics = IDEMPOTENT,
            commandPublishing = Publishing.ENABLED,
            executionPublishing = Publishing.ENABLED,
            associateWith = "name",
            domainEvent = updateName.DomainEvent.class)                 // <2>
    public class updateName {                                           // <.>

        public class DomainEvent extends
            SimpleModule.ActionDomainEvent<SimpleObject.updateName> {}  // <.>

        public SimpleObject act(@Name final String name) {
            setName(name);                                              // <.>
            return SimpleObject.this;
        }
        public String default0Act() {                                   // <.>
            return getName();                                           // <.>
        }
    }
    // ...
}
----
<.> Mixin class is not `static`, so that the containing object is implicitly available.
+
Its name can be either "camelCase" or "PascalCase", either will work.

<.> Domain event can be declared within the mixin, again, not `static`.
+
Note that it is genericised on the mixin, not on the mixee

<.> Acts on the owning instance.
<.> xref:business-rules.adoc[Supporting methods] follow the same naming convention.
<.> Acts on the owning instance.


== Programmatic usage

When a domain object is rendered, the framework will automatically instantiate all required mixins and delegate to them dynamically.
If writing integration tests or fixtures, or (sometimes) just regular domain logic, then you may need to instantiate mixins directly.

For this you can use the xref:refguide:applib:index/services/factory/FactoryService.adoc[FactoryService#mixin(...)] method.

For example:

[source,java]
----
DocumentHolder_documents mixin =
    factoryService.mixin(DocumentHolder_documents.class, customer);
----

Alternatively, you can use xref:refguide:applib:index/services/inject/ServiceInjector.adoc[ServiceInjector] to inject domain services after the mixin has been instantiated.
You'll need to use this method if using nested non-`static` mixins:


[source,java]
----
SimpleObject.updateName mixin =
    serviceInjector.injectServicesInto( simpleObject.new updateName() );
----


