cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dk...@apache.org
Subject svn commit: r637990 - in /incubator/cxf/trunk: rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/ rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/ systests/src/test/java/org/apache/cxf/systest/jaxws/
Date Mon, 17 Mar 2008 17:44:59 GMT
Author: dkulp
Date: Mon Mar 17 10:44:57 2008
New Revision: 637990

URL: http://svn.apache.org/viewvc?rev=637990&view=rev
Log:
[CXF-1410] Allow proxies to be configured such that the request context is thread local like
the response context

Added:
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxws/JaxWsClientThreadTest.java
  (with props)
Modified:
    incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsClientProxy.java
    incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsProxyFactoryBean.java
    incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/JaxWsClientTest.java

Modified: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsClientProxy.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsClientProxy.java?rev=637990&r1=637989&r2=637990&view=diff
==============================================================================
--- incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsClientProxy.java
(original)
+++ incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsClientProxy.java
Mon Mar 17 10:44:57 2008
@@ -25,6 +25,7 @@
 import java.net.HttpURLConnection;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.FutureTask;
 import java.util.logging.Logger;
@@ -59,10 +60,44 @@
 
 public class JaxWsClientProxy extends org.apache.cxf.frontend.ClientProxy implements
     InvocationHandler, BindingProvider {
+ 
+    /*
+     * modification are echoed back to the shared map
+     */
+    public static class EchoContext extends HashMap<String, Object> {
+        final Map<String, Object> shared; 
+        public EchoContext(Map<String, Object> sharedMap) {
+            super(sharedMap);
+            shared = sharedMap;
+        }
+
+        public Object put(String key, Object value) {
+            shared.put(key, value);
+            return super.put(key, value);
+        }
+
+        public void putAll(Map<? extends String, ? extends Object> t) {
+            shared.putAll(t);
+            super.putAll(t);
+        }
+        
+        public Object remove(Object key) {
+            shared.remove(key);
+            return super.remove(key);
+        }
+        
+        public void reload() {
+            super.clear();
+            super.putAll(shared);
+        }
+    }
 
+    public static final String THREAD_LOCAL_REQUEST_CONTEXT = "thread.local.request.context";
     private static final Logger LOG = LogUtils.getL7dLogger(JaxWsClientProxy.class);
 
-    protected Map<String, Object> requestContext = new ConcurrentHashMap<String,
Object>();
+    protected Map<String, Object> currentRequestContext = new ConcurrentHashMap<String,
Object>();
+    protected ThreadLocal <EchoContext> requestContext =
+        new ThreadLocal<EchoContext>();
 
     protected ThreadLocal <Map<String, Object>> responseContext =
             new ThreadLocal<Map<String, Object>>();
@@ -80,8 +115,8 @@
     private void setupEndpointAddressContext(Endpoint endpoint) {
         // NOTE for jms transport the address would be null
         if (null != endpoint && null != endpoint.getEndpointInfo().getAddress())
{
-            getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, 
-                                    endpoint.getEndpointInfo().getAddress());
+            currentRequestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, 
+                                      endpoint.getEndpointInfo().getAddress());
         }
     }
 
@@ -232,19 +267,47 @@
         }
     }
 
+    public boolean isThreadLocalRequestContext() {
+        if (currentRequestContext.containsKey(THREAD_LOCAL_REQUEST_CONTEXT)) {
+            Object o = currentRequestContext.get(THREAD_LOCAL_REQUEST_CONTEXT);
+            boolean local = false;
+            if (o instanceof Boolean) {
+                local = ((Boolean)o).booleanValue();
+            } else {
+                local = Boolean.parseBoolean(o.toString());
+            }
+            return local;
+        }
+        return false;
+    }
+    public void setThreadLocalRequestContext(boolean b) {
+        currentRequestContext.put(THREAD_LOCAL_REQUEST_CONTEXT, b);
+    }
 
