The Java – @ aroundinvoke interceptor is called twice on the @ WebService class

abstract

Call the @ aroundinvoke interceptor twice on 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 from within another bean, it is called only once (as I expected)

The intercepted method itself is always called only once!

Question 1: can I intercept the interceptor only once?

Question 2: if I can't, is there a transferable (server independent) way to determine which interceptor I am in, then can I ignore the redundant interceptors?

Question 3: is this behavior common (and defined and described in some documents), or does it depend on my specific environment (JBoss EAP 6.4.0)?

Observation:

>These two calls are not in the same interceptor chain. > It is different from the instance of interceptor class. > The implementation classes of the invocationcontext of the two calls are different. > Interestingly, one of the contextdata (the field of invocationcontext used to pass data along the interceptor chain) is not an instance of HashMap, but wrappedmessagecontext, but it does not wrap other contextdata anyway

Minimal reproducible code

(I deleted the package name.)

Myendpoint interface

import javax.jws.WebService;

@WebService
public interface MyEndpoint {
    public static final String SERVICE_NAME = "MyEndpointService";
    public String getHello();
}

Myendpointimpl class

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";
    }
}

Testinterceptor class

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();
    }
}

yield

Interceptor called
Interceptor called
MyEndpointImpl.getHello() called

More details

To get more runtime information, I added more logging

Myendpointimpl class

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 {},contextData);
        return ret;
    }
}

yield

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

Solution

I can't answer your question directly, but perhaps a clarification of the context may help you

Java EE Jax - WS implementations vary from server to server For example, GlassFish uses Metro and JBoss uses Apache CXF

There are different types of interceptor chains that allow programmatic control of conditions before and after request / response processing

The interceptors of soap web service calls are soap handlers and logical handlers (see Oracle documentation) Both can access SOAP messages at different levels (whole or payload only)

My assumption is that your interceptor is called twice, once for HTTP / soap access and once for RMI access

In the first interceptor call, the context you see is org apache. cxf. jaxws. context. Wrappedmessagecontext, which is a map implementation See warppedmessagecontext, Apache CXF web service context It is called for HTTP / soap access

The second call is what you expect when using RMI (possibly triggered from Apache CXF after processing the SOAP message)

To avoid this, you can use the third class for logical implementation and define interceptors The existing web service implementation class will only delegate to it and no longer contain interceptor comments

The sample code can be seen here: OSCM project

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>