You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by dk...@apache.org on 2012/07/27 20:44:57 UTC

svn commit: r1366490 - in /cxf/sandbox/dkulp_async_clients/http-jetty-client: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/cxf/ src/main/java/org/apache/cxf/transport/ src/main/java/org/apache/c...

Author: dkulp
Date: Fri Jul 27 18:44:57 2012
New Revision: 1366490

URL: http://svn.apache.org/viewvc?rev=1366490&view=rev
Log:
Add experiment using Jetty client APIs - fairly simple, but the API's do require a fair bit of copying of bytes between buffers.  Additionally, if using their getRequestContentChunk api's, creates a bunch of extra network packets for the chunk sizes.

Added:
    cxf/sandbox/dkulp_async_clients/http-jetty-client/
    cxf/sandbox/dkulp_async_clients/http-jetty-client/pom.xml
    cxf/sandbox/dkulp_async_clients/http-jetty-client/src/
    cxf/sandbox/dkulp_async_clients/http-jetty-client/src/main/
    cxf/sandbox/dkulp_async_clients/http-jetty-client/src/main/java/
    cxf/sandbox/dkulp_async_clients/http-jetty-client/src/main/java/org/
    cxf/sandbox/dkulp_async_clients/http-jetty-client/src/main/java/org/apache/
    cxf/sandbox/dkulp_async_clients/http-jetty-client/src/main/java/org/apache/cxf/
    cxf/sandbox/dkulp_async_clients/http-jetty-client/src/main/java/org/apache/cxf/transport/
    cxf/sandbox/dkulp_async_clients/http-jetty-client/src/main/java/org/apache/cxf/transport/http/
    cxf/sandbox/dkulp_async_clients/http-jetty-client/src/main/java/org/apache/cxf/transport/http/asyncclient/
    cxf/sandbox/dkulp_async_clients/http-jetty-client/src/main/java/org/apache/cxf/transport/http/asyncclient/AsyncHTTPConduit.java
    cxf/sandbox/dkulp_async_clients/http-jetty-client/src/main/java/org/apache/cxf/transport/http/asyncclient/AsyncHTTPTransportFactory.java
    cxf/sandbox/dkulp_async_clients/http-jetty-client/src/test/
    cxf/sandbox/dkulp_async_clients/http-jetty-client/src/test/java/
    cxf/sandbox/dkulp_async_clients/http-jetty-client/src/test/java/org/
    cxf/sandbox/dkulp_async_clients/http-jetty-client/src/test/java/org/apache/
    cxf/sandbox/dkulp_async_clients/http-jetty-client/src/test/java/org/apache/cxf/
    cxf/sandbox/dkulp_async_clients/http-jetty-client/src/test/java/org/apache/cxf/transport/
    cxf/sandbox/dkulp_async_clients/http-jetty-client/src/test/java/org/apache/cxf/transport/http/
    cxf/sandbox/dkulp_async_clients/http-jetty-client/src/test/java/org/apache/cxf/transport/http/asyncclient/
    cxf/sandbox/dkulp_async_clients/http-jetty-client/src/test/java/org/apache/cxf/transport/http/asyncclient/AsyncHTTPConduitTest.java

Added: cxf/sandbox/dkulp_async_clients/http-jetty-client/pom.xml
URL: http://svn.apache.org/viewvc/cxf/sandbox/dkulp_async_clients/http-jetty-client/pom.xml?rev=1366490&view=auto
==============================================================================
--- cxf/sandbox/dkulp_async_clients/http-jetty-client/pom.xml (added)
+++ cxf/sandbox/dkulp_async_clients/http-jetty-client/pom.xml Fri Jul 27 18:44:57 2012
@@ -0,0 +1,106 @@
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.apache.cxf</groupId>
+    <artifactId>cxf-rt-transports-http-jetty-client</artifactId>
+    <packaging>jar</packaging>
+    <version>2.7.0-SNAPSHOT</version>
+    <name>Apache CXF Runtime HTTP Transport</name>
+    <description>Apache CXF Runtime HTTP Jetty Client Transport</description>
+    <url>http://cxf.apache.org</url>
+
+    <parent>
+        <groupId>org.apache.cxf</groupId>
+        <artifactId>cxf-parent</artifactId>
+        <version>2.7.0-SNAPSHOT</version>
+        <relativePath>../../../parent/pom.xml</relativePath>
+    </parent>
+    <properties>
+        <cxf.osgi.import>
+            javax.servlet*;version="${cxf.osgi.javax.servlet.version}",
+        </cxf.osgi.import>
+        <cxf.osgi.export>
+            org.apache.cxf.*,
+        </cxf.osgi.export>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymock</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-transports-http</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-client</artifactId>
+            <version>${cxf.jetty.version}</version>
+        </dependency>
+
+
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-jdk14</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-transports-http-jetty</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-frontend-jaxws</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-testutils</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+
+
+</project>

Added: cxf/sandbox/dkulp_async_clients/http-jetty-client/src/main/java/org/apache/cxf/transport/http/asyncclient/AsyncHTTPConduit.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dkulp_async_clients/http-jetty-client/src/main/java/org/apache/cxf/transport/http/asyncclient/AsyncHTTPConduit.java?rev=1366490&view=auto
==============================================================================
--- cxf/sandbox/dkulp_async_clients/http-jetty-client/src/main/java/org/apache/cxf/transport/http/asyncclient/AsyncHTTPConduit.java (added)
+++ cxf/sandbox/dkulp_async_clients/http-jetty-client/src/main/java/org/apache/cxf/transport/http/asyncclient/AsyncHTTPConduit.java Fri Jul 27 18:44:57 2012
@@ -0,0 +1,386 @@
+/**
+ * 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.transport.http.asyncclient;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.helpers.HttpHeaderHelper;
+import org.apache.cxf.helpers.LoadingByteArrayOutputStream;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.service.model.EndpointInfo;
+import org.apache.cxf.transport.http.HTTPConduit;
+import org.apache.cxf.transport.http.Headers;
+import org.apache.cxf.transport.https.HttpsURLConnectionInfo;
+import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
+import org.apache.cxf.version.Version;
+import org.apache.cxf.ws.addressing.EndpointReferenceType;
+import org.eclipse.jetty.client.CachedExchange;
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.http.HttpFields;
+import org.eclipse.jetty.io.Buffer;
+import org.eclipse.jetty.io.ByteArrayBuffer;
+
+
+
+/**
+ * 
+ */
+public class AsyncHTTPConduit extends HTTPConduit {
+    final HttpClient client;
+    LoadingByteArrayOutputStream fixedBuffer;
+    public AsyncHTTPConduit(Bus b, EndpointInfo ei, EndpointReferenceType t,
+                            HttpClient f) throws IOException {
+        super(b, ei, t);
+        this.client = f;
+    }
+
+    public void close() {
+    }
+    
+    protected void setupConnection(Message message, URL url, HTTPClientPolicy csPolicy) throws IOException {
+        String httpRequestMethod = 
+            (String)message.get(Message.HTTP_REQUEST_METHOD);
+        if (httpRequestMethod == null) {
+            httpRequestMethod = "POST";
+            message.put(Message.HTTP_REQUEST_METHOD, httpRequestMethod);
+        }
+        CXFExchange request = new CXFExchange();
+        request.setMethod(httpRequestMethod);
+        request.setRequestURI(url.toString());
+        try {
+            request.setURI(url.toURI());
+        } catch (URISyntaxException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        
+        message.put(CXFExchange.class, request);
+    }
+    
+    static class BufferInputStream extends InputStream {
+        volatile Buffer content;
+        boolean complete;
+        
+        public synchronized void complete() {
+            complete = true;
+            notifyAll();
+        }
+        public synchronized void loadContent() throws IOException {
+            while (content == null && !complete) {
+                try {
+                    wait();
+                } catch (InterruptedException e) {
+                    throw new IOException(e);
+                }
+            }
+        }
+        public synchronized void setContent(Buffer c) {
+            content = c;
+            notifyAll();
+            try {
+                wait();
+            } catch (InterruptedException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+        }
+        
+        public int read(byte[] b) throws IOException {
+            return read(b, 0, b.length);
+        } 
+        public int read(byte[] b, int off, int len) throws IOException {
+            loadContent();
+            if (content != null && content.hasContent()) {
+                int i = content.get(b, off, len);
+                if (!content.hasContent()) {
+                    synchronized (this) {
+                        content = null;
+                        notifyAll();
+                    }
+                }
+                return i;
+            }
+            return -1;
+        }
+        public int available() throws IOException {
+            return super.available();
+        }
+        public void close() throws IOException {
+            super.close();
+        }
+        public int read() throws IOException {
+            loadContent();
+            if (content != null && content.hasContent()) {
+                return content.get();
+            } else {
+                synchronized (this) {
+                    content = null;
+                    notifyAll();
+                }
+            }
+            return -1;
+        }
+    }
+    static class CXFExchange extends CachedExchange {
+        static final Buffer EMPTY_BUFFER = new ByteArrayBuffer(0);
+        String reason;
+        boolean doneHeaders;
+        BufferInputStream in = new BufferInputStream();
+        volatile Buffer contentBuffer = new ByteArrayBuffer(1024 * 16);
+        volatile boolean done;
+        
+        public CXFExchange() {
+            super(true);
+        }
+        
+        public InputStream getInputStream() {
+            return in;
+        }
+        public String getResponseReason() {
+            return reason;
+        }
+        protected void onResponseStatus(Buffer version, int status, Buffer r)
+            throws IOException {
+            super.onResponseStatus(version, status, r);
+            reason = r.toString();
+        }
+        @Override
+        protected synchronized void onResponseHeaderComplete() throws IOException {
+            super.onResponseHeaderComplete();
+            doneHeaders = true;
+            notifyAll();
+        }
+
+        public synchronized void waitForResponseHeaders() throws IOException {
+            while (!doneHeaders) {
+                try {
+                    wait();
+                } catch (InterruptedException e) {
+                    throw new IOException(e);
+                }
+            }
+        }
+        protected void onResponseContent(Buffer content) throws IOException {
+            in.setContent(content);
+        }
+        @Override
+        protected void onResponseComplete() throws IOException {
+            super.onResponseComplete();
+            in.complete();
+        }
+
+        public InputStream getRequestContentSource() {
+            return new InputStream() {
+                public int available() {
+                    return 0;
+                }
+                public int read() throws IOException {
+                    return 0;
+                }
+            };
+        }
+        @Override
+        public synchronized Buffer getRequestContentChunk(Buffer buffer) throws IOException {
+            if (contentBuffer.hasContent()) {
+                Buffer b = contentBuffer;
+                contentBuffer = new ByteArrayBuffer(1024 * 16);
+                notifyAll();
+                return b;
+            } 
+            if (done) {
+                return null;
+            }
+            return EMPTY_BUFFER;
+        }
+
+        public synchronized void write(byte[] b, int off, int len) throws IOException {
+            int i = contentBuffer.put(b, off, len);
+            while (i > 0) {
+                off += i;
+                len -= i;
+                if (len > 0) {
+                    i = contentBuffer.put(b, off, len);
+                } else {
+                    return;
+                }
+            }
+            if (len > 0) {
+                try {
+                    wait();
+                } catch (InterruptedException e) {
+                    throw new IOException(e);
+                }
+                write(b, off, len);
+            }
+        }
+
+        public void doneWrite() {
+            done = true;
+        }
+
+    }
+    
+    protected OutputStream createOutputStream(Message message, 
+                                              boolean needToCacheRequest, 
+                                              boolean isChunking,
+                                              int chunkThreshold) {
+        CXFExchange request = message.get(CXFExchange.class);
+        String url = request.getRequestURI();  //FIXME get the URL
+        return new AsyncWrappedOutputStream(message,
+                                            needToCacheRequest, 
+                                            isChunking,
+                                            chunkThreshold,
+                                            getConduitName(),
+                                            url);
+    }
+    
+    
+    class AsyncWrappedOutputStream extends WrappedOutputStream {
+        CXFExchange request;
+        public AsyncWrappedOutputStream(Message message,
+                                        boolean needToCacheRequest, 
+                                        boolean isChunking,
+                                        int chunkThreshold, 
+                                        String conduitName,
+                                        String url) {
+            super(message, needToCacheRequest, isChunking,
+                  chunkThreshold, conduitName,
+                  url);
+            request = message.get(CXFExchange.class);
+        }
+        
+
+        protected void setProtocolHeaders() throws IOException {
+            Headers h = new Headers(outMessage);
+            request.setRequestContentType(h.determineContentType());
+            for (Map.Entry<String, List<String>> header : h.headerMap().entrySet()) {
+                if (HttpHeaderHelper.CONTENT_TYPE.equalsIgnoreCase(header.getKey())) {
+                    continue;
+                }
+
+                StringBuilder b = new StringBuilder();
+                for (int i = 0; i < header.getValue().size(); i++) {
+                    b.append(header.getValue().get(i));
+                    if (i + 1 < header.getValue().size()) {
+                        b.append(',');
+                    }
+                }
+                request.setRequestHeader(header.getKey(), b.toString());
+            }
+            if (!h.headerMap().containsKey("User-Agent")) {
+                request.setRequestHeader("User-Agent", Version.getCompleteVersionString());
+            }
+        }
+        
+        protected void setFixedLengthStreamingMode(int i) {
+            fixedBuffer = buffer;
+        }
+        public void thresholdReached() throws IOException {
+            //request.setChunked(true);
+        }
+        
+        
+        
+        protected void setupWrappedStream() throws IOException {
+            if (fixedBuffer != null) {
+                wrappedStream = new OutputStream() {
+                    public void write(int b) throws IOException {
+                    }
+                };
+                request.addRequestHeader("Content-Length", Integer.toString(fixedBuffer.size()));
+                request.setRequestContent(new ByteArrayBuffer(fixedBuffer.getRawBytes(), 0, fixedBuffer.size()));
+            } else {
+                wrappedStream = new OutputStream() {
+                    public void write(int b) throws IOException {
+                        write(new byte[] {(byte)b});
+                    }
+                    public void write(byte b[], int off, int len) throws IOException {
+                        request.write(b, off, len);
+                    }
+                    public void close() {
+                        request.doneWrite();
+                    }
+                };
+
+            }
+            client.send(request);
+        }
+        
+        protected void handleResponseAsync() throws IOException {
+        }
+        protected void closeInputStream() throws IOException {
+        }
+        
+        protected boolean usingProxy() {
+            return false;
+        }
+        protected HttpsURLConnectionInfo getHttpsURLConnectionInfo() throws IOException {
+            return null;
+        }
+        protected int getResponseCode() throws IOException {
+            request.waitForResponseHeaders();
+            return request.getResponseStatus();
+        }
+        protected String getResponseMessage() throws IOException {
+            request.waitForResponseHeaders();
+            return request.getResponseReason();
+        }
+        
+        private void readHeaders(Headers h) {
+            h.headerMap().clear();
+            HttpFields fields = request.getResponseFields();
+            for (String n : fields.getFieldNamesCollection()) {
+                h.headerMap().put(n, new ArrayList<String>(fields.getValuesCollection(n)));
+            }
+        }
+        protected void updateResponseHeaders(Message inMessage) {
+            Headers h = new Headers(inMessage);
+            readHeaders(h);
+            inMessage.put(Message.CONTENT_TYPE, h.determineContentType());
+            cookies.readFromHeaders(h);
+        }
+        protected void updateCookiesBeforeRetransmit() {
+            Headers h = new Headers();
+            readHeaders(h);
+            cookies.readFromHeaders(h);
+        }
+        protected void retransmitStream() throws IOException {
+        }
+        protected void setupNewConnection(String newURL) throws IOException {           
+        }
+        protected InputStream getInputStream() throws IOException {
+            return request.getInputStream();
+        }
+        protected InputStream getPartialResponse() throws IOException {
+            return null;
+        }
+
+    }
+    
+}

Added: cxf/sandbox/dkulp_async_clients/http-jetty-client/src/main/java/org/apache/cxf/transport/http/asyncclient/AsyncHTTPTransportFactory.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dkulp_async_clients/http-jetty-client/src/main/java/org/apache/cxf/transport/http/asyncclient/AsyncHTTPTransportFactory.java?rev=1366490&view=auto
==============================================================================
--- cxf/sandbox/dkulp_async_clients/http-jetty-client/src/main/java/org/apache/cxf/transport/http/asyncclient/AsyncHTTPTransportFactory.java (added)
+++ cxf/sandbox/dkulp_async_clients/http-jetty-client/src/main/java/org/apache/cxf/transport/http/asyncclient/AsyncHTTPTransportFactory.java Fri Jul 27 18:44:57 2012
@@ -0,0 +1,135 @@
+/**
+ * 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.transport.http.asyncclient;
+
+import java.io.IOException;
+
+import javax.annotation.Resource;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.buslifecycle.BusLifeCycleListener;
+import org.apache.cxf.buslifecycle.BusLifeCycleManager;
+import org.apache.cxf.common.injection.NoJSR250Annotations;
+import org.apache.cxf.service.model.EndpointInfo;
+import org.apache.cxf.transport.Conduit;
+import org.apache.cxf.transport.http.DestinationRegistry;
+import org.apache.cxf.transport.http.HTTPConduit;
+import org.apache.cxf.transport.http.HTTPConduitConfigurer;
+import org.apache.cxf.transport.http.HTTPTransportFactory;
+import org.apache.cxf.ws.addressing.EndpointReferenceType;
+import org.eclipse.jetty.client.HttpClient;
+
+/**
+ * 
+ */
+@NoJSR250Annotations(unlessNull = "bus")
+public class AsyncHTTPTransportFactory extends HTTPTransportFactory implements BusLifeCycleListener {
+    HttpClient client;
+    
+    public AsyncHTTPTransportFactory() {
+        super();
+    }
+    public AsyncHTTPTransportFactory(Bus b) {
+        super(b);
+        addListener(b);
+    }
+    public AsyncHTTPTransportFactory(Bus b, DestinationRegistry registry) {
+        super(b, registry);
+        addListener(b);
+    }
+
+    public AsyncHTTPTransportFactory(DestinationRegistry registry) {
+        super(registry);
+    }
+    
+    @Resource 
+    public void setBus(Bus b) {
+        super.setBus(b);
+        addListener(b);
+    }
+    public void initComplete() {
+    }
+    public synchronized void preShutdown() {
+        if (client != null) { 
+            try {
+                client.stop();
+            } catch (Exception e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+        }
+    }
+    public void postShutdown() {
+        if (client != null) { 
+            client.destroy();
+        }
+    }    
+    
+    private void addListener(Bus b) {
+        b.getExtension(BusLifeCycleManager.class).registerLifeCycleListener(this);
+    }
+    
+    
+    public synchronized HttpClient getHttpClient() {
+        if (client == null) {
+            client = getBus().getExtension(HttpClient.class);
+            if (client == null) {
+                client = (HttpClient)getBus()
+                    .getProperty(HttpClient.class.getName());
+            }
+            if (client == null) {
+                client = new HttpClient();
+                try {
+                    client.start();
+                } catch (Exception e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                }
+            }
+        }
+        return client;
+    }
+    
+    /**
+     * This call creates a new HTTP Conduit based on the EndpointInfo and
+     * EndpointReferenceType.
+     * TODO: What are the formal constraints on EndpointInfo and 
+     * EndpointReferenceType values?
+     */
+    public Conduit getConduit(
+            EndpointInfo endpointInfo,
+            EndpointReferenceType target
+    ) throws IOException {
+        HTTPConduit conduit = new AsyncHTTPConduit(bus, endpointInfo, target, getHttpClient());
+        // Spring configure the conduit.  
+        String address = conduit.getAddress();
+        if (address != null && address.indexOf('?') != -1) {
+            address = address.substring(0, address.indexOf('?'));
+        }
+        HTTPConduitConfigurer c1 = bus.getExtension(HTTPConduitConfigurer.class);
+        if (c1 != null) {
+            c1.configure(conduit.getBeanName(), address, conduit);
+        }
+        configure(conduit, conduit.getBeanName(), address);
+        conduit.finalizeConfig();
+        return conduit;
+    }
+
+}

Added: cxf/sandbox/dkulp_async_clients/http-jetty-client/src/test/java/org/apache/cxf/transport/http/asyncclient/AsyncHTTPConduitTest.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dkulp_async_clients/http-jetty-client/src/test/java/org/apache/cxf/transport/http/asyncclient/AsyncHTTPConduitTest.java?rev=1366490&view=auto
==============================================================================
--- cxf/sandbox/dkulp_async_clients/http-jetty-client/src/test/java/org/apache/cxf/transport/http/asyncclient/AsyncHTTPConduitTest.java (added)
+++ cxf/sandbox/dkulp_async_clients/http-jetty-client/src/test/java/org/apache/cxf/transport/http/asyncclient/AsyncHTTPConduitTest.java Fri Jul 27 18:44:57 2012
@@ -0,0 +1,125 @@
+/**
+ * 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.transport.http.asyncclient;
+
+import java.net.URL;
+
+import javax.xml.ws.Endpoint;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
+import org.apache.hello_world.Greeter;
+import org.apache.hello_world.services.SOAPService;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+
+
+public class AsyncHTTPConduitTest extends AbstractBusClientServerTestBase {
+    public static final String PORT = allocatePort(AsyncHTTPConduitTest.class);
+    public static final String PORT2 = allocatePort(AsyncHTTPConduitTest.class, 2);
+    
+    static Endpoint ep;
+    @BeforeClass
+    public static void start() throws Exception {
+        Bus b = createStaticBus();
+        new AsyncHTTPTransportFactory(b);
+        ep = Endpoint.publish("http://localhost:" + PORT + "/SoapContext/SoapPort",
+                              new org.apache.hello_world.GreeterImpl());
+        ep = Endpoint.publish("http://localhost:" + PORT2 + "/SoapContext/SoapPort",
+                              new org.apache.hello_world.GreeterImpl());
+    }
+    
+    @AfterClass
+    public static void stop() throws Exception {
+        ep.stop();
+        ep = null;
+    }
+    
+    @Test
+    public void testCall() throws Exception {
+        URL wsdl = getClass().getResource("/wsdl/hello_world_services.wsdl");
+        assertNotNull("WSDL is null", wsdl);
+
+        SOAPService service = new SOAPService();
+        assertNotNull("Service is null", service);
+
+        StringBuilder builder = new StringBuilder("NaNaNa");
+        for (int x = 0; x < 1000; x++) {
+            builder.append(" NaNaNa ");
+        }
+        
+        Greeter g = service.getSoapPort();
+        assertNotNull("Port is null", g);
+        updateAddressPort(g, PORT);
+        g.greetMe(builder.toString());
+    }
+        
+    @Test
+    public void testCalls() throws Exception {
+        URL wsdl = getClass().getResource("/wsdl/hello_world_services.wsdl");
+        assertNotNull("WSDL is null", wsdl);
+
+        SOAPService service = new SOAPService();
+        assertNotNull("Service is null", service);
+
+        StringBuilder builder = new StringBuilder("NaNaNa");
+        for (int x = 0; x < 1000; x++) {
+            builder.append(" NaNaNa ");
+        }
+        
+        Greeter g = service.getSoapPort();
+        assertNotNull("Port is null", g);
+        updateAddressPort(g, PORT);
+
+        //warmup
+        for (int x = 0; x < 10000; x++) {
+            //builder.append("a");
+            //long s1 = System.nanoTime();
+            //System.out.println("aa1: " + s1);
+            String value = g.greetMe(builder.toString());
+            //long s2 = System.nanoTime();
+            //System.out.println("aa2: " + s2 + " " + (s2 - s1));
+            assertEquals("Hello " + builder.toString(), value);
+            //System.out.println();
+        }
+
+        long start = System.currentTimeMillis();
+        for (int x = 0; x < 10000; x++) {
+            //builder.append("a");
+            //long s1 = System.nanoTime();
+            //System.out.println("aa1: " + s1);
+            g.greetMe(builder.toString());
+            //long s2 = System.nanoTime();
+            //System.out.println("aa2: " + s2 + " " + (s2 - s1));
+            //System.out.println();
+        }
+        long end = System.currentTimeMillis();
+        System.out.println("Total: " + (end - start));
+        /*
+        updateAddressPort(g, PORT2);
+        String value = g.greetMe(builder.toString());
+        assertEquals("Hello " + builder.toString(), value);
+        */
+    }
+
+}