You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by jg...@apache.org on 2021/06/03 12:32:21 UTC

[tomee] branch master updated: TOMEE-3752 Fix issue injecting WebServiceContext into field when usign CDI interceptor

This is an automated email from the ASF dual-hosted git repository.

jgallimore pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tomee.git


The following commit(s) were added to refs/heads/master by this push:
     new dfbdedb  TOMEE-3752 Fix issue injecting WebServiceContext into field when usign CDI interceptor
     new 8abe5fd  Merge pull request #799 from jgallimore/TOMEE-3752
dfbdedb is described below

commit dfbdedbcebf71cab294c4b01ee43651de369ced3
Author: Jonathan Gallimore <jo...@jrg.me.uk>
AuthorDate: Wed May 26 11:18:30 2021 +0100

    TOMEE-3752 Fix issue injecting WebServiceContext into field when usign CDI interceptor
---
 .../tests/jaxws/WebServiceContextTest.java         | 137 +++++++++++++++++++++
 .../openejb/server/cxf/transport/util/CxfUtil.java |  32 +++++
 2 files changed, 169 insertions(+)

diff --git a/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxws-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxws/WebServiceContextTest.java b/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxws-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxws/WebServiceContextTest.java
new file mode 100644
index 0000000..9ba9bd7
--- /dev/null
+++ b/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxws-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxws/WebServiceContextTest.java
@@ -0,0 +1,137 @@
+package org.apache.openejb.arquillian.tests.jaxws;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.descriptor.api.Descriptors;
+import org.jboss.shrinkwrap.descriptor.api.beans11.BeansDescriptor;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.annotation.Priority;
+import javax.annotation.Resource;
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.Interceptor;
+import javax.interceptor.InterceptorBinding;
+import javax.interceptor.InvocationContext;
+import javax.jws.WebService;
+import javax.servlet.http.HttpServletRequest;
+import javax.xml.namespace.QName;
+import javax.xml.ws.Service;
+import javax.xml.ws.WebServiceContext;
+import javax.xml.ws.handler.MessageContext;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.net.URL;
+import java.util.logging.Logger;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+@RunWith(Arquillian.class)
+public class WebServiceContextTest {
+
+    @ArquillianResource
+    private URL url;
+
+    @Deployment(testable = false)
+    public static WebArchive createDeployment() {
+        final String beansXml = Descriptors.create(BeansDescriptor.class)
+                .getOrCreateInterceptors()
+                .clazz(LogInterceptor.class.getName())
+                .up().exportAsString();
+
+        return ShrinkWrap.create(WebArchive.class, "ROOT.war")
+                .addClasses(Echo.class, EchoWS.class, SimpleRequestContext.class, Log.class, LogInterceptor.class)
+                .addAsWebInfResource(new StringAsset(beansXml), "beans.xml");
+    }
+
+    @Test
+    public void invoke() throws Exception {
+        final Service service = Service.create(new URL(url.toExternalForm() + "/EchoWSService?wsdl"), new QName("http://jaxws.tests.arquillian.openejb.apache.org/", "EchoWSService"));
+        final Echo echo = service.getPort(Echo.class);
+        assertEquals("foo", echo.echo("foo"));
+        final String remote = echo.remote();
+        System.out.println(remote);
+        assertEquals("127.0.0.1", remote);
+    }
+
+    @WebService(portName = "EchoWSPort")
+    public static interface Echo {
+        public String echo(final String input);
+        public String remote();
+    }
+
+    @WebService
+    public static class EchoWS implements Echo {
+        @Resource
+        private WebServiceContext wsc;
+
+        @Inject
+        private SimpleRequestContext ctx;
+
+        @Override
+        @Log
+        public String remote() {
+            final HttpServletRequest request = (HttpServletRequest) wsc.getMessageContext().get(MessageContext.SERVLET_REQUEST);
+            return request.getRemoteAddr();
+        }
+
+        @Override
+        @Log
+        public String echo(String input) {
+            return input;
+        }
+    }
+
+    @RequestScoped
+    public static class SimpleRequestContext {
+        private String status;
+
+        public String getStatus() {
+            return status;
+        }
+
+        public void setStatus(String status) {
+            this.status = status;
+        }
+    }
+
+    @InterceptorBinding
+    @Priority(4020)
+    @Target({TYPE, METHOD})
+    @Retention(RUNTIME)
+    public @interface Log {
+    }
+
+    @Interceptor
+    @Log
+    public static class LogInterceptor {
+
+        private static final Logger LOGGER = Logger.getLogger(LogInterceptor.class.getName());
+
+        @AroundInvoke
+        protected Object businessMethodInterceptor(final InvocationContext ic) throws Throwable {
+            final Object result;
+            try {
+                LOGGER.info("Entering " + ic.getMethod().toString());
+                result = ic.proceed();
+            } catch (Throwable t) {
+                throw t;
+            } finally {
+                LOGGER.info("Exiting " + ic.getMethod().toString());
+            }
+
+            return result;
+        }
+    }
+
+}
diff --git a/server/openejb-cxf-transport/src/main/java/org/apache/openejb/server/cxf/transport/util/CxfUtil.java b/server/openejb-cxf-transport/src/main/java/org/apache/openejb/server/cxf/transport/util/CxfUtil.java
index 24ee6d4..3d58bb0 100644
--- a/server/openejb-cxf-transport/src/main/java/org/apache/openejb/server/cxf/transport/util/CxfUtil.java
+++ b/server/openejb-cxf-transport/src/main/java/org/apache/openejb/server/cxf/transport/util/CxfUtil.java
@@ -49,8 +49,13 @@ import org.apache.openejb.server.cxf.transport.OpenEJBHttpDestinationFactory;
 import org.apache.openejb.server.cxf.transport.event.BusCreated;
 import org.apache.openejb.util.PropertiesHelper;
 import org.apache.openejb.util.reflection.Reflections;
+import org.apache.webbeans.intercept.DefaultInterceptorHandler;
+import org.apache.webbeans.proxy.InterceptorHandler;
+import org.apache.webbeans.proxy.OwbInterceptorProxy;
+import org.apache.webbeans.util.ExceptionUtil;
 
 import javax.management.MBeanServer;
+import java.lang.reflect.Field;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
@@ -62,6 +67,8 @@ import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.logging.Level;
 
+import static org.apache.webbeans.proxy.InterceptorDecoratorProxyFactory.FIELD_INTERCEPTOR_HANDLER;
+
 public final class CxfUtil {
     public static final String ENDPOINT_PROPERTIES = "properties";
     public static final String FEATURES = "features";
@@ -129,8 +136,33 @@ public final class CxfUtil {
 
                 @Override
                 public Object getRealObject(Object o) {
+                    // special case for OWB proxies - ie, a webservice endpoint with a CDI interceptor
+                    // we'll want to unwrap this and set the field on the proxied instance, rather than set the field
+                    // straight on the proxy
+                    if (o instanceof OwbInterceptorProxy) {
+                        return getProxiedInstance(o);
+                    }
+
                     return o;
                 }
+
+                private Object getProxiedInstance(Object o) {
+                    try {
+                        final Field field = o.getClass().getDeclaredField(FIELD_INTERCEPTOR_HANDLER);
+                        field.setAccessible(true);
+
+                        final Object fieldValue = field.get(o);
+
+                        if (fieldValue instanceof DefaultInterceptorHandler) {
+                            final DefaultInterceptorHandler handler = (DefaultInterceptorHandler) fieldValue;
+                            return handler.getTarget();
+                        } else {
+                            throw new IllegalStateException("Expected OwbInterceptorProxy handler to be an instance of Default Interceptor Handler.");
+                        }
+                    } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
+                        throw new RuntimeException(e);
+                    }
+                }
             });
 
             SystemInstance.get().addObserver(new LifecycleManager());