You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by re...@apache.org on 2017/01/05 14:39:14 UTC

cxf git commit: CXF-7164: Support tracing using OpenZipkin Brave. Refactored JAX-wS implementation, added more test cases.

Repository: cxf
Updated Branches:
  refs/heads/master 33c767136 -> 69826a090


CXF-7164: Support tracing using OpenZipkin Brave. Refactored JAX-wS implementation, added more test cases.


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

Branch: refs/heads/master
Commit: 69826a090e5f7868b9633e69b76f051fa15b65ef
Parents: 33c7671
Author: reta <dr...@gmail.com>
Authored: Thu Jan 5 09:38:56 2017 -0500
Committer: reta <dr...@gmail.com>
Committed: Thu Jan 5 09:38:56 2017 -0500

----------------------------------------------------------------------
 .../brave/AbstractBraveClientInterceptor.java   |  63 ++++
 .../tracing/brave/AbstractBraveInterceptor.java | 101 +++---
 .../tracing/brave/AbstractBraveProvider.java    |  10 +-
 .../cxf/tracing/brave/BraveClientFeature.java   |  50 +++
 .../brave/BraveClientStartInterceptor.java      |  50 +++
 .../brave/BraveClientStopInterceptor.java       |  50 +++
 .../apache/cxf/tracing/brave/BraveFeature.java  |   9 +-
 .../tracing/brave/BraveStartInterceptor.java    |  27 +-
 .../cxf/tracing/brave/BraveStopInterceptor.java |  42 ++-
 .../cxf/tracing/brave/BraveTraceTest.java       |   9 +-
 systests/tracing/pom.xml                        |   5 +
 .../cxf/systest/jaxws/tracing/BookStore.java    |  43 ---
 .../systest/jaxws/tracing/BookStoreService.java |   1 +
 .../systest/jaxws/tracing/brave/BookStore.java  |  68 ++++
 .../jaxws/tracing/brave/BraveTracingTest.java   | 309 +++++++++++++++++++
 .../systest/jaxws/tracing/htrace/BookStore.java |  49 +++
 .../jaxws/tracing/htrace/HTraceTracingTest.java |   5 +-
 17 files changed, 750 insertions(+), 141 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/69826a09/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/AbstractBraveClientInterceptor.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/AbstractBraveClientInterceptor.java b/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/AbstractBraveClientInterceptor.java
new file mode 100644
index 0000000..1780f56
--- /dev/null
+++ b/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/AbstractBraveClientInterceptor.java
@@ -0,0 +1,63 @@
+/**
+ * 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.brave;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+import com.github.kristofa.brave.Brave;
+
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.PhaseInterceptor;
+
+public abstract class AbstractBraveClientInterceptor extends AbstractBraveClientProvider 
+        implements PhaseInterceptor<Message> {
+    
+    private String phase;
+
+    protected AbstractBraveClientInterceptor(final String phase, final Brave brave) {
+        super(brave);
+        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/69826a09/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/AbstractBraveInterceptor.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/AbstractBraveInterceptor.java b/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/AbstractBraveInterceptor.java
index 32e2560..001fc8e 100644
--- a/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/AbstractBraveInterceptor.java
+++ b/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/AbstractBraveInterceptor.java
@@ -21,25 +21,25 @@ package org.apache.cxf.tracing.brave;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import com.github.kristofa.brave.Brave;
-import com.github.kristofa.brave.http.HttpClientRequest;
-import com.github.kristofa.brave.http.HttpServerRequest;
 import com.github.kristofa.brave.http.SpanNameProvider;
 
 import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.message.MessageUtils;
-import org.apache.cxf.phase.AbstractPhaseInterceptor;
+import org.apache.cxf.phase.PhaseInterceptor;
 
-public abstract class AbstractBraveInterceptor extends AbstractPhaseInterceptor<Message> {
-    protected final Brave brave;
-    protected final SpanNameProvider spanNameProvider;
+public abstract class AbstractBraveInterceptor extends AbstractBraveProvider implements PhaseInterceptor<Message> {
+    private final String phase;
     
-    private static class ParsedMessage {
+    protected static class ParsedMessage {
         private Message message;
 
         ParsedMessage(Message message) {
@@ -54,7 +54,7 @@ public abstract class AbstractBraveInterceptor extends AbstractPhaseInterceptor<
             return (value instanceof String) ? value.toString() : null;
         }
         
-        public String getUriSt() {
+        private String getUriSt() {
             String uri = safeGet(Message.REQUEST_URL);
             if (uri == null) {
                 String address = safeGet(Message.ENDPOINT_ADDRESS);
@@ -78,7 +78,7 @@ public abstract class AbstractBraveInterceptor extends AbstractPhaseInterceptor<
             }
         }
         
-        public URI getUri() {
+        URI getUri() {
             try {
                 String uriSt = getUriSt();
                 return uriSt != null ? new URI(uriSt) : new URI("");
@@ -97,21 +97,14 @@ public abstract class AbstractBraveInterceptor extends AbstractPhaseInterceptor<
             }
         }
         
-        Map<String, String> getHeaders() {
+        Map<String, List<String>> getHeaders() {
             Map<String, List<String>> headers = CastUtils.cast((Map<?, ?>)message.get(Message.PROTOCOL_HEADERS));
-            Map<String, String> result = new HashMap<>();
+
             if (headers == null) {
-                return result;
-            }
-            for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
-                if (entry.getValue().size() == 1) {
-                    result.put(entry.getKey(), entry.getValue().get(0));
-                } else {
-                    String[] valueAr = entry.getValue().toArray(new String[] {});
-                    result.put(entry.getKey(), valueAr.toString());
-                }
+                return Collections.emptyMap();
             }
-            return result;
+
+            return headers;
         }
         
         void addHeader(String key, String value) {
@@ -123,57 +116,43 @@ public abstract class AbstractBraveInterceptor extends AbstractPhaseInterceptor<
             headers.put(key, Arrays.asList(value));
         }
 
-        public String getHttpMethod() {
+        String getHttpMethod() {
             ParsedMessage eMessage = new ParsedMessage(getEffectiveMessage());
             return eMessage.safeGet(Message.HTTP_REQUEST_METHOD);
         }
     }
 
     protected AbstractBraveInterceptor(String phase, Brave brave, SpanNameProvider spanNameProvider) {
-        super(phase);
-        this.brave = brave;
-        this.spanNameProvider = spanNameProvider;
+        super(brave, spanNameProvider);
+        this.phase = phase;
     }
     
-    protected HttpClientRequest getClientRequest(final Message message) {
-        final ParsedMessage parsedMessage = new ParsedMessage(message);
-        
-        return new HttpClientRequest() {
-            @Override
-            public URI getUri() {
-                return parsedMessage.getUri();
-            }
-
-            @Override
-            public String getHttpMethod() {
-                return parsedMessage.getHttpMethod();
-            }
+    @Override
+    public Set<String> getAfter() {
+        return Collections.emptySet();
+    }
 
-            @Override
-            public void addHeader(String header, String value) {
-                parsedMessage.addHeader(header, value);
-            }
-        };
+    @Override
+    public Set<String> getBefore() {
+        return Collections.emptySet();
     }
-    
-    protected HttpServerRequest getServerRequest(final Message message) {
-        final ParsedMessage parsedMessage = new ParsedMessage(message);
-        
-        return new HttpServerRequest() {
-            @Override
-            public URI getUri() {
-                return parsedMessage.getUri();
-            }
 
-            @Override
-            public String getHttpMethod() {
-                return parsedMessage.getHttpMethod();
-            }
+    @Override
+    public String getId() {
+        return getClass().getName();
+    }
 
-            @Override
-            public String getHttpHeaderValue(String headerName) {
-                return parsedMessage.getHeaders().get(headerName);
-            }
-        };
+    @Override
+    public String getPhase() {
+        return phase;
+    }
+    
+    @Override
+    public Collection<PhaseInterceptor<? extends Message>> getAdditionalInterceptors() {
+        return null;
+    }
+    
+    @Override
+    public void handleFault(Message message) {
     }
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/69826a09/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/AbstractBraveProvider.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/AbstractBraveProvider.java b/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/AbstractBraveProvider.java
index 306923f..576b7f9 100644
--- a/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/AbstractBraveProvider.java
+++ b/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/AbstractBraveProvider.java
@@ -41,10 +41,14 @@ public abstract class AbstractBraveProvider extends AbstractTracingProvider {
     protected static final Logger LOG = LogUtils.getL7dLogger(AbstractBraveProvider.class);
     protected static final String TRACE_SPAN = "org.apache.cxf.tracing.brave.span";
         
-    private final Brave brave;
-    private final SpanNameProvider spanNameProvider;
+    protected final Brave brave;
+    protected final SpanNameProvider spanNameProvider;
             
-    public AbstractBraveProvider(final Brave brave) {
+    protected AbstractBraveProvider(final Brave brave) {
+        this(brave, new ServerSpanNameProvider());
+    }
+    
+    protected AbstractBraveProvider(final Brave brave, final SpanNameProvider spanNameProvider) {
         this.brave = brave;
         this.spanNameProvider = new ServerSpanNameProvider();
     }

http://git-wip-us.apache.org/repos/asf/cxf/blob/69826a09/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveClientFeature.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveClientFeature.java b/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveClientFeature.java
new file mode 100644
index 0000000..039b241
--- /dev/null
+++ b/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveClientFeature.java
@@ -0,0 +1,50 @@
+/**
+ * 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.brave;
+
+import com.github.kristofa.brave.Brave;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.annotations.Provider;
+import org.apache.cxf.annotations.Provider.Scope;
+import org.apache.cxf.annotations.Provider.Type;
+import org.apache.cxf.common.injection.NoJSR250Annotations;
+import org.apache.cxf.feature.AbstractFeature;
+import org.apache.cxf.interceptor.InterceptorProvider;
+
+@NoJSR250Annotations
+@Provider(value = Type.Feature, scope = Scope.Client)
+public class BraveClientFeature extends AbstractFeature {
+    private BraveClientStartInterceptor out;
+    private BraveClientStopInterceptor in;
+
+    public BraveClientFeature(Brave brave) {
+        out = new BraveClientStartInterceptor(brave);
+        in = new BraveClientStopInterceptor(brave);
+    }
+
+    @Override
+    protected void initializeProvider(InterceptorProvider provider, Bus bus) {
+        provider.getInInterceptors().add(in);
+        provider.getInFaultInterceptors().add(in);
+
+        provider.getOutInterceptors().add(out);
+        provider.getOutFaultInterceptors().add(out);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/69826a09/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveClientStartInterceptor.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveClientStartInterceptor.java b/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveClientStartInterceptor.java
new file mode 100644
index 0000000..d6775e9
--- /dev/null
+++ b/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveClientStartInterceptor.java
@@ -0,0 +1,50 @@
+/**
+ * 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.brave;
+
+import com.github.kristofa.brave.Brave;
+import com.twitter.zipkin.gen.Span;
+
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.Phase;
+import org.apache.cxf.tracing.brave.AbstractBraveInterceptor.ParsedMessage;
+
+public class BraveClientStartInterceptor extends AbstractBraveClientInterceptor {
+    public BraveClientStartInterceptor(final Brave brave) {
+        this(Phase.PRE_STREAM, brave);
+    }
+
+    public BraveClientStartInterceptor(final String phase, final Brave brave) {
+        super(phase, brave);
+    }
+
+    @Override
+    public void handleMessage(Message message) throws Fault {
+        final ParsedMessage parsed = new ParsedMessage(message);
+        
+        final TraceScopeHolder<Span> holder = super.startTraceSpan(parsed.getHeaders(), 
+            parsed.getUri(), parsed.getHttpMethod());
+        
+        if (holder != null) {
+            message.getExchange().put(TRACE_SPAN, holder);
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/69826a09/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveClientStopInterceptor.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveClientStopInterceptor.java b/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveClientStopInterceptor.java
new file mode 100644
index 0000000..583227c
--- /dev/null
+++ b/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveClientStopInterceptor.java
@@ -0,0 +1,50 @@
+/**
+ * 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.brave;
+
+import com.github.kristofa.brave.Brave;
+import com.twitter.zipkin.gen.Span;
+
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.Phase;
+
+public class BraveClientStopInterceptor extends AbstractBraveClientInterceptor {
+    public BraveClientStopInterceptor(final Brave brave) {
+        this(Phase.RECEIVE, brave);
+    }
+    
+    public BraveClientStopInterceptor(final String phase, final Brave brave) {
+        super(phase, brave);
+    }
+
+    @Override
+    public void handleMessage(Message message) throws Fault {
+        @SuppressWarnings("unchecked")
+        final TraceScopeHolder<Span> holder = 
+            (TraceScopeHolder<Span>)message.getExchange().get(TRACE_SPAN);
+        
+        Integer responseCode = (Integer)message.get(Message.RESPONSE_CODE);
+        if (responseCode == null) {
+            responseCode = 200;
+        }
+        
+        super.stopTraceSpan(holder, responseCode);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/69826a09/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveFeature.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveFeature.java b/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveFeature.java
index 7b352bf..0ba3fc3 100644
--- a/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveFeature.java
+++ b/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveFeature.java
@@ -19,25 +19,24 @@
 package org.apache.cxf.tracing.brave;
 
 import com.github.kristofa.brave.Brave;
-import com.github.kristofa.brave.http.DefaultSpanNameProvider;
 
 import org.apache.cxf.Bus;
 import org.apache.cxf.annotations.Provider;
+import org.apache.cxf.annotations.Provider.Scope;
 import org.apache.cxf.annotations.Provider.Type;
 import org.apache.cxf.common.injection.NoJSR250Annotations;
 import org.apache.cxf.feature.AbstractFeature;
 import org.apache.cxf.interceptor.InterceptorProvider;
 
 @NoJSR250Annotations
-@Provider(value = Type.Feature)
+@Provider(value = Type.Feature, scope = Scope.Server)
 public class BraveFeature extends AbstractFeature {
     private BraveStartInterceptor in;
     private BraveStopInterceptor out;
 
     public BraveFeature(Brave brave) {
-        DefaultSpanNameProvider nameProvider = new DefaultSpanNameProvider();
-        in = new BraveStartInterceptor(brave, nameProvider);
-        out = new BraveStopInterceptor(brave, nameProvider);
+        in = new BraveStartInterceptor(brave);
+        out = new BraveStopInterceptor(brave);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cxf/blob/69826a09/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveStartInterceptor.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveStartInterceptor.java b/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveStartInterceptor.java
index c075aaa..466482e 100644
--- a/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveStartInterceptor.java
+++ b/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveStartInterceptor.java
@@ -19,31 +19,28 @@
 package org.apache.cxf.tracing.brave;
 
 import com.github.kristofa.brave.Brave;
-import com.github.kristofa.brave.http.HttpClientResponseAdapter;
-import com.github.kristofa.brave.http.HttpServerRequestAdapter;
-import com.github.kristofa.brave.http.SpanNameProvider;
+import com.github.kristofa.brave.ServerSpan;
+
 import org.apache.cxf.common.injection.NoJSR250Annotations;
 import org.apache.cxf.interceptor.Fault;
 import org.apache.cxf.message.Message;
-import org.apache.cxf.message.MessageUtils;
 import org.apache.cxf.phase.Phase;
 
-/**
- * 
- */
 @NoJSR250Annotations
 public class BraveStartInterceptor extends AbstractBraveInterceptor {
-    public BraveStartInterceptor(Brave brave, SpanNameProvider spanNameProvider) {
-        super(Phase.PRE_INVOKE, brave, spanNameProvider);
+    public BraveStartInterceptor(Brave brave) {
+        super(Phase.PRE_INVOKE, brave, new ServerSpanNameProvider());
     }
 
+    @Override
     public void handleMessage(Message message) throws Fault {       
-        if (MessageUtils.isRequestor(message)) {
-            brave.clientResponseInterceptor().handle(new HttpClientResponseAdapter(() -> 200));
-        } else {
-            HttpServerRequestAdapter adapter = 
-                new HttpServerRequestAdapter(getServerRequest(message), spanNameProvider);
-            brave.serverRequestInterceptor().handle(adapter);
+        final ParsedMessage parsed = new ParsedMessage(message);
+        
+        final TraceScopeHolder<ServerSpan> holder = super.startTraceSpan(parsed.getHeaders(), 
+            parsed.getUri(), parsed.getHttpMethod());
+        
+        if (holder != null) {
+            message.getExchange().put(TRACE_SPAN, holder);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/69826a09/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveStopInterceptor.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveStopInterceptor.java b/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveStopInterceptor.java
index de01464..616af9f 100644
--- a/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveStopInterceptor.java
+++ b/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/BraveStopInterceptor.java
@@ -18,11 +18,15 @@
  */
 package org.apache.cxf.tracing.brave;
 
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 import com.github.kristofa.brave.Brave;
-import com.github.kristofa.brave.http.HttpClientRequestAdapter;
-import com.github.kristofa.brave.http.HttpServerResponseAdapter;
-import com.github.kristofa.brave.http.SpanNameProvider;
+import com.github.kristofa.brave.ServerSpan;
+
 import org.apache.cxf.common.injection.NoJSR250Annotations;
+import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.interceptor.Fault;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.message.MessageUtils;
@@ -33,16 +37,34 @@ import org.apache.cxf.phase.Phase;
  */
 @NoJSR250Annotations
 public class BraveStopInterceptor extends AbstractBraveInterceptor {
-    public BraveStopInterceptor(Brave brave, SpanNameProvider spanNameProvider) {
-        super(Phase.PRE_PROTOCOL, brave, spanNameProvider);
+    public BraveStopInterceptor(final Brave brave) {
+        super(Phase.PRE_MARSHAL, brave, new ServerSpanNameProvider());
     }
 
+    @Override
     public void handleMessage(Message message) throws Fault {
-        if (MessageUtils.isRequestor(message)) {
-            brave.clientRequestInterceptor().handle(
-                new HttpClientRequestAdapter(getClientRequest(message), spanNameProvider));
-        } else {
-            brave.serverResponseInterceptor().handle(new HttpServerResponseAdapter(() -> 200));
+        Map<String, List<Object>> responseHeaders = CastUtils.cast((Map<?, ?>)message.get(Message.PROTOCOL_HEADERS));
+        
+        if (responseHeaders == null) {
+            responseHeaders = new HashMap<String, List<Object>>();
+            message.put(Message.PROTOCOL_HEADERS, responseHeaders);
+        }
+        
+        boolean isRequestor = MessageUtils.isRequestor(message);
+        Message requestMessage = isRequestor ? message.getExchange().getOutMessage() 
+            : message.getExchange().getInMessage();
+        Map<String, List<String>> requestHeaders =  
+            CastUtils.cast((Map<?, ?>)requestMessage.get(Message.PROTOCOL_HEADERS));
+        
+        @SuppressWarnings("unchecked")
+        final TraceScopeHolder<ServerSpan> holder = 
+            (TraceScopeHolder<ServerSpan>)message.getExchange().get(TRACE_SPAN);
+        
+        Integer responseCode = (Integer)message.get(Message.RESPONSE_CODE);
+        if (responseCode == null) {
+            responseCode = 200; 
         }
+        
+        super.stopTraceSpan(requestHeaders, responseHeaders, responseCode, holder);
     }
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/69826a09/integration/tracing/tracing-brave/src/test/java/org/apache/cxf/tracing/brave/BraveTraceTest.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-brave/src/test/java/org/apache/cxf/tracing/brave/BraveTraceTest.java b/integration/tracing/tracing-brave/src/test/java/org/apache/cxf/tracing/brave/BraveTraceTest.java
index 3c4b3d4..bc6b27b 100644
--- a/integration/tracing/tracing-brave/src/test/java/org/apache/cxf/tracing/brave/BraveTraceTest.java
+++ b/integration/tracing/tracing-brave/src/test/java/org/apache/cxf/tracing/brave/BraveTraceTest.java
@@ -40,18 +40,20 @@ public class BraveTraceTest {
     private static final String ADDRESS = "http://localhost:8182";
     private Server server;
     private BraveFeature logging;
+    private BraveClientFeature clientLogging;
     private Localreporter localReporter;
 
     @Before
     public void startServer() {
         localReporter = new Localreporter();
         logging = createLoggingFeature(localReporter);
+        clientLogging = createClientLoggingFeature(localReporter);
         server = createServer(logging);
     }
 
     @Test
     public void testMyService() {
-        MyService myService = createProxy(logging);
+        MyService myService = createProxy(clientLogging);
         myService.echo("test");
         for (Span span : localReporter.spans) {
             System.out.println(span);
@@ -86,6 +88,11 @@ public class BraveTraceTest {
         return new BraveFeature(brave);
     }
     
+    private static BraveClientFeature createClientLoggingFeature(Reporter<Span> reporter) {
+        Brave brave = new Brave.Builder("myservice").reporter(reporter).build();
+        return new BraveClientFeature(brave);
+    }
+    
     static final class Localreporter implements Reporter<Span> {
         List<Span> spans = new ArrayList<Span>();
 

http://git-wip-us.apache.org/repos/asf/cxf/blob/69826a09/systests/tracing/pom.xml
----------------------------------------------------------------------
diff --git a/systests/tracing/pom.xml b/systests/tracing/pom.xml
index 6028f38..2f1e0f6 100644
--- a/systests/tracing/pom.xml
+++ b/systests/tracing/pom.xml
@@ -65,6 +65,11 @@
         </dependency>
         <dependency>
             <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-features-logging</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
             <artifactId>cxf-rt-frontend-jaxrs</artifactId>
             <version>${project.version}</version>
         </dependency>

http://git-wip-us.apache.org/repos/asf/cxf/blob/69826a09/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/BookStore.java
----------------------------------------------------------------------
diff --git a/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/BookStore.java b/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/BookStore.java
deleted file mode 100644
index 602c86e..0000000
--- a/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/BookStore.java
+++ /dev/null
@@ -1,43 +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.jaxws.tracing;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.UUID;
-
-import javax.jws.WebMethod;
-import javax.jws.WebService;
-
-import org.apache.cxf.systest.Book;
-import org.apache.htrace.core.TraceScope;
-import org.apache.htrace.core.Tracer;
-
-@WebService(endpointInterface = "org.apache.cxf.systest.jaxws.tracing.BookStoreService", serviceName = "BookStore")
-public class BookStore implements BookStoreService {
-    @WebMethod
-    public Collection< Book > getBooks() {
-        try (TraceScope span = Tracer.curThreadTracer().newScope("Get Books")) {
-            return Arrays.asList(
-                new Book("Apache CXF in Action", UUID.randomUUID().toString()),
-                new Book("Mastering Apache CXF", UUID.randomUUID().toString())
-            );
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/cxf/blob/69826a09/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/BookStoreService.java
----------------------------------------------------------------------
diff --git a/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/BookStoreService.java b/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/BookStoreService.java
index 635eb6c..e2c5ab8 100644
--- a/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/BookStoreService.java
+++ b/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/BookStoreService.java
@@ -27,4 +27,5 @@ import org.apache.cxf.systest.Book;
 @WebService
 public interface BookStoreService {
     Collection< Book > getBooks();
+    int removeBooks();
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/69826a09/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/brave/BookStore.java
----------------------------------------------------------------------
diff --git a/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/brave/BookStore.java b/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/brave/BookStore.java
new file mode 100644
index 0000000..26157fc
--- /dev/null
+++ b/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/brave/BookStore.java
@@ -0,0 +1,68 @@
+/**
+ * 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.tracing.brave;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.UUID;
+
+import javax.jws.WebMethod;
+import javax.jws.WebService;
+
+import com.github.kristofa.brave.Brave;
+
+import org.apache.cxf.systest.Book;
+import org.apache.cxf.systest.TestSpanReporter;
+import org.apache.cxf.systest.jaxws.tracing.BookStoreService;
+
+import zipkin.Constants;
+
+@WebService(endpointInterface = "org.apache.cxf.systest.jaxws.tracing.BookStoreService", serviceName = "BookStore")
+public class BookStore implements BookStoreService {
+    private final Brave brave;
+    
+    public BookStore() {
+        brave = new Brave.Builder("book-store")
+            .reporter(new TestSpanReporter())
+            .build();
+    }
+    
+    @WebMethod
+    public Collection< Book > getBooks() {
+        try {
+            brave
+                .localTracer()
+                .startNewSpan(Constants.LOCAL_COMPONENT, "Get Books");
+            
+            return Arrays.asList(
+                    new Book("Apache CXF in Action", UUID.randomUUID().toString()),
+                    new Book("Mastering Apache CXF", UUID.randomUUID().toString())
+                );
+        } finally {
+            brave
+                .localTracer()
+                .finishSpan();
+        }
+    }
+    
+    @WebMethod
+    public int removeBooks() {
+        throw new RuntimeException("Unable to remove books");
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/69826a09/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/brave/BraveTracingTest.java
----------------------------------------------------------------------
diff --git a/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/brave/BraveTracingTest.java b/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/brave/BraveTracingTest.java
new file mode 100644
index 0000000..13accb9
--- /dev/null
+++ b/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/brave/BraveTracingTest.java
@@ -0,0 +1,309 @@
+/**
+ * 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.tracing.brave;
+
+import java.net.MalformedURLException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+import javax.xml.ws.soap.SOAPFaultException;
+
+import com.github.kristofa.brave.Brave;
+import com.github.kristofa.brave.SpanId;
+import com.github.kristofa.brave.http.BraveHttpHeaders;
+
+import org.apache.cxf.endpoint.Client;
+import org.apache.cxf.ext.logging.LoggingInInterceptor;
+import org.apache.cxf.ext.logging.LoggingOutInterceptor;
+import org.apache.cxf.frontend.ClientProxy;
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
+import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.systest.TestSpanReporter;
+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.brave.BraveClientFeature;
+import org.apache.cxf.tracing.brave.BraveFeature;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.hasItem;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.nullValue;
+
+import zipkin.Constants;
+
+public class BraveTracingTest extends AbstractBusClientServerTestBase {
+    public static final String PORT = allocatePort(BraveTracingTest.class);
+    
+    @Ignore
+    public static class Server extends AbstractBusTestServerBase {
+        protected void run() {
+            final Brave brave = new Brave.Builder("book-store")
+                .reporter(new TestSpanReporter())
+                .build();
+
+            final JaxWsServerFactoryBean sf = new JaxWsServerFactoryBean();
+            sf.setServiceClass(BookStore.class);
+            sf.setAddress("http://localhost:" + PORT);
+            sf.getFeatures().add(new BraveFeature(brave));
+            sf.create();
+        }
+    }
+    
+    private interface Configurator {
+        void configure(JaxWsProxyFactoryBean factory);
+    }
+    
+    @BeforeClass
+    public static void startServers() throws Exception {
+        //keep out of process due to stack traces testing failures
+        assertTrue("server did not launch correctly", launchServer(Server.class, true));
+        createStaticBus();
+    }
+    
+    @Before
+    public void setUp() {
+        TestSpanReporter.clear();
+    }
+    
+    @Test
+    public void testThatNewSpanIsCreatedWhenNotProvided() throws MalformedURLException {
+        final BookStoreService service = createJaxWsService();
+        assertThat(service.getBooks().size(), equalTo(2));
+        
+        assertThat(TestSpanReporter.getAllSpans().size(), equalTo(2));
+        assertThat(TestSpanReporter.getAllSpans().get(0).name, equalTo("get books"));
+        assertThat(TestSpanReporter.getAllSpans().get(1).name, equalTo("post /bookstore"));
+        
+        final Map<String, List<String>> headers = getResponseHeaders(service);
+        assertFalse(headers.containsKey(BraveHttpHeaders.TraceId.getName()));
+        assertFalse(headers.containsKey(BraveHttpHeaders.Sampled.getName()));
+        assertFalse(headers.containsKey(BraveHttpHeaders.ParentSpanId.getName()));
+        assertFalse(headers.containsKey(BraveHttpHeaders.ParentSpanId.getName()));
+    }
+    
+    @Test
+    public void testThatNewInnerSpanIsCreated() throws MalformedURLException {
+        final Random random = new Random();
+        
+        final SpanId spanId = SpanId
+            .builder()
+            .traceId(random.nextLong())
+            .parentId(random.nextLong())
+            .spanId(random.nextLong())
+            .sampled(true)
+            .build();
+
+        final Map<String, List<String>> headers = new HashMap<String, List<String>>();
+        headers.put(BraveHttpHeaders.SpanId.getName(), Arrays.asList(Long.toString(spanId.spanId)));
+        headers.put(BraveHttpHeaders.TraceId.getName(), Arrays.asList(Long.toString(spanId.traceId)));
+        headers.put(BraveHttpHeaders.Sampled.getName(), Arrays.asList(Boolean.toString(spanId.sampled())));
+        headers.put(BraveHttpHeaders.ParentSpanId.getName(), Arrays.asList(Long.toString(spanId.parentId)));
+
+        final BookStoreService service = createJaxWsService(headers);
+        assertThat(service.getBooks().size(), equalTo(2));
+        
+        assertThat(TestSpanReporter.getAllSpans().size(), equalTo(2));
+        assertThat(TestSpanReporter.getAllSpans().get(0).name, equalTo("get books"));
+        assertThat(TestSpanReporter.getAllSpans().get(1).name, equalTo("post /bookstore"));
+        
+        final Map<String, List<String>> response = getResponseHeaders(service);
+        assertThatTraceIsPresent(response, spanId);
+    }
+    
+    @Test
+    public void testThatNewChildSpanIsCreatedWhenParentIsProvided() throws MalformedURLException {
+        final Brave brave = new Brave.Builder("book-store")
+            .reporter(new TestSpanReporter())
+            .build();
+    
+        final BookStoreService service = createJaxWsService(new Configurator() {
+            @Override
+            public void configure(final JaxWsProxyFactoryBean factory) {
+                factory.getFeatures().add(new BraveClientFeature(brave));
+            }
+        });
+        assertThat(service.getBooks().size(), equalTo(2));
+        
+        assertThat(TestSpanReporter.getAllSpans().size(), equalTo(3));
+        assertThat(TestSpanReporter.getAllSpans().get(0).name, equalTo("get books"));
+        assertThat(TestSpanReporter.getAllSpans().get(0).parentId, not(nullValue()));
+        assertThat(TestSpanReporter.getAllSpans().get(1).name, equalTo("post /bookstore"));
+        assertThat(TestSpanReporter.getAllSpans().get(2).name, 
+            equalTo("post http://localhost:" + PORT + "/bookstore"));
+        
+        final Map<String, List<String>> response = getResponseHeaders(service);
+        assertThatTraceHeadersArePresent(response, false);
+    }
+    
+    @Test
+    public void testThatProvidedSpanIsNotClosedWhenActive() throws MalformedURLException {
+        final Brave brave = new Brave.Builder("book-store")
+            .reporter(new TestSpanReporter())
+            .build();
+
+        final BookStoreService service = createJaxWsService(new Configurator() {
+            @Override
+            public void configure(final JaxWsProxyFactoryBean factory) {
+                factory.getFeatures().add(new BraveClientFeature(brave));
+            }
+        });
+
+        try {
+            brave.localTracer().startNewSpan(Constants.LOCAL_COMPONENT, "test span");
+            
+            assertThat(service.getBooks().size(), equalTo(2));
+            assertThat(brave.localSpanThreadBinder().getCurrentLocalSpan(), not(nullValue()));
+            
+            assertThat(TestSpanReporter.getAllSpans().size(), equalTo(3));
+            assertThat(TestSpanReporter.getAllSpans().get(0).name, equalTo("get books"));
+            assertThat(TestSpanReporter.getAllSpans().get(0).parentId, not(nullValue()));
+            assertThat(TestSpanReporter.getAllSpans().get(1).name, equalTo("post /bookstore"));
+            assertThat(TestSpanReporter.getAllSpans().get(2).name, 
+                equalTo("post http://localhost:" + PORT + "/bookstore"));
+            
+            final Map<String, List<String>> response = getResponseHeaders(service);
+            assertThatTraceHeadersArePresent(response, true);
+        } finally {
+            brave.localTracer().finishSpan();
+        }
+        
+        assertThat(TestSpanReporter.getAllSpans().size(), equalTo(4));
+        assertThat(TestSpanReporter.getAllSpans().get(3).name, equalTo("test span"));
+    }
+    
+    @Test
+    public void testThatNewSpanIsCreatedInCaseOfFault() throws MalformedURLException {
+        final BookStoreService service = createJaxWsService();
+        
+        try {
+            service.removeBooks();
+            fail("Expected SOAPFaultException to be raised");
+        } catch (final SOAPFaultException ex) {
+            /* expected exception */
+        }
+        
+        assertThat(TestSpanReporter.getAllSpans().size(), equalTo(1));
+        assertThat(TestSpanReporter.getAllSpans().get(0).name, equalTo("post /bookstore"));
+        
+        final Map<String, List<String>> headers = getResponseHeaders(service);
+        assertFalse(headers.containsKey(BraveHttpHeaders.TraceId.getName()));
+        assertFalse(headers.containsKey(BraveHttpHeaders.Sampled.getName()));
+        assertFalse(headers.containsKey(BraveHttpHeaders.ParentSpanId.getName()));
+        assertFalse(headers.containsKey(BraveHttpHeaders.ParentSpanId.getName()));
+    }
+    
+    @Test
+    public void testThatNewChildSpanIsCreatedWhenParentIsProvidedInCaseOfFault() throws MalformedURLException {
+        final Brave brave = new Brave.Builder("book-store")
+            .reporter(new TestSpanReporter())
+            .build();
+    
+        final BookStoreService service = createJaxWsService(new Configurator() {
+            @Override
+            public void configure(final JaxWsProxyFactoryBean factory) {
+                factory.getFeatures().add(new BraveClientFeature(brave));
+            }
+        });
+        
+        try {
+            service.removeBooks();
+            fail("Expected SOAPFaultException to be raised");
+        } catch (final SOAPFaultException ex) {
+            /* expected exception */
+        }
+        
+        assertThat(TestSpanReporter.getAllSpans().size(), equalTo(2));
+        assertThat(TestSpanReporter.getAllSpans().get(0).name, equalTo("post /bookstore"));
+        assertThat(TestSpanReporter.getAllSpans().get(1).name, 
+            equalTo("post http://localhost:" + PORT + "/bookstore"));
+        
+        final Map<String, List<String>> response = getResponseHeaders(service);
+        assertThatTraceHeadersArePresent(response, false);
+    }
+
+    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 service;
+    }
+    
+    private Map<String, List<String>> getResponseHeaders(final BookStoreService service) {
+        final Client proxy = ClientProxy.getClient(service);
+        return CastUtils.cast((Map<?, ?>)proxy.getResponseContext().get(Message.PROTOCOL_HEADERS));
+    }
+    
+    private void assertThatTraceIsPresent(Map<String, List<String>> headers, SpanId spanId) {
+        assertThat(headers.get(BraveHttpHeaders.SpanId.getName()), 
+            hasItem(Long.toString(spanId.spanId)));
+        assertThat(headers.get(BraveHttpHeaders.TraceId.getName()), 
+            hasItem(Long.toString(spanId.traceId)));
+        assertThat(headers.get(BraveHttpHeaders.Sampled.getName()), 
+            hasItem(Boolean.toString(spanId.sampled())));
+        assertThat(headers.get(BraveHttpHeaders.ParentSpanId.getName()), 
+            hasItem(Long.toString(spanId.parentId)));
+    }
+
+    private void assertThatTraceHeadersArePresent(Map<String, List<String>> headers, boolean expectParent) {
+        assertTrue(headers.containsKey(BraveHttpHeaders.SpanId.getName()));
+        assertTrue(headers.containsKey(BraveHttpHeaders.TraceId.getName()));
+        assertTrue(headers.containsKey(BraveHttpHeaders.Sampled.getName()));
+        
+        if (expectParent) {
+            assertTrue(headers.containsKey(BraveHttpHeaders.ParentSpanId.getName()));
+        } else {
+            assertFalse(headers.containsKey(BraveHttpHeaders.ParentSpanId.getName()));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/69826a09/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/htrace/BookStore.java
----------------------------------------------------------------------
diff --git a/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/htrace/BookStore.java b/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/htrace/BookStore.java
new file mode 100644
index 0000000..4bd10b5
--- /dev/null
+++ b/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/htrace/BookStore.java
@@ -0,0 +1,49 @@
+/**
+ * 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.tracing.htrace;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.UUID;
+
+import javax.jws.WebMethod;
+import javax.jws.WebService;
+
+import org.apache.cxf.systest.Book;
+import org.apache.cxf.systest.jaxws.tracing.BookStoreService;
+import org.apache.htrace.core.TraceScope;
+import org.apache.htrace.core.Tracer;
+
+@WebService(endpointInterface = "org.apache.cxf.systest.jaxws.tracing.BookStoreService", serviceName = "BookStore")
+public class BookStore implements BookStoreService {
+    @WebMethod
+    public Collection< Book > getBooks() {
+        try (TraceScope span = Tracer.curThreadTracer().newScope("Get Books")) {
+            return Arrays.asList(
+                new Book("Apache CXF in Action", UUID.randomUUID().toString()),
+                new Book("Mastering Apache CXF", UUID.randomUUID().toString())
+            );
+        }
+    }
+    
+    @WebMethod
+    public int removeBooks() {
+        throw new RuntimeException("Unable to remove books");
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/69826a09/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 260591f..d5379f9 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
@@ -25,16 +25,15 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.cxf.endpoint.Client;
+import org.apache.cxf.ext.logging.LoggingInInterceptor;
+import org.apache.cxf.ext.logging.LoggingOutInterceptor;
 import org.apache.cxf.frontend.ClientProxy;
 import org.apache.cxf.helpers.CastUtils;
-import org.apache.cxf.interceptor.LoggingInInterceptor;
-import org.apache.cxf.interceptor.LoggingOutInterceptor;
 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.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;