This project has retired. For details please refer to its Attic page.
Create a Concern
Zest™
Introduction
Tutorials
Javadoc
Samples
Core
Libraries
Extensions
Tools
Glossary 

Create a Concern

Concerns are defined in Concern.

If you want to reproduce what’s explained in this tutorial, remember to depend on the Core Bootstrap artifact:

Table 10. Artifact

Group IDArtifact IDVersion

org.qi4j.core

org.qi4j.core.bootstrap

2.1


At runtime you will need the Core Runtime artifact too. See the Depend on Zest™ in your build tutorial for details.

Typed Concern

A typed Concern is a Java class that implements the MixinType it can be used on:

public class InventoryConcern extends ConcernOf<Order>
    implements Order
{
    @Service
    private InventoryService inventory;

    @Override
    public void addLineItem( LineItem item )
    {
        String productCode = item.productCode().get();
        int quantity = item.quantity().get();
        inventory.remove( productCode, quantity );
        next.addLineItem( item );
    }

    @Override
    public void removeLineItem( LineItem item )
    {
        String productCode = item.productCode().get();
        int quantity = item.quantity().get();
        inventory.add( productCode, quantity );
        next.removeLineItem( item );
    }
}

Note that we could have implemented the InventoryConcern as an abstract class if we were not interested in all the methods in the Order interface. Extending the ConcernOf is a convenience mechanism, instead of an explicit @ConcernFor annotation on a private field, which can be used in rare occasions when you are not able to extend. This base class defines the next field, which is set up by the Zest™ runtime and points to the next fragment in the call stack. We can also see that the InventoryService is provided to the concern, which is done with dependency injection. Zest™ also supports dependency injection via constructors and methods.

It can be used as follows;

@Concerns( InventoryConcern.class )
public interface Order
{
    void addLineItem( LineItem item );
    void removeLineItem( LineItem item );

      [...snip...]

Methods of the Concern Fragment will be called before the Mixin invocation.

Generic Concern

A generic Concern is a Java class that implements java.lang.reflect.InvocationHandler which allows it to be used on any arbitrary MixinType.

public class MyGenericConcern extends GenericConcern
{
    @Override
    public Object invoke( Object proxy, Method method, Object[] args )
        throws Throwable
    {
        // Do whatever you want

          [...snip...]

It can be used as follows;

@Concerns( MyGenericConcern.class )
public interface AnyMixinType
{

  [...snip...]

    @MyAnnotation
    void doSomething();

    void doSomethingElse();

Methods of the Concern Fragment will be called before the Mixin invocation.

AppliesTo

For generic Concerns that should only trigger on methods with specific annotations or fulfilling some expression, add @AppliesTo annotation to the Concern class which points to either triggering annotation(s), or to AppliesToFilter implementation(s).

The Concern is invoked if one of the triggering annotations is found or one of the AppliesToFilter accepts the invocation. In other words the AppliesTo arguments are OR’ed.

Here is how the declaration goes ;

@AppliesTo( { MyAnnotation.class, MyAppliesToFilter.class } )
public class MyGenericConcern extends GenericConcern
{

And how to use the annotation ;

@Concerns( MyGenericConcern.class )
public interface AnyMixinType
{

    @MyAnnotation
    void doSomething();

    void doSomethingElse();

}

Here only the doSomething() method will see the Concern applied whereas the doSomethingElse() method won’t.

Finally here is how to implement an AppliesToFilter:

public class MyAppliesToFilter implements AppliesToFilter
{
    public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> modifierClass )
    {
        boolean appliesTo = evaluate(method); // Do whatever you want
        return appliesTo;
    }

      [...snip...]

    private boolean evaluate( Method method )
    {
        return true;
    }