cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From r...@apache.org
Subject cxf git commit: CXF-6360: Integration with Apache HTrace. Added JAX-WS client-side interceptors and more test cases for HTrace tracing.
Date Fri, 25 Sep 2015 01:41:54 GMT
Repository: cxf
Updated Branches:
  refs/heads/master 008c8835a -> 8a82bbfb5


CXF-6360: Integration with Apache HTrace. Added JAX-WS client-side interceptors and more test
cases for HTrace tracing.


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/8a82bbfb
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/8a82bbfb
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/8a82bbfb

Branch: refs/heads/master
Commit: 8a82bbfb59141801864e74ebe92f499f117ba6ef
Parents: 008c883
Author: reta <drreta@gmail.com>
Authored: Thu Sep 24 21:41:33 2015 -0400
Committer: reta <drreta@gmail.com>
Committed: Thu Sep 24 21:41:33 2015 -0400

----------------------------------------------------------------------
 .../htrace/AbstractHTraceClientInterceptor.java | 62 ++++++++++++++
 .../htrace/AbstractHTraceClientProvider.java    | 87 +++++++++++++++++++
 .../htrace/HTraceClientStartInterceptor.java    | 48 +++++++++++
 .../htrace/HTraceClientStopInterceptor.java     | 41 +++++++++
 .../htrace/jaxrs/HTraceClientProvider.java      | 61 ++------------
 .../apache/cxf/systest/TestSpanReceiver.java    | 66 +++++++++++++++
 .../jaxrs/tracing/htrace/HTraceTracingTest.java | 52 ++++++++++++
 .../jaxrs/tracing/htrace/TestSpanReceiver.java  | 66 ---------------
 .../jaxws/tracing/htrace/HTraceTracingTest.java | 89 ++++++++++++++++++--
 9 files changed, 448 insertions(+), 124 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/8a82bbfb/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/AbstractHTraceClientInterceptor.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/AbstractHTraceClientInterceptor.java
b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/AbstractHTraceClientInterceptor.java
new file mode 100644
index 0000000..4cdbc9c
--- /dev/null
+++ b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/AbstractHTraceClientInterceptor.java
@@ -0,0 +1,62 @@
+/**
+ * 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.tracing.htrace;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.PhaseInterceptor;
+import org.apache.htrace.Sampler;
+
+public abstract class AbstractHTraceClientInterceptor extends AbstractHTraceClientProvider

+        implements PhaseInterceptor<Message> {
+    
+    private String phase;
+
+    protected AbstractHTraceClientInterceptor(final String phase, final Sampler< ? >
sampler) {
+        super(sampler);
+        this.phase = phase;
+    }
+    
+    public Collection<PhaseInterceptor<? extends Message>> getAdditionalInterceptors()
{
+        return null;
+    }
+
+    public Set<String> getAfter() {
+        return Collections.emptySet();
+    }
+
+    public Set<String> getBefore() {
+        return Collections.emptySet();
+    }
+
+    public String getId() {
+        return getClass().getName();
+    }
+
+    public String getPhase() {
+        return phase;
+    }
+    
+    public void handleFault(Message message) {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/8a82bbfb/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/AbstractHTraceClientProvider.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/AbstractHTraceClientProvider.java
b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/AbstractHTraceClientProvider.java
new file mode 100644
index 0000000..d1cbcb0
--- /dev/null
+++ b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/AbstractHTraceClientProvider.java
@@ -0,0 +1,87 @@
+/**
+ * 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.tracing.htrace;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.jaxrs.utils.JAXRSUtils;
+import org.apache.cxf.tracing.AbstractTracingProvider;
+import org.apache.htrace.Sampler;
+import org.apache.htrace.Span;
+import org.apache.htrace.Trace;
+import org.apache.htrace.TraceScope;
+
+public abstract class AbstractHTraceClientProvider extends AbstractTracingProvider { 
+    protected static final Logger LOG = LogUtils.getL7dLogger(AbstractHTraceClientProvider.class);
+    protected static final String TRACE_SPAN = "org.apache.cxf.tracing.htrace.span";
+        
+    private final Sampler< ? > sampler;
+        
+    public AbstractHTraceClientProvider(final Sampler< ? > sampler) {
+        this.sampler = sampler;
+    }
+
+    protected TraceScope startTraceSpan(final Map<String, List<String>> requestHeaders,
String path, String method) {
+        Span span = Trace.currentSpan();
+        TraceScope scope = null;
+        
+        if (span == null) {
+            scope = Trace.startSpan(buildSpanDescription(path, method), sampler);
+            span = scope.getSpan();
+        }
+        
+        if (span != null) {
+            final String traceIdHeader = getTraceIdHeader();
+            final String spanIdHeader = getSpanIdHeader();
+            
+            // Transfer tracing headers into the response headers
+            requestHeaders.put(traceIdHeader, Collections.singletonList(Long.toString(span.getTraceId())));
+            requestHeaders.put(spanIdHeader, Collections.singletonList(Long.toString(span.getSpanId())));
+        }
+        
+        // In case of asynchronous client invocation, the span should be detached as JAX-RS

+        // client request / response filters are going to be executed in different threads.
+        if (isAsyncInvocation() && scope != null) {
+            scope.detach();
+        }
+        
+        return scope;
+    }
+    
+    private boolean isAsyncInvocation() {
+        return !JAXRSUtils.getCurrentMessage().getExchange().isSynchronous();
+    }
+
+    protected void stopTraceSpan(final TraceScope scope) {
+        if (scope != null) {
+            // If the client invocation was asynchronous , the trace scope has been created

+            // in another thread and should be re-attached to the current one.
+            if (scope.isDetached()) {
+                final TraceScope continueSpan = Trace.continueSpan(scope.getSpan()); 
+                continueSpan.close();
+            } else {
+                scope.close();
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/8a82bbfb/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/HTraceClientStartInterceptor.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/HTraceClientStartInterceptor.java
b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/HTraceClientStartInterceptor.java
new file mode 100644
index 0000000..72005eb
--- /dev/null
+++ b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/HTraceClientStartInterceptor.java
@@ -0,0 +1,48 @@
+/**
+ * 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.tracing.htrace;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.Phase;
+import org.apache.htrace.Sampler;
+import org.apache.htrace.TraceScope;
+
+public class HTraceClientStartInterceptor extends AbstractHTraceClientInterceptor {
+    public HTraceClientStartInterceptor(final Sampler< ? > sampler) {
+        this(Phase.PRE_STREAM, sampler);
+    }
+
+    public HTraceClientStartInterceptor(final String phase, final Sampler< ? > sampler)
{
+        super(phase, sampler);
+    }
+
+    @Override
+    public void handleMessage(Message message) throws Fault {
+        Map<String, List<String>> headers = CastUtils.cast((Map<?, ?>)message.get(Message.PROTOCOL_HEADERS));

+        TraceScope scope = super.startTraceSpan(headers, (String)message.get(Message.REQUEST_URI),

+            (String)message.get(Message.HTTP_REQUEST_METHOD));
+        message.getExchange().put(TRACE_SPAN, scope);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/8a82bbfb/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/HTraceClientStopInterceptor.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/HTraceClientStopInterceptor.java
b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/HTraceClientStopInterceptor.java
new file mode 100644
index 0000000..d52fb07
--- /dev/null
+++ b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/HTraceClientStopInterceptor.java
@@ -0,0 +1,41 @@
+/**
+ * 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.tracing.htrace;
+
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.Phase;
+import org.apache.htrace.TraceScope;
+
+public class HTraceClientStopInterceptor extends AbstractHTraceClientInterceptor {
+    public HTraceClientStopInterceptor() {
+        this(Phase.RECEIVE);
+    }
+    
+    public HTraceClientStopInterceptor(final String phase) {
+        super(phase, null);
+    }
+
+    @Override
+    public void handleMessage(Message message) throws Fault {
+        final TraceScope span = (TraceScope)message.getExchange().get(TRACE_SPAN);
+        super.stopTraceSpan(span);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/8a82bbfb/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/jaxrs/HTraceClientProvider.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/jaxrs/HTraceClientProvider.java
b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/jaxrs/HTraceClientProvider.java
index cfd5ca7..7a5f2c1 100644
--- a/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/jaxrs/HTraceClientProvider.java
+++ b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/jaxrs/HTraceClientProvider.java
@@ -24,83 +24,40 @@ import javax.ws.rs.client.ClientRequestContext;
 import javax.ws.rs.client.ClientRequestFilter;
 import javax.ws.rs.client.ClientResponseContext;
 import javax.ws.rs.client.ClientResponseFilter;
-import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.ext.Provider;
 
-import org.apache.cxf.jaxrs.utils.JAXRSUtils;
-import org.apache.cxf.tracing.AbstractTracingProvider;
+import org.apache.cxf.tracing.htrace.AbstractHTraceClientProvider;
 import org.apache.htrace.Sampler;
-import org.apache.htrace.Span;
-import org.apache.htrace.Trace;
 import org.apache.htrace.TraceScope;
 import org.apache.htrace.impl.NeverSampler;
 
 @Provider
-public class HTraceClientProvider extends AbstractTracingProvider 
+public class HTraceClientProvider extends AbstractHTraceClientProvider 
         implements ClientRequestFilter, ClientResponseFilter {
     private static final String TRACE_SPAN = "org.apache.cxf.tracing.client.htrace.span";
     
-    private final Sampler< ? > sampler;
-    
     public HTraceClientProvider() {
         this(NeverSampler.INSTANCE);
     }
 
     public HTraceClientProvider(final Sampler< ? > sampler) {
-        this.sampler = sampler;
+        super(sampler);
     }
 
     @Override
     public void filter(final ClientRequestContext requestContext) throws IOException {
-        Span span = Trace.currentSpan();
-        TraceScope scope = null;
-        
-        if (span == null) {
-            scope = Trace.startSpan(buildSpanDescription(requestContext.getUri().toString(),

-                requestContext.getMethod()), sampler);
-            span = scope.getSpan();
-            
-            if (span != null) {
-                requestContext.setProperty(TRACE_SPAN, scope);
-            }
-        }
-        
-        if (span != null) {
-            final MultivaluedMap<String, Object> requestHeaders = requestContext.getHeaders();
-            
-            final String traceIdHeader = getTraceIdHeader();
-            final String spanIdHeader = getSpanIdHeader();
-            
-            // Transfer tracing headers into the response headers
-            requestHeaders.putSingle(traceIdHeader, Long.toString(span.getTraceId()));
-            requestHeaders.putSingle(spanIdHeader, Long.toString(span.getSpanId()));
-        }
-        
-        // In case of asynchronous client invocation, the span should be detached as JAX-RS

-        // client request / response filters are going to be executed in different threads.
-        if (isAsyncInvocation() && scope != null) {
-            scope.detach();
+        final TraceScope scope = super.startTraceSpan(requestContext.getStringHeaders(),

+            requestContext.getUri().toString(), requestContext.getMethod());
+
+        if (scope != null) {
+            requestContext.setProperty(TRACE_SPAN, scope);
         }
     }
     
     @Override
     public void filter(final ClientRequestContext requestContext,
             final ClientResponseContext responseContext) throws IOException {
-        
         final TraceScope scope = (TraceScope)requestContext.getProperty(TRACE_SPAN);
-        if (scope != null) {
-            // If the client invocation was asynchronous , the trace scope has been created

-            // in another thread and should be re-attached to the current one.
-            if (scope.isDetached()) {
-                final TraceScope continueSpan = Trace.continueSpan(scope.getSpan()); 
-                continueSpan.close();
-            } else {            
-                scope.close();
-            }
-        }
-    }
-    
-    private boolean isAsyncInvocation() {
-        return !JAXRSUtils.getCurrentMessage().getExchange().isSynchronous();
+        super.stopTraceSpan(scope);
     }
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/8a82bbfb/systests/tracing/src/test/java/org/apache/cxf/systest/TestSpanReceiver.java
----------------------------------------------------------------------
diff --git a/systests/tracing/src/test/java/org/apache/cxf/systest/TestSpanReceiver.java b/systests/tracing/src/test/java/org/apache/cxf/systest/TestSpanReceiver.java
new file mode 100644
index 0000000..e5f6c97
--- /dev/null
+++ b/systests/tracing/src/test/java/org/apache/cxf/systest/TestSpanReceiver.java
@@ -0,0 +1,66 @@
+/**
+ * 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;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.htrace.HTraceConfiguration;
+import org.apache.htrace.Span;
+import org.apache.htrace.SpanReceiver;
+import org.apache.htrace.Trace;
+
+/**
+ * Test HTrace Span receiver
+ */
+public class TestSpanReceiver implements SpanReceiver {
+    private static List<Span> spans = new ArrayList<Span>();
+    private static TestSpanReceiver instance;
+
+    public TestSpanReceiver(final HTraceConfiguration conf) {
+        if (instance != null) {
+            Trace.removeReceiver(instance);
+        }
+        instance = this;
+    }
+
+    public Collection<Span> getSpans() {
+        return spans;
+    }
+
+    @Override
+    public void close() throws IOException {
+    }
+
+    @Override
+    public void receiveSpan(Span span) {
+        spans.add(span);
+    }
+    
+    public static void clear() {
+        spans.clear();
+    }
+    
+    public static List<Span> getAllSpans() {
+        return spans;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cxf/blob/8a82bbfb/systests/tracing/src/test/java/org/apache/cxf/systest/jaxrs/tracing/htrace/HTraceTracingTest.java
----------------------------------------------------------------------
diff --git a/systests/tracing/src/test/java/org/apache/cxf/systest/jaxrs/tracing/htrace/HTraceTracingTest.java
b/systests/tracing/src/test/java/org/apache/cxf/systest/jaxrs/tracing/htrace/HTraceTracingTest.java
index 11b7442..74704ba 100644
--- a/systests/tracing/src/test/java/org/apache/cxf/systest/jaxrs/tracing/htrace/HTraceTracingTest.java
+++ b/systests/tracing/src/test/java/org/apache/cxf/systest/jaxrs/tracing/htrace/HTraceTracingTest.java
@@ -18,6 +18,7 @@
  */
 package org.apache.cxf.systest.jaxrs.tracing.htrace;
 
+import java.net.MalformedURLException;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
@@ -34,6 +35,7 @@ import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
 import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
 import org.apache.cxf.jaxrs.model.AbstractResourceInfo;
+import org.apache.cxf.systest.TestSpanReceiver;
 import org.apache.cxf.systest.jaxrs.tracing.BookStore;
 import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
 import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
@@ -41,6 +43,8 @@ import org.apache.cxf.tracing.TracerHeaders;
 import org.apache.cxf.tracing.htrace.jaxrs.HTraceClientProvider;
 import org.apache.cxf.tracing.htrace.jaxrs.HTraceFeature;
 import org.apache.htrace.HTraceConfiguration;
+import org.apache.htrace.Trace;
+import org.apache.htrace.TraceScope;
 import org.apache.htrace.impl.AlwaysSampler;
 import org.junit.Before;
 import org.junit.BeforeClass;
@@ -222,6 +226,54 @@ public class HTraceTracingTest extends AbstractBusClientServerTestBase
{
         assertTrue(r.getHeaders().containsKey(TracerHeaders.DEFAULT_HEADER_SPAN_ID));
     }
     
+    @Test
+    public void testThatProvidedSpanIsNotClosedWhenActive() throws MalformedURLException
{
+        final Map<String, String> properties = new HashMap<String, String>();
+        final HTraceConfiguration conf = HTraceConfiguration.fromMap(properties);       

+        final AlwaysSampler sampler = new AlwaysSampler(conf);
+        
+        try (final TraceScope scope = Trace.startSpan("test span", sampler)) {
+            final Response r = createWebClient("/bookstore/books", htraceClientProvider).get();
+            assertEquals(Status.OK.getStatusCode(), r.getStatus());
+            
+            assertThat(TestSpanReceiver.getAllSpans().size(), equalTo(2));
+            assertThat(TestSpanReceiver.getAllSpans().get(0).getDescription(), equalTo("Get
Books"));
+            assertThat(TestSpanReceiver.getAllSpans().get(0).getParents().length, equalTo(1));
+            assertThat(TestSpanReceiver.getAllSpans().get(1).getDescription(), equalTo("GET
bookstore/books"));
+            
+            assertTrue(r.getHeaders().containsKey(TracerHeaders.DEFAULT_HEADER_TRACE_ID));
+            assertTrue(r.getHeaders().containsKey(TracerHeaders.DEFAULT_HEADER_SPAN_ID));
+        }
+        
+        assertThat(TestSpanReceiver.getAllSpans().size(), equalTo(3));
+        assertThat(TestSpanReceiver.getAllSpans().get(2).getDescription(), equalTo("test
span"));
+    }
+    
+    @Test
+    public void testThatProvidedSpanIsNotDetachedWhenActiveUsingAsyncClient() throws Exception
{
+        final Map<String, String> properties = new HashMap<String, String>();
+        final HTraceConfiguration conf = HTraceConfiguration.fromMap(properties);       

+        final AlwaysSampler sampler = new AlwaysSampler(conf);
+
+        final WebClient client = createWebClient("/bookstore/books", htraceClientProvider);
+        try (final TraceScope scope = Trace.startSpan("test span", sampler)) {
+            final Future<Response> f = client.async().get();
+        
+            final Response r = f.get(1, TimeUnit.SECONDS);
+            assertEquals(Status.OK.getStatusCode(), r.getStatus());
+            assertThat(scope.isDetached(), equalTo(false));
+            
+            assertThat(TestSpanReceiver.getAllSpans().size(), equalTo(2));
+            assertThat(TestSpanReceiver.getAllSpans().get(0).getDescription(), equalTo("Get
Books"));
+            assertThat(TestSpanReceiver.getAllSpans().get(1).getDescription(), equalTo("GET
bookstore/books"));
+            
+            assertTrue(r.getHeaders().containsKey(TracerHeaders.DEFAULT_HEADER_TRACE_ID));
+            assertTrue(r.getHeaders().containsKey(TracerHeaders.DEFAULT_HEADER_SPAN_ID));
+        }
+        
+        assertThat(TestSpanReceiver.getAllSpans().get(2).getDescription(), equalTo("test
span"));
+    }
+    
     protected WebClient createWebClient(final String url, final Object ... providers) {
         return WebClient
             .create("http://localhost:" + PORT + url, Arrays.asList(providers))

http://git-wip-us.apache.org/repos/asf/cxf/blob/8a82bbfb/systests/tracing/src/test/java/org/apache/cxf/systest/jaxrs/tracing/htrace/TestSpanReceiver.java
----------------------------------------------------------------------
diff --git a/systests/tracing/src/test/java/org/apache/cxf/systest/jaxrs/tracing/htrace/TestSpanReceiver.java
b/systests/tracing/src/test/java/org/apache/cxf/systest/jaxrs/tracing/htrace/TestSpanReceiver.java
deleted file mode 100644
index 6567422..0000000
--- a/systests/tracing/src/test/java/org/apache/cxf/systest/jaxrs/tracing/htrace/TestSpanReceiver.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * 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.jaxrs.tracing.htrace;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import org.apache.htrace.HTraceConfiguration;
-import org.apache.htrace.Span;
-import org.apache.htrace.SpanReceiver;
-import org.apache.htrace.Trace;
-
-/**
- * Test HTrace Span receiver
- */
-public class TestSpanReceiver implements SpanReceiver {
-    private static List<Span> spans = new ArrayList<Span>();
-    private static TestSpanReceiver instance;
-
-    public TestSpanReceiver(final HTraceConfiguration conf) {
-        if (instance != null) {
-            Trace.removeReceiver(instance);
-        }
-        instance = this;
-    }
-
-    public Collection<Span> getSpans() {
-        return spans;
-    }
-
-    @Override
-    public void close() throws IOException {
-    }
-
-    @Override
-    public void receiveSpan(Span span) {
-        spans.add(span);
-    }
-    
-    public static void clear() {
-        spans.clear();
-    }
-    
-    public static List<Span> getAllSpans() {
-        return spans;
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cxf/blob/8a82bbfb/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/htrace/HTraceTracingTest.java
----------------------------------------------------------------------
diff --git a/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/htrace/HTraceTracingTest.java
b/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/htrace/HTraceTracingTest.java
index 684a4b4..66810c1 100644
--- a/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/htrace/HTraceTracingTest.java
+++ b/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/htrace/HTraceTracingTest.java
@@ -33,16 +33,19 @@ import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
 import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.phase.Phase;
-import org.apache.cxf.systest.jaxrs.tracing.htrace.TestSpanReceiver;
+import org.apache.cxf.systest.TestSpanReceiver;
 import org.apache.cxf.systest.jaxws.tracing.BookStore;
 import org.apache.cxf.systest.jaxws.tracing.BookStoreService;
 import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
 import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
 import org.apache.cxf.tracing.TracerHeaders;
+import org.apache.cxf.tracing.htrace.HTraceClientStartInterceptor;
+import org.apache.cxf.tracing.htrace.HTraceClientStopInterceptor;
 import org.apache.cxf.tracing.htrace.HTraceStartInterceptor;
 import org.apache.cxf.tracing.htrace.HTraceStopInterceptor;
 import org.apache.htrace.HTraceConfiguration;
 import org.apache.htrace.Trace;
+import org.apache.htrace.TraceScope;
 import org.apache.htrace.impl.AlwaysSampler;
 import org.junit.Before;
 import org.junit.BeforeClass;
@@ -51,6 +54,7 @@ import org.junit.Test;
 
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.CoreMatchers.hasItems;
+import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.CoreMatchers.nullValue;
 
 public class HTraceTracingTest extends AbstractBusClientServerTestBase {
@@ -72,6 +76,10 @@ public class HTraceTracingTest extends AbstractBusClientServerTestBase
{
         }
     }
     
+    private interface Configurator {
+        void configure(final JaxWsProxyFactoryBean factory);
+    }
+    
     @BeforeClass
     public static void startServers() throws Exception {
         //keep out of process due to stack traces testing failures
@@ -100,13 +108,11 @@ public class HTraceTracingTest extends AbstractBusClientServerTestBase
{
     
     @Test
     public void testThatNewInnerSpanIsCreated() throws MalformedURLException {
-        final BookStoreService service = createJaxWsService();
-        final Client proxy = ClientProxy.getClient(service);
-        
         final Map<String, List<String>> headers = new HashMap<String, List<String>>();
         headers.put(TracerHeaders.DEFAULT_HEADER_TRACE_ID, Arrays.asList("10"));
         headers.put(TracerHeaders.DEFAULT_HEADER_SPAN_ID, Arrays.asList("20"));
-        proxy.getRequestContext().put(Message.PROTOCOL_HEADERS, headers);
+
+        final BookStoreService service = createJaxWsService(headers);
         assertThat(service.getBooks().size(), equalTo(2));
         
         assertThat(TestSpanReceiver.getAllSpans().size(), equalTo(2));
@@ -118,22 +124,93 @@ public class HTraceTracingTest extends AbstractBusClientServerTestBase
{
         assertThat(response.get(TracerHeaders.DEFAULT_HEADER_SPAN_ID), hasItems("20"));
     }
     
+    @Test
+    public void testThatNewChildSpanIsCreatedWhenParentIsProvided() throws MalformedURLException
{
+        final Map<String, String> properties = new HashMap<String, String>();
+        final HTraceConfiguration conf = HTraceConfiguration.fromMap(properties);
+    
+        final BookStoreService service = createJaxWsService(new Configurator() {
+            @Override
+            public void configure(final JaxWsProxyFactoryBean factory) {
+                factory.getOutInterceptors().add(new HTraceClientStartInterceptor(new AlwaysSampler(conf)));
+                factory.getInInterceptors().add(new HTraceClientStopInterceptor());
+            }
+        });
+        assertThat(service.getBooks().size(), equalTo(2));
+        
+        assertThat(TestSpanReceiver.getAllSpans().size(), equalTo(3));
+        assertThat(TestSpanReceiver.getAllSpans().get(0).getDescription(), equalTo("Get Books"));
+        assertThat(TestSpanReceiver.getAllSpans().get(0).getParents().length, equalTo(1));
+        
+        final Map<String, List<String>> response = getResponseHeaders(service);
+        assertThat(response.get(TracerHeaders.DEFAULT_HEADER_TRACE_ID), not(nullValue()));
+        assertThat(response.get(TracerHeaders.DEFAULT_HEADER_SPAN_ID), not(nullValue()));
+    }
+    
+    @Test
+    public void testThatProvidedSpanIsNotClosedWhenActive() throws MalformedURLException
{
+        final Map<String, String> properties = new HashMap<String, String>();
+        final HTraceConfiguration conf = HTraceConfiguration.fromMap(properties);
+    
+        final AlwaysSampler sampler = new AlwaysSampler(conf);
+        final BookStoreService service = createJaxWsService(new Configurator() {
+            @Override
+            public void configure(final JaxWsProxyFactoryBean factory) {
+                
+                factory.getOutInterceptors().add(new HTraceClientStartInterceptor(sampler));
+                factory.getInInterceptors().add(new HTraceClientStopInterceptor());
+            }
+        });
+        
+        try (final TraceScope scope = Trace.startSpan("test span", sampler)) {
+            assertThat(service.getBooks().size(), equalTo(2));
+            assertThat(Trace.isTracing(), equalTo(true));
+            
+            assertThat(TestSpanReceiver.getAllSpans().size(), equalTo(2));
+            assertThat(TestSpanReceiver.getAllSpans().get(0).getDescription(), equalTo("Get
Books"));
+            assertThat(TestSpanReceiver.getAllSpans().get(0).getParents().length, equalTo(1));
+            assertThat(TestSpanReceiver.getAllSpans().get(1).getDescription(), equalTo("POST
/BookStore"));        
+        }
+        
+        assertThat(TestSpanReceiver.getAllSpans().size(), equalTo(3));
+        assertThat(TestSpanReceiver.getAllSpans().get(2).getDescription(), equalTo("test
span"));
+        
+        final Map<String, List<String>> response = getResponseHeaders(service);
+        assertThat(response.get(TracerHeaders.DEFAULT_HEADER_TRACE_ID), not(nullValue()));
+        assertThat(response.get(TracerHeaders.DEFAULT_HEADER_SPAN_ID), not(nullValue()));
+    }
+    
+    
     private BookStoreService createJaxWsService() throws MalformedURLException {
         return createJaxWsService(new HashMap<String, List<String>>());
     }
     
     private BookStoreService createJaxWsService(final Map<String, List<String>>
headers) throws MalformedURLException {
+        return createJaxWsService(headers, null);
+    }
+    
+    private BookStoreService createJaxWsService(final Configurator configurator) throws MalformedURLException
{
+        return createJaxWsService(new HashMap<String, List<String>>(), configurator);
+    }
+
+    private BookStoreService createJaxWsService(final Map<String, List<String>>
headers, 
+            final Configurator configurator) throws MalformedURLException {
+
         JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
         factory.getOutInterceptors().add(new LoggingOutInterceptor());
         factory.getInInterceptors().add(new LoggingInInterceptor());
         factory.setServiceClass(BookStoreService.class);
         factory.setAddress("http://localhost:" + PORT + "/BookStore");
         
+        if (configurator != null) {
+            configurator.configure(factory);
+        }
+        
         final BookStoreService service = (BookStoreService) factory.create();
         final Client proxy = ClientProxy.getClient(service);
         proxy.getRequestContext().put(Message.PROTOCOL_HEADERS, headers);
         
-        return (BookStoreService) factory.create();
+        return service;
     }
     
     private Map<String, List<String>> getResponseHeaders(final BookStoreService
service) {


Mime
View raw message