+    
     private Map<String, Object> getRequestContextCopy() {
         Map<String, Object> realMap = new HashMap<String, Object>();
         WrappedMessageContext ctx = new WrappedMessageContext(realMap,
                                                               Scope.APPLICATION);
-        for (Map.Entry<String, Object> ent : requestContext.entrySet()) {
-            ctx.put(ent.getKey(), ent.getValue());
+        // thread local contexts reflect currentRequestContext as of 
+        // last call to getRequestContext()
+        if (isThreadLocalRequestContext()
+            && null != requestContext.get()) {
+            ctx.putAll(requestContext.get());
+        } else {
+            ctx.putAll(currentRequestContext);
         }
         return realMap;
     }
-    
+
     public Map<String, Object> getRequestContext() {
-        return requestContext;
+        if (isThreadLocalRequestContext()) {
+            if (null == requestContext.get()) {
+                requestContext.set(new EchoContext(currentRequestContext));
+            }
+            return requestContext.get();
+        }
+        return currentRequestContext;
     }
 
     public Map<String, Object> getResponseContext() {

Modified: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsProxyFactoryBean.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsProxyFactoryBean.java?rev=637990&r1=637989&r2=637990&view=diff
==============================================================================
--- incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsProxyFactoryBean.java
(original)
+++ incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsProxyFactoryBean.java
Mon Mar 17 10:44:57 2008
@@ -66,6 +66,7 @@
     protected ClientProxy clientClientProxy(Client c) {
         JaxWsClientProxy cp = new JaxWsClientProxy(c, 
                                                    ((JaxWsEndpointImpl)c.getEndpoint()).getJaxwsBinding());
+        cp.getRequestContext().putAll(this.getProperties());
         buildHandlerChain(cp);
         return cp;
     }

Modified: incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/JaxWsClientTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/JaxWsClientTest.java?rev=637990&r1=637989&r2=637990&view=diff
==============================================================================
--- incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/JaxWsClientTest.java
(original)
+++ incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/JaxWsClientTest.java
Mon Mar 17 10:44:57 2008
@@ -106,6 +106,43 @@
     }
 
     @Test
+    public void testRequestContextPutAndRemoveEcho() throws Exception {
+        URL url = getClass().getResource("/wsdl/hello_world.wsdl");
+        javax.xml.ws.Service s = javax.xml.ws.Service
+            .create(url, serviceName);
+        Greeter greeter = s.getPort(portName, Greeter.class);
+        final InvocationHandler handler  = Proxy.getInvocationHandler(greeter);
+                
+        Map<String, Object> requestContext = ((BindingProvider)handler).getRequestContext();
+        requestContext.put(JaxWsClientProxy.THREAD_LOCAL_REQUEST_CONTEXT, Boolean.TRUE);
+        
+        //re-get the context so it's not a thread safe variant
+        requestContext = ((BindingProvider)handler).getRequestContext();
+        
+        final String key = "Hi";
+    
+        requestContext.put(key, "ho");
+        
+        final Object[] result = new Object[2];
+        Thread t = new Thread() {
+            public void run() {
+                Map<String, Object> requestContext = ((BindingProvider)handler).getRequestContext();
+                result[0] = requestContext.get(key);
+                requestContext.remove(key);
+                result[1] = requestContext.get(key);
+            }
+        };
+        t.start();
+        t.join();
+        
+        assertEquals("thread sees the put", "ho", result[0]);
+        assertNull("thread did not remove the put", result[1]);
+        
+        assertEquals("main thread does not see removal", 
+                     "ho", requestContext.get(key));
+    }
+
+    @Test
     public void testEndpoint() throws Exception {
         ReflectionServiceFactoryBean bean = new JaxWsServiceFactoryBean();
         URL resource = getClass().getResource("/wsdl/hello_world.wsdl");

Added: incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxws/JaxWsClientThreadTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxws/JaxWsClientThreadTest.java?rev=637990&view=auto
==============================================================================
--- incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxws/JaxWsClientThreadTest.java
(added)
+++ incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxws/JaxWsClientThreadTest.java
Mon Mar 17 10:44:57 2008
@@ -0,0 +1,121 @@
+/**
+ * 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.cxf.systest.jaxws;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+import javax.xml.ws.BindingProvider;
+import javax.xml.ws.soap.SOAPFaultException;
+
+import org.apache.cxf.jaxws.JaxWsClientProxy;
+import org.apache.cxf.test.AbstractCXFTest;
+import org.apache.hello_world_soap_http.Greeter;
+import org.junit.Test;
+
+public class JaxWsClientThreadTest extends AbstractCXFTest {
+
+    private final QName serviceName = new QName("http://apache.org/hello_world_soap_http",
"SOAPService");
+    private final QName portName = new QName("http://apache.org/hello_world_soap_http", "SoapPort");
+    
+    @Test
+    public void testRequestContextThreadSafety() throws Throwable {
+
+        URL url = getClass().getResource("/wsdl/hello_world.wsdl");
+        javax.xml.ws.Service s = javax.xml.ws.Service.create(url, serviceName);
+        final Greeter greeter = s.getPort(portName, Greeter.class);
+        final InvocationHandler handler = Proxy.getInvocationHandler(greeter);
+
+        ((BindingProvider)handler).getRequestContext().put(JaxWsClientProxy.THREAD_LOCAL_REQUEST_CONTEXT,
+                                                           Boolean.TRUE);
+        
+        Map<String, Object> requestContext = ((BindingProvider)handler).getRequestContext();
+        
+        String address = (String)requestContext.get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
+
+        final Throwable errorHolder[] = new Throwable[1];
+
+        Runnable r = new Runnable() {
+            public void run() {
+                try {
+                    final String protocol = "http-" + Thread.currentThread().getId();
+                    for (int i = 0; i < 70; i++) {
+                        String threadSpecificaddress = protocol + "://localhost:80/" + i;
+                        Map<String, Object> requestContext = ((BindingProvider)handler)
+                                    .getRequestContext();
+                        requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
+                                           threadSpecificaddress);
+                        assertEquals("we get what we set", threadSpecificaddress, requestContext
+                                     .get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY));
+                        try {
+                            greeter.greetMe("Hi");
+                        } catch (SOAPFaultException expected) {
+                            //expected.getCause().printStackTrace();
+                            MalformedURLException mue = (MalformedURLException)expected
+                                .getCause().getCause();
+                            assertTrue("protocol contains thread id from context", mue.getMessage()
+                                .indexOf(protocol) != 0);
+                        }
+                        
+                        requestContext.remove(BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
+                        assertTrue("property is null", requestContext
+                                     .get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY) == null);
+                        
+                    }
+                } catch (Throwable t) {
+                    // capture assert failures
+                    errorHolder[0] = t;
+                }
+            }
+        };
+        
+        final int numThreads = 5;
+        Thread[] threads = new Thread[numThreads];
+        for (int i = 0; i < numThreads; i++) {
+            threads[i] = new Thread(r);
+        }
+        for (int i = 0; i < numThreads; i++) {
+            threads[i].start();
+        }
+        for (int i = 0; i < numThreads; i++) {
+            threads[i].join();
+        }
+        if (errorHolder[0] != null) {
+            throw errorHolder[0];
+        }
+
+        // main thread contextValues are un changed
+        assertTrue("address from existing context has not changed", address.equals(requestContext
+            .get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY)));
+
+        // get the latest values
+        ((JaxWsClientProxy.EchoContext)requestContext).reload();
+        assertTrue("address is different", !address.equals(requestContext
+            .get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY)));
+        // verify value reflects what other threads were doing
+        assertTrue("property is null from last thread execution", requestContext
+                   .get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY) == null);
+    }
+}
+

Propchange: incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxws/JaxWsClientThreadTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxws/JaxWsClientThreadTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date



Mime
View raw message