EJB client interceptors in JBoss EAP 6

Solution Unverified - Updated

Environment

  • Red Hat JBoss Enterprise Application Platform (EAP)
    • 6.x

Issue

  • Can I register interceptors that will be valid for every EJB invocation or I have to register them separately (EJBClientContext.getCurrent().registerInterceptor(0, new HelloClientInterceptor());) - For example, what if I wanted HelloClientInterceptor to be always used for every EJB invocation (without requiring registration everywhere in code)?

  • How will this interceptors play with invoking remote EJBs in cluster (from one EAP instance to another one)?

  • If I do @EJB injection of remote EJB how do I attach interceptor in that case?

  • I am not able to find documentation about these JBoss specific interceptors. Do you have anything available?

Resolution

What does an EJB client interceptor class look like?

package com.jboss.examples.ejb3.client;

import org.jboss.ejb.client.EJBClientInterceptor;
import org.jboss.ejb.client.EJBClientInvocationContext;

public class HelloClientInterceptor implements EJBClientInterceptor
{
    @Override
    public void handleInvocation(EJBClientInvocationContext context)throws Exception
    {
        // Must make this call
        context.sendRequest();
    }

    @Override
    public Object handleInvocationResult(EJBClientInvocationContext context)
            throws Exception
    {
        // Must make this call
        return context.getResult();
    }
}

How to register an EJB client interceptor

EJB Client (not using scoped context)

Using the JBoss EJB Client API


EJBClientContext.getCurrent().registerInterceptor(0, new HelloClientInterceptor());)

Note: you should only register the interceptor once in the container

Using the service loader mechanism (JBoss EAP 6.1 and later)


[https://issues.jboss.org/browse/EJBCLIENT-61](https://issues.jboss.org/browse/EJBCLIENT-61)

Note: the service loader mechanism method cannot be used by packaging the jar in an application deployed in JBoss EAP 6, the deployments are not scanned. You can used the JBoss EJB Client API method or you can package your interceptors into a jar with the META-INF/services file and put the jar in the org.jboss.ejb-client module and list it as a resource-root in the module.xml

Create a file in the META-INF/services directory named org.jboss.ejb.client.EJBClientInterceptor and list the fully qualified name of your client interceptor class

META-INF/services/org.jboss.ejb.client.EJBClientInterceptor

com.jboss.examples.ejb3.client.HelloClientInterceptor

EJB Client using scoped context

Using the service loader mechanism (JBoss EAP 6.1 and later)


https://issues.jboss.org/browse/EJBCLIENT-61

Note: the service loader mechanism method cannot be used by packaging the jar in an application deployed in JBoss EAP 6, the deployments are not scanned. You can used the JBoss EJB Client API method or you can package your interceptors into a jar with the META-INF/services file and put the jar in the org.jboss.ejb-client module and list it as a resource-root in the module.xml

Create a file in the META-INF/services directory named org.jboss.ejb.client.EJBClientInterceptor and list the fully qualified name of your client interceptor class

META-INF/services/org.jboss.ejb.client.EJBClientInterceptor

com.jboss.examples.ejb3.client.HelloClientInterceptor

Note: When you register a JBoss EJB client interceptor, it will apply to all remote view/interface invocations in the container. This means once the interceptor is registered it does not and should not be registered again. The interceptor implementation can use the EJBClientInvocationContext to see which EJB/method is being invoked and determine if it wants to do something. The interceptor will run if you use @EJB to inject the remote interface view also. The interceptor will not run if you use @EJB to inject the local interface or no interface view. If the client is calling the remote interface clustered EJB, the interceptor will run.

Content from docs.jboss.org is not included.http://docs.jboss.org/ejbclient/1.0.5.Final/org/jboss/ejb/client/EJBClientInvocationContext.html

Why do the EJB client interceptors use JBoss specific classes?


The JavaEE 6 specification defines EJB server side interceptors, but it does not define EJB client side interceptors, thus the client side interceptors are not portable to other JavaEE containers and are application server specific.

What about EJB client interceptors to intercept local view invocations?


For local views you can use the Java EE specified interceptors or JBoss specific "container interceptors" depending on the use case.

JBoss "container interceptors" (JBoss EAP 6.1 and later)


The standard JavaEE interceptors are called after security and other mandated JavaEE setup (security context propagation, transaction management, etc), which maybe too late for some users use case. JBoss container interceptors

Container interceptors are configured in jboss-ejb3.xml as such:

<jboss xmlns="http://www.jboss.com/xml/ns/javaee"
       xmlns:jee="http://java.sun.com/xml/ns/javaee"
       xmlns:ci ="urn:container-interceptors:1.0">
 
    <jee:assembly-descriptor>
        <ci:container-interceptors>
            <!-- Default interceptor -->
            <jee:interceptor-binding>
                <ejb-name>*</ejb-name>
                <interceptor-class>org.jboss.as.test.integration.ejb.container.interceptor.ContainerInterceptorOne</interceptor-class>
            </jee:interceptor-binding>
            <!-- Class level container-interceptor -->
            <jee:interceptor-binding>
                <ejb-name>AnotherFlowTrackingBean</ejb-name>
                <interceptor-class>org.jboss.as.test.integration.ejb.container.interceptor.ClassLevelContainerInterceptor</interceptor-class>
            </jee:interceptor-binding>
            <!-- Method specific container-interceptor -->
            <jee:interceptor-binding>
                <ejb-name>AnotherFlowTrackingBean</ejb-name>
                <interceptor-class>org.jboss.as.test.integration.ejb.container.interceptor.MethodSpecificContainerInterceptor</interceptor-class>
                <method>
                    <method-name>echoWithMethodSpecificContainerInterceptor</method-name>
                </method>
            </jee:interceptor-binding>
            <!-- container interceptors in a specific order -->
            <jee:interceptor-binding>
                <ejb-name>AnotherFlowTrackingBean</ejb-name>
                <interceptor-order>
                    <interceptor-class>org.jboss.as.test.integration.ejb.container.interceptor.ClassLevelContainerInterceptor</interceptor-class>
                    <interceptor-class>org.jboss.as.test.integration.ejb.container.interceptor.MethodSpecificContainerInterceptor</interceptor-class>
                    <interceptor-class>org.jboss.as.test.integration.ejb.container.interceptor.ContainerInterceptorOne</interceptor-class>
                </interceptor-order>
                <method>
                    <method-name>echoInSpecificOrderOfContainerInterceptors</method-name>
                </method>
            </jee:interceptor-binding>
        </ci:container-interceptors>
    </jee:assembly-descriptor>
</jboss>

Example of a container interceptor implementation class:

public class ClassLevelContainerInterceptor {
    @AroundInvoke
    private Object iAmAround(final InvocationContext invocationContext) throws Exception {
        return this.getClass().getName() + " " + invocationContext.proceed();
    }
}

Note: Although the container interceptors are modeled to be similar to the Java EE interceptors, there are some differences in the API semantics. One such difference is that invoking on javax.interceptor.InvocationContext.getTarget() method is illegal for container interceptors since these interceptors are invoked way before the EJB components are setup or instantiated.

[1] Content from issues.jboss.org is not included.Content from issues.jboss.org is not included.https://issues.jboss.org/browse/AS7-5897
[2] Content from docs.jboss.org is not included.Content from docs.jboss.org is not included.https://docs.jboss.org/author/display/AS72/Container+interceptors

Components
Category

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.