= Understanding Callbacks
:index-group: Unrevised
:jbake-date: 2018-12-05
:jbake-type: page
:jbake-status: published

The rules here are pretty hard to follow without
examples.

When they say one AroundInvoke per class they mean that in the most
literal sense as in one individual java class definition, not including
it's parent class or classes, may exactly one AroundInvoke method. The
bean or interceptor class may have an AroundInvoke method, its parent
class may have an AroundInvoke method, the parent's parent class may
have an AroundInvoke method and so on.

So the following is legal.

[source,java]
----
public class Plant {
    @AroundInvoke
    public Object a(InvocationContext ctx) throws Exception {
        return ctx.proceed();
    }
}

public class Fruit extends Plant {
    @AroundInvoke
    public Object b(InvocationContext ctx) throws Exception {
        return ctx.proceed();
    }
}

@Stateless
public class Apple extends Fruit implements AppleLocal {
    @AroundInvoke
    public Object c(InvocationContext ctx) throws Exception {
        return ctx.proceed();
    }

    public String grow(){
        return "ready to pick";
    }
}

public interface AppleLocal {
    public String grow();
}
----

The result is that when the "grow" method on AppleLocal (and
consequently on Apple) is invoked, the container will first invoke the
following AroundInvoke methods in this order; a, b, c.

What the ejb spec doesn't do such a good job at stating is that there
are ways to effectively shut off the callbacks, including AroundInvoke,
of a parent class by simply overriding the method. We can shut off the
"a" around invoke with a slightly different version of Apple as follows:

[source,java]
----
@Stateless
public class Apple extends Fruit implements AppleLocal {

    // This will now never be called.
    public Object a(InvocationContext ctx) throws Exception {
        return null;
    }

    @AroundInvoke
    public Object c(InvocationContext ctx) throws Exception {
        return ctx.proceed();
    }

    public String grow(){
        return "ready to pick";
    }
}
----

The result of this is that when the "grow" method on AppleLocal is
invoked, the container will first invoke the AroundInvoke methods "b"
then "c" skipping "a" completely.

When they say that an AroundInvoke method cannot be a business method,
they mean that they cannot be exposed to clients through a local or
remote interface. The following would be illegal.

[source,java]
----
public interface AppleLocal {
    public String grow();

    // This is an AroundInvoke method in the bean class, not a legal business method!
    public Object c(InvocationContext ctx) throws Exception;
}
----
