You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by db...@apache.org on 2012/12/30 05:29:18 UTC

svn commit: r1426887 - in /openejb/trunk/openejb: arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/context/ container/openejb-core/src/main/java/org/apache/openejb/util/proxy/ server...

Author: dblevins
Date: Sun Dec 30 04:29:18 2012
New Revision: 1426887

URL: http://svn.apache.org/viewvc?rev=1426887&view=rev
Log:
TOMEE-686 - JAX-RS @Context injection for EJB interceptors
TOMEE-687 - Refer to internal EJB BeanContext via WeakReference in JAX-RS layer

Added:
    openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/BeanContextInvocationHandler.java   (with props)
    openejb/trunk/openejb/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/ContextReferenceTypes.java   (with props)
    openejb/trunk/openejb/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/RsInterceptorInjectionTest.java
      - copied, changed from r1426800, openejb/trunk/openejb/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/RsInjectionTest.java
Modified:
    openejb/trunk/openejb/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/context/EjbInterceptorContextInjectionTest.java
    openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/ProxyEJB.java
    openejb/trunk/openejb/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/Contexts.java
    openejb/trunk/openejb/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfRsHttpListener.java
    openejb/trunk/openejb/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/OpenEJBEJBInvoker.java

Modified: openejb/trunk/openejb/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/context/EjbInterceptorContextInjectionTest.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/context/EjbInterceptorContextInjectionTest.java?rev=1426887&r1=1426886&r2=1426887&view=diff
==============================================================================
--- openejb/trunk/openejb/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/context/EjbInterceptorContextInjectionTest.java (original)
+++ openejb/trunk/openejb/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/context/EjbInterceptorContextInjectionTest.java Sun Dec 30 04:29:18 2012
@@ -53,7 +53,6 @@ import static org.junit.Assert.assertEqu
  * @version $Rev$ $Date$
  */
 @RunWith(Arquillian.class)
-@Ignore
 public class EjbInterceptorContextInjectionTest {
 
     @ArquillianResource
@@ -86,9 +85,6 @@ public class EjbInterceptorContextInject
         }
     }
 
-    public static class FooException extends RuntimeException {
-    }
-
     public static class RsEjbInterceptor {
         @Context
         private HttpHeaders httpHeaders;
@@ -151,4 +147,8 @@ public class EjbInterceptorContextInject
             return true;
         }
     }
+
+    public static class FooException extends RuntimeException {
+    }
+
 }

Added: openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/BeanContextInvocationHandler.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/BeanContextInvocationHandler.java?rev=1426887&view=auto
==============================================================================
--- openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/BeanContextInvocationHandler.java (added)
+++ openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/BeanContextInvocationHandler.java Sun Dec 30 04:29:18 2012
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.openejb.util.proxy;
+
+import org.apache.openejb.BeanContext;
+
+import java.lang.reflect.InvocationHandler;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public interface BeanContextInvocationHandler extends InvocationHandler {
+    public BeanContext getBeanContext();
+}

Propchange: openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/BeanContextInvocationHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/ProxyEJB.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/ProxyEJB.java?rev=1426887&r1=1426886&r2=1426887&view=diff
==============================================================================
--- openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/ProxyEJB.java (original)
+++ openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/ProxyEJB.java Sun Dec 30 04:29:18 2012
@@ -21,6 +21,7 @@ import org.apache.openejb.RpcContainer;
 import org.apache.openejb.core.ivm.IntraVmProxy;
 
 import java.io.Serializable;
+import java.lang.ref.WeakReference;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 
@@ -54,19 +55,35 @@ public class ProxyEJB {
         return Proxy.newProxyInstance(itfs[0].getClassLoader(), itfs, new Handler(beanContext));
     }
 
-    private static class Handler implements java.lang.reflect.InvocationHandler {
-        private BeanContext beanContext;
+    private static class Handler implements BeanContextInvocationHandler {
+
+        private transient WeakReference<BeanContext> beanContextRef;
+        private final Object deploymentID;
 
         public Handler(BeanContext bc) {
-            beanContext = bc;
+            beanContextRef = new WeakReference<BeanContext>(bc);
+            deploymentID = bc.getDeploymentID();
         }
 
         @Override
         public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+            final BeanContext beanContext = getBeanContext();
             final RpcContainer container = RpcContainer.class.cast(beanContext.getContainer());
+
             return container.invoke(beanContext.getDeploymentID(),
                     beanContext.getInterfaceType(method.getDeclaringClass()),
                     method.getDeclaringClass(), method, args, null);
         }
+
+
+        public BeanContext getBeanContext() {
+            BeanContext beanContext = beanContextRef.get();
+            if (beanContext == null|| beanContext.isDestroyed()){
+                beanContextRef.clear();
+                throw new IllegalStateException("Bean '" + deploymentID + "' has been undeployed.");
+            }
+            return beanContext;
+        }
+
     }
 }

Added: openejb/trunk/openejb/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/ContextReferenceTypes.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/ContextReferenceTypes.java?rev=1426887&view=auto
==============================================================================
--- openejb/trunk/openejb/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/ContextReferenceTypes.java (added)
+++ openejb/trunk/openejb/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/ContextReferenceTypes.java Sun Dec 30 04:29:18 2012
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.openejb.server.cxf.rs;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @version $Rev$ $Date$
+ */
+class ContextReferenceTypes {
+
+    private final Set<Class<?>> types = new HashSet<Class<?>>();
+
+    ContextReferenceTypes(Set<Class<?>> types) {
+        this.types.addAll(types);
+    }
+
+    public Set<Class<?>> get() {
+        return types;
+    }
+}

Propchange: openejb/trunk/openejb/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/ContextReferenceTypes.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: openejb/trunk/openejb/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/Contexts.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/Contexts.java?rev=1426887&r1=1426886&r2=1426887&view=diff
==============================================================================
--- openejb/trunk/openejb/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/Contexts.java (original)
+++ openejb/trunk/openejb/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/Contexts.java Sun Dec 30 04:29:18 2012
@@ -36,8 +36,11 @@ import javax.ws.rs.core.UriInfo;
 import javax.ws.rs.ext.ContextResolver;
 import javax.ws.rs.ext.Providers;
 import java.lang.reflect.Field;
+import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 
 public final class Contexts {
     private Contexts() {
@@ -52,8 +55,25 @@ public final class Contexts {
         final ClassResourceInfo cri = exchange.get(OperationResourceInfo.class).getClassResourceInfo();
 
         // binding context fields
+        final Set<Class<?>> types = new HashSet<Class<?>>();
         for (Field field : cri.getContextFields()) {
-            Class<?> type = field.getType();
+            types.add(field.getType());
+        }
+
+        bind(exchange, types);
+    }
+
+    /**
+     * Using a set ensures we don't set the thread local twice or more,
+     * there may be super classes with injection points of identical types
+     *
+     * Also allows us to get context references from other sources such as interceptors
+     *
+     * @param exchange
+     * @param types
+     */
+    public static void bind(Exchange exchange, Set<Class<?>> types) {
+        for (Class<?> type : types) {
             if (Request.class.equals(type)) {
                 Request binding = JAXRSUtils.createContextValue(exchange.getInMessage(), null, Request.class);
                 ThreadLocalContextManager.REQUEST.set(binding);

Modified: openejb/trunk/openejb/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfRsHttpListener.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfRsHttpListener.java?rev=1426887&r1=1426886&r2=1426887&view=diff
==============================================================================
--- openejb/trunk/openejb/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfRsHttpListener.java (original)
+++ openejb/trunk/openejb/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfRsHttpListener.java Sun Dec 30 04:29:18 2012
@@ -30,26 +30,33 @@ import org.apache.openejb.Injection;
 import org.apache.openejb.assembler.classic.ServiceInfo;
 import org.apache.openejb.assembler.classic.util.ServiceConfiguration;
 import org.apache.openejb.assembler.classic.util.ServiceInfos;
+import org.apache.openejb.core.interceptor.InterceptorData;
 import org.apache.openejb.server.cxf.transport.util.CxfUtil;
 import org.apache.openejb.server.httpd.HttpRequest;
 import org.apache.openejb.server.httpd.HttpRequestImpl;
 import org.apache.openejb.server.httpd.HttpResponse;
 import org.apache.openejb.server.rest.RsHttpListener;
+import org.apache.openejb.util.Classes;
 import org.apache.openejb.util.LogCategory;
 import org.apache.openejb.util.Logger;
 import org.apache.openejb.util.proxy.ProxyEJB;
 import org.apache.webbeans.config.WebBeansContext;
+import org.apache.xbean.finder.AnnotationFinder;
+import org.apache.xbean.finder.archive.ClassesArchive;
 
 import javax.naming.Context;
 import javax.servlet.http.HttpServletRequestWrapper;
 import javax.ws.rs.core.Application;
 import javax.xml.bind.Marshaller;
+import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 public class CxfRsHttpListener implements RsHttpListener {
     private static final Logger LOGGER = Logger.getInstance(LogCategory.OPENEJB_RS, CxfRsHttpListener.class);
@@ -98,10 +105,31 @@ public class CxfRsHttpListener implement
     @Override
     public void deployEJB(String fullContext, BeanContext beanContext, Collection<Object> additionalProviders, ServiceConfiguration configuration) {
         final Object proxy = ProxyEJB.subclassProxy(beanContext);
+
+        addContextTypes(beanContext);
+
         deploy(beanContext.getBeanClass(), fullContext, new NoopResourceProvider(beanContext.getBeanClass(), proxy),
                 proxy, null, new OpenEJBEJBInvoker(), additionalProviders, configuration);
     }
 
+    private void addContextTypes(BeanContext beanContext) {
+        final Set<Class<?>> classes = new HashSet<Class<?>>();
+        classes.addAll(Classes.ancestors(beanContext.getBeanClass()));
+        for (InterceptorData interceptorData : beanContext.getInstanceScopedInterceptors()) {
+            classes.addAll(Classes.ancestors(interceptorData.getInterceptorClass()));
+        }
+
+        // We really shouldn't do this here -- should be done in the AnnotationDeployer where we already payed for the AnnotationFinder
+        final AnnotationFinder finder = new AnnotationFinder(new ClassesArchive(classes));
+        final List<Field> fields = finder.findAnnotatedFields(javax.ws.rs.core.Context.class);
+        final Set<Class<?>> contextTypes = new HashSet<Class<?>>();
+        for (Field field : fields) {
+            contextTypes.add(field.getType());
+        }
+
+        beanContext.set(ContextReferenceTypes.class, new ContextReferenceTypes(contextTypes));
+    }
+
     private void deploy(Class<?> clazz, String address, ResourceProvider rp, Object serviceBean, Application app, Invoker invoker,
                         Collection<Object> additionalProviders, ServiceConfiguration configuration) {
         final String impl;

Modified: openejb/trunk/openejb/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/OpenEJBEJBInvoker.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/OpenEJBEJBInvoker.java?rev=1426887&r1=1426886&r2=1426887&view=diff
==============================================================================
--- openejb/trunk/openejb/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/OpenEJBEJBInvoker.java (original)
+++ openejb/trunk/openejb/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/OpenEJBEJBInvoker.java Sun Dec 30 04:29:18 2012
@@ -18,17 +18,30 @@ package org.apache.openejb.server.cxf.rs
 
 import org.apache.cxf.jaxrs.JAXRSInvoker;
 import org.apache.cxf.message.Exchange;
+import org.apache.openejb.BeanContext;
 import org.apache.openejb.InvalidateReferenceException;
 import org.apache.openejb.rest.ThreadLocalContextManager;
+import org.apache.openejb.util.proxy.BeanContextInvocationHandler;
+import org.apache.openejb.util.proxy.ProxyManager;
 
+import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.rmi.RemoteException;
+import java.util.Set;
 
 public class OpenEJBEJBInvoker extends JAXRSInvoker {
     @Override
     public Object invoke(final Exchange exchange, final Object request, final Object resourceObject) {
-        Contexts.bind(exchange);
+
+        final Set<Class<?>> types = getContextTypes(resourceObject);
+
+        if (types != null) {
+            Contexts.bind(exchange, types);
+        } else {
+            Contexts.bind(exchange);
+        }
+
         try {
             return super.invoke(exchange, request, resourceObject);
         } finally {
@@ -36,6 +49,18 @@ public class OpenEJBEJBInvoker extends J
         }
     }
 
+    private Set<Class<?>> getContextTypes(Object resourceObject) {
+        final InvocationHandler handler = ProxyManager.getInvocationHandler(resourceObject);
+        if (!(handler instanceof BeanContextInvocationHandler)) return null;
+
+        final BeanContext beanContext = ((BeanContextInvocationHandler) handler).getBeanContext();
+        final ContextReferenceTypes contextReferenceTypes = beanContext.get(ContextReferenceTypes.class);
+
+        if (contextReferenceTypes == null) return null;
+
+        return contextReferenceTypes.get();
+    }
+
     @Override
     protected Object performInvocation(final Exchange exchange, final Object serviceObject,
                                        final Method m, final Object[] paramArray) throws Exception {

Copied: openejb/trunk/openejb/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/RsInterceptorInjectionTest.java (from r1426800, openejb/trunk/openejb/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/RsInjectionTest.java)
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/RsInterceptorInjectionTest.java?p2=openejb/trunk/openejb/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/RsInterceptorInjectionTest.java&p1=openejb/trunk/openejb/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/RsInjectionTest.java&r1=1426800&r2=1426887&rev=1426887&view=diff
==============================================================================
--- openejb/trunk/openejb/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/RsInjectionTest.java (original)
+++ openejb/trunk/openejb/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/RsInterceptorInjectionTest.java Sun Dec 30 04:29:18 2012
@@ -17,20 +17,35 @@
 package org.apache.openejb.server.cxf.rs;
 
 import org.apache.openejb.OpenEjbContainer;
+import org.apache.openejb.core.ivm.naming.MapObjectReference;
+import org.apache.openejb.core.ivm.naming.ObjectReference;
 import org.apache.openejb.jee.Empty;
 import org.apache.openejb.jee.SingletonBean;
 import org.apache.openejb.junit.ApplicationComposer;
 import org.apache.openejb.junit.Configuration;
 import org.apache.openejb.junit.Module;
 import org.apache.openejb.loader.IO;
+import org.apache.openejb.rest.ThreadLocalContextManager;
+import org.junit.Assert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import javax.ejb.Singleton;
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.Interceptors;
+import javax.interceptor.InvocationContext;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.ContextResolver;
 import javax.ws.rs.ext.Providers;
 import java.io.IOException;
 import java.net.URL;
@@ -39,7 +54,8 @@ import java.util.Properties;
 import static org.junit.Assert.assertEquals;
 
 @RunWith(ApplicationComposer.class)
-public class RsInjectionTest {
+public class RsInterceptorInjectionTest {
+
     @Module
     public static SingletonBean service() throws Exception {
         final SingletonBean bean = new SingletonBean(RsInjection.class);
@@ -56,23 +72,98 @@ public class RsInjectionTest {
 
     @Test
     public void rest() throws IOException {
-        final String response = IO.slurp(new URL("http://127.0.0.1:4204/RsInjectionTest/injections/check"));
+        final String response = IO.slurp(new URL("http://127.0.0.1:4204/RsInterceptorInjectionTest/injections/check"));
         assertEquals("true", response);
     }
 
     @Singleton
+    @Interceptors(RsEjbInterceptor.class)
     @Path("/injections")
     public static class RsInjection {
+
+        @GET
+        @Path("/check")
+        public boolean check() {
+            return false;
+        }
+    }
+
+    public static class RsEjbInterceptor {
+
+        @Context
+        private HttpHeaders httpHeaders;
+
         @Context
         private Providers providers;
 
         @Context
         private HttpServletResponse response;
 
-        @GET
-        @Path("/check")
-        public boolean check() {
-            return providers != null && response != null;
+        @Context
+        private Request request;
+
+        @Context
+        private HttpServletRequest httpServletRequest;
+
+// TODO TOMEE-684
+//        @Context
+//        private ServletRequest servletRequest;
+//
+        @Context
+        private UriInfo uriInfo;
+
+        @Context
+        private SecurityContext securityContext;
+
+        @Context
+        private ContextResolver contextResolver;
+
+// TODO TOMEE-685
+//        @Context
+//        private ServletConfig servletConfig;
+
+
+        @AroundInvoke
+        private Object invoke(InvocationContext context) throws Exception {
+            // Are they injected?
+            Assert.assertNotNull("httpHeaders", httpHeaders);
+            Assert.assertNotNull("providers", providers);
+            Assert.assertNotNull("response", response);
+            Assert.assertNotNull("request", request);
+            Assert.assertNotNull("httpServletRequest", httpServletRequest);
+            Assert.assertNotNull("uriInfo", uriInfo);
+            Assert.assertNotNull("securityContext", securityContext);
+            Assert.assertNotNull("contextResolver", contextResolver);
+
+            // Do the thread locals actually point anywhere?
+            Assert.assertTrue(httpHeaders.getRequestHeaders().size() > 0);
+            Assert.assertTrue(providers.getExceptionMapper(FooException.class) == null);
+            Assert.assertTrue(response.getHeaderNames() != null);
+            Assert.assertTrue(request.getMethod() != null);
+            Assert.assertTrue(httpServletRequest.getMethod() != null);
+            Assert.assertTrue(uriInfo.getPath() != null);
+// TODO OPENEJB-1979 - JAX-RS SecurityContext.isCallerInRole always returns true in Embedded EJBContainer
+//            Assert.assertTrue(!securityContext.isUserInRole("ThereIsNoWayThisShouldEverPass"));
+            Assert.assertTrue(contextResolver.getContext(null) == null);
+
+            context.proceed();
+
+            // Test again to ensure thread locals are still valid
+            Assert.assertTrue(httpHeaders.getRequestHeaders().size() > 0);
+            Assert.assertTrue(providers.getExceptionMapper(FooException.class) == null);
+            Assert.assertTrue(response.getHeaderNames() != null);
+            Assert.assertTrue(request.getMethod() != null);
+            Assert.assertTrue(httpServletRequest.getMethod() != null);
+            Assert.assertTrue(uriInfo.getPath() != null);
+// TODO OPENEJB-1979 - JAX-RS SecurityContext.isCallerInRole always returns true in Embedded EJBContainer
+//            Assert.assertTrue(!securityContext.isUserInRole("ThereIsNoWayThisShouldEverPass"));
+            Assert.assertTrue(contextResolver.getContext(null) == null);
+
+            return true;
         }
     }
+
+    public static class FooException extends RuntimeException {
+    }
+
 }