////
*******************************************************************
* Copyright (c) 2019, 2022 Eclipse Foundation
*
* This specification document is made available under the terms
* of the Eclipse Foundation Specification License v1.0, which is
* available at https://www.eclipse.org/legal/efsl.php.
*******************************************************************
////

[[associating_interceptors_with_classes_and_methods_using_interceptor_bindings]]
== Associating Interceptors with Classes and Methods using Interceptor Bindings

Interceptor bindings are intermediate
annotations that may be used to associate interceptors with any
component that is not itself an interceptor or decorator
see [<<bib10>>].

[[interceptor_binding_types]]
=== Interceptor Binding Types

An interceptor binding type is a Java
annotation defined as `Retention(RUNTIME)`. Typically an interceptor
binding is defined as `Target({TYPE, METHOD, CONSTRUCTOR})` or any subset
of valid target types.

An interceptor binding type may be declared
by specifying the InterceptorBinding meta-annotation.

[source, java]
----
@Inherited
@InterceptorBinding
@Target({TYPE, METHOD})
@Retention(RUNTIME)
public @interface Monitored {}
----

[[interceptor_binding_types_with_additional_interceptor_bindings]]
==== Interceptor binding types with additional interceptor bindings

An interceptor binding type may declare other
interceptor bindings.

[source, java]
----
@Inherited
@InterceptorBinding
@Target({TYPE, METHOD})
@Retention(RUNTIME)
@Monitored
public @interface DataAccess {}
----

Interceptor bindings are transitive—an
interceptor binding declared by an interceptor binding type is inherited
by all components and other interceptor binding types that declare that
interceptor binding type.

An interceptor binding type can only be
applied to an interceptor binding type defining a subset of its target
types. For example, interceptor binding types declared `Target(TYPE)` may
not be applied to interceptor binding types declared `Target({TYPE, METHOD})`.

[[other_sources_of_interceptor_bindings]]
==== Other sources of interceptor bindings

An extension specification may define other
sources of interceptor bindings, such as by CDI stereotypes.

[[declaring_the_interceptor_bindings_of_an_interceptor]]
=== Declaring the Interceptor Bindings of an Interceptor

The interceptor bindings of an interceptor
are specified by annotating the interceptor class with the interceptor
binding types and the Interceptor annotation and are called the set of
interceptor bindings for the interceptor.

[source, java]
----
@Monitored @Interceptor
public class MonitoringInterceptor {
    @AroundInvoke
    public Object monitorInvocation(InvocationContext ctx)
        throws Exception { ... }
}
----
An interceptor class may declare multiple
interceptor bindings.

Multiple interceptors may declare the same
interceptor bindings.

If an interceptor does not declare an
`Interceptor` annotation, it can be bound to components using the
`Interceptors` annotation.

An extension specification may define other
ways of declaring an interceptor and binding an interceptor to a
component, such as by means of a deployment descriptor.

An interceptor declared using the `Interceptor`
annotation should specify at least one `interceptor` binding. If an interceptor
declared using the `Interceptor` annotation does not declare any intercep-
tor binding, non-portable behavior results.

[[binding_an_interceptor_to_a_component]]
=== Binding an Interceptor to a Component

An interceptor may be bound to a component by
annotating the component class or a method or constructor of the
component class with the interceptor binding type.

In the following example, the
`MonitoringInterceptor` is applied to the target class. It will therefore
apply to all business methods of the class.

[source, java]
----
@Monitored
public class ShoppingCart { ... }
----


In this example, the `MonitoringInterceptor` is
applied to a single method:

[source, java]
----
public class ShoppingCart {

    @Monitored
    public void placeOrder() {
        ...
    }

}
----

A component class or a method or constructor
of a component class may declare multiple interceptor bindings.

The set of interceptor bindings for a method
or constructor are those applied to the target class combined with those
applied at method level or constructor level. Note that the interceptor
bindings applied to the target class may include those inherited from
its superclasses. The CDI specification rules for the inheritance of
type-level metadata apply to the inheritance of interceptor bindings
from superclasses of the target class. See [<<bib8>>].

An interceptor binding declared on a method
or constructor replaces an interceptor binding of the same type declared
at class level or inherited from a superclass footnote:[This requirement
follows the rules from the Jakarta Annotations specification, section 3.1 &#91;<<bib9>>&#91;.].

An extension specification may define
additional rules for combining interceptor bindings, such as
interceptors defined via a CDI stereotype.

If a component class declares or inherits a
class-level interceptor binding, it must not be declared `final`, or have
any non-`static`, non-`private`, `final` methods. If a component has a
class-level interceptor binding and is declared `final` or has a
non-`static`, non-`private`, `final` method, the container automatically
detects the problem and treats it as a definition error, and causes
deployment to fail.

If a non-`static`, non-`private` method of a
component class declares a method-level interceptor binding, neither the
method nor the component class may be declared final. If a non-`static`,
non-`private`, `final` method of a component has a method-level interceptor
binding, the container automatically detects the problem and treats it
as a definition error, and causes deployment to fail.

[[interceptor_resolution]]
=== Interceptor Resolution

The process of matching interceptors to a
given business method, timeout method, or lifecycle event of a component
is called `interceptor resolution`.

For a lifecycle event other than instance
construction, the interceptor bindings include the interceptor bindings
declared or inherited by the component at the class level, including,
recursively, interceptor bindings declared as meta-annotations of other
interceptor bindings.

For a business method, timeout method, or
constructor, the interceptor bindings include the interceptor bindings
declared or inherited by the component at the class level, including,
recursively, interceptor bindings declared as meta-annotations of other
interceptor bindings, together with all interceptor bindings declared on
the constructor or method, including, recursively, interceptor bindings
declared as meta-annotations of other interceptor bindings.

An interceptor is bound to a method or
constructor if:

- The method or constructor has all the
interceptor bindings of the interceptor. A method or constructor has an
interceptor binding of an interceptor if it has an interceptor binding
with (a) the same type and (b) the same annotation member value for each
member. An extension specification may further refine this rule. For
example, the CDI specification [<<bib8>>,<<bib3>>] adds the
`jakarta.enterprise.util.Nonbinding` annotation, causing member values to be
ignored by the resolution process.

- The interceptor intercepts the given kind of
lifecycle event or method.

- The interceptor is enabled. An interceptor is
enabled if the `Priority` annotation is applied to the interceptor
class footnote:[The Priority annotation also orders interceptors. See Chapter 5 <<interceptor_ordering>>.].
An extension specification may define other
means of enabling interceptors. For example, the CDI specification
enables an interceptor if the interceptor class is listed under the
`<interceptors>` element of the `beans.xml` file for the bean archive.

[[interceptors_with_multiple_bindings]]
==== Interceptors with multiple bindings

An interceptor class may specify multiple
interceptor bindings.

[source, java]
----
@Monitored @Logged @Interceptor @Priority(1100)
public class MonitoringLoggingInterceptor {
    @AroundInvoke
    public Object aroundInvoke(InvocationContext context)
        throws Exception { ... }
}
----

This interceptor will be bound to all methods
of this component:

[source, java]
----
@Monitored @Logged
public class ShoppingCart { ... }
----

The `MonitoringLoggingInterceptor` will not be
bound to methods of this component, since the Logged interceptor binding
does not appear:

[source, java]
----
@Monitored
public class ShoppingCart {
    public void placeOrder() { ... }
}
----

However, the `MonitoringLoggingInterceptor`
will be bound to the placeOrder method of this component:

[source, java]
----
@Monitored
public class ShoppingCart {
    @Logged
    public void placeOrder() { ... }
}
----

[[interceptor_binding_types_with_members]]
==== Interceptor binding types with members

Interceptor binding types may have annotation
members.

[source, java]
----
@Inherited
@InterceptorBinding
@Target({TYPE, METHOD})
@Retention(RUNTIME)
public @interface Monitored {
    boolean persistent();
}
----

Any interceptor with that interceptor binding
type must select a member value:

[source, java]
----
@Monitored(persistent=true) @Interceptor @Priority(2100)
public class PersistentMonitoringInterceptor {
    @AroundInvoke
    public Object monitorInvocation(InvocationContext ctx)
        throws Exception { ... }
}
----

The `PersistentMonitoringInterceptor` applies
to this component:

[source, java]
----
@Monitored(persistent=true)
public class ShoppingCart { ... }
----

But not to this component:

[source, java]
----
@Monitored(persistent=false)
public class SimpleShoppingCart { ... }
----

Annotation member values are compared using
the `equals` method.

Array-valued or annotation-valued members of
an interceptor binding type are not supported. An extension
specification may add support for these member types. For example the
CDI specification [<<bib3>>,<<bib8>>] adds the
`jakarta.enterprise.util.Nonbinding` annotation, allowing array-valued or
annotation-valued members to be used on the annotation type, but ignored
by the resolution process.

If the set of interceptor bindings of a
component class or interceptor, including bindings inherited from CDI
stereotypes [<<bib3>>,<<bib8>>] and other interceptor bindings,
has two instances of a certain interceptor binding type and the
instances have different values of some annotation member, the container
automatically detects the problem, treats it as a definition error, and
causes deployment to fail.

