Summary
@AroundInvoke interceptor is called twice in the @WebService class if the intercepted method is called from outside the application through the endpoint as a SOAP web service.
If the same method is called internally from another bean, it calls only once (as expected).
The most intercepted method is always called only once!
Question 1 . Can I get the interceptor to be called only once?
Question 2 . If I canβt, is there a transfer method (server independent) for the solution in which I intercept, so I can ignore the redundant?
Question 3 : Is this behavior common (and defined and described in some documentation), or does it depend on my specific environment (JBoss EAP 6.4.0)?
Comment:
- Two calls are not in the same chain of interceptors.
- This is not the same instance of the interceptor class.
- The
InvocationContext implementation class is different for both calls. - It's funny that one of the
contextData fields, InvocationContext for transmitting data along the chain of interceptors, is not an HashMap instance, but a WrappedMessageContext , but it does not transfer another contextData in any case.
Minimum reproducible code
(I removed the package name.)
MyEndpoint Interface
import javax.jws.WebService; @WebService public interface MyEndpoint { public static final String SERVICE_NAME = "MyEndpointService"; public String getHello(); }
Class MyEndpointImpl
import javax.interceptor.Interceptors; import javax.jws.WebService; @WebService(endpointInterface = "MyEndpoint", serviceName = MyEndpoint.SERVICE_NAME) @Interceptors({TestInterceptor.class}) public class MyEndpointImpl implements MyEndpoint { @Override public String getHello() { System.out.println("MyEndpointImpl.getHello() called"); return "Hello"; } }
Class TestInterceptor
import javax.interceptor.AroundInvoke; import javax.interceptor.InvocationContext; public class TestInterceptor { @AroundInvoke private Object countCalls(InvocationContext ic) throws Exception { System.out.println("Interceptor called"); return ic.proceed(); } }
Output
Interceptor called Interceptor called MyEndpointImpl.getHello() called
More details
To get more runtime information, I added more protocols.
Class MyEndpointImpl
import java.lang.reflect.Method; import java.util.Map; import javax.interceptor.AroundInvoke; import javax.interceptor.InvocationContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TestInterceptor { private static Logger logger = LoggerFactory.getLogger(TestInterceptor.class); private static int callCnt = 0; @AroundInvoke private Object countCalls(InvocationContext ic) throws Exception { final String interceptorClass = this.toString(); final String invocationContextClass = ic.getClass().getName(); final Method method = ic.getMethod(); final String calledClass = method.getDeclaringClass().getName(); final String calledName = method.getName(); final String message = String.format( "%n INTERCEPTOR: %s%n InvocationContext: %s%n %s # %s()", interceptorClass, invocationContextClass, calledClass, calledName); logger.info(message); final int call = ++callCnt; final Map<String, Object> contextData = ic.getContextData(); contextData.put("whoami", call); logger.info("BEFORE PROCEED {}, {}", call, contextData); final Object ret = ic.proceed(); logger.info("AFTER PROCEED {}, {}", call, contextData); return ret; } }
Output
INTERCEPTOR: TestInterceptor@74c90b72 InvocationContext: org.jboss.invocation.InterceptorContext$Invocation MyEndpointImpl # getHello() BEFORE PROCEED 1, org.apache.cxf.jaxws. context.WrappedMessageContext@2cfccb1d INTERCEPTOR: TestInterceptor@5226f6d8 InvocationContext: org.jboss.weld.interceptor.proxy.InterceptorInvocationContext MyEndpointImpl # getHello() BEFORE PROCEED 2, {whoami=2} MyEndpointImpl.getHello() called AFTER PROCEED 2, {whoami=2} AFTER PROCEED 1, org.apache.cxf.jaxws.context.WrappedMessageContext@2cfccb1d