diff --git com/kenai/jbosh/ApacheHTTPResponse.java com/kenai/jbosh/ApacheHTTPResponse.java
new file mode 100644
index 0000000..9f6731f
--- /dev/null
+++ com/kenai/jbosh/ApacheHTTPResponse.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2009 Guenther Niess
+ *
+ * Licensed 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 com.kenai.jbosh;
+
+import java.io.IOException;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ByteArrayEntity;
+
+import org.apache.http.protocol.BasicHttpContext;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.util.EntityUtils;
+
+final class ApacheHTTPResponse implements HTTPResponse {
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Constants:
+
+    /**
+     * Name of the accept encoding header.
+     */
+    private static final String ACCEPT_ENCODING = "Accept-Encoding";
+
+    /**
+     * Value to use for the ACCEPT_ENCODING header.
+     */
+    private static final String ACCEPT_ENCODING_VAL =
+            ZLIBCodec.getID() + ", " + GZIPCodec.getID();
+
+    /**
+     * Name of the character set to encode the body to/from.
+     */
+    private static final String CHARSET = "UTF-8";
+
+    /**
+     * Content type to use when transmitting the body data.
+     */
+    private static final String CONTENT_TYPE = "text/xml; charset=utf-8";
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Class variables:
+
+    /**
+     * Lock used for internal synchronization.
+     */
+    private final Lock lock = new ReentrantLock();
+
+    /**
+     * The execution state of an HTTP process.
+     */
+    private final HttpContext context;
+
+    /**
+     * HttpClient instance to use to communicate.
+     */
+    private final HttpClient client;
+
+    /**
+     * The HTTP POST request is sent to the server.
+     */
+    private final HttpPost post;
+
+    /**
+     * A flag which indicates if the transmission was already done.
+     */
+    private boolean sent;
+
+    /**
+     * Exception to throw when the response data is attempted to be accessed,
+     * or {@code null} if no exception should be thrown.
+     */
+    private BOSHException toThrow;
+
+    /**
+     * The response body which was received from the server or {@code null}
+     * if that has not yet happened.
+     */
+    private AbstractBody body;
+
+    /**
+     * The HTTP response status code.
+     */
+    private int statusCode;
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Constructors:
+
+    /**
+     * Create and send a new request to the upstream connection manager,
+     * providing deferred access to the results to be returned.
+     *
+     * @param client client instance to use when sending the request
+     * @param cfg client configuration
+     * @param params connection manager parameters from the session creation
+     *  response, or {@code null} if the session has not yet been established
+     * @param request body of the client request
+     */
+    ApacheHTTPResponse(
+            final HttpClient client,
+            final BOSHClientConfig cfg,
+            final CMSessionParams params,
+            final AbstractBody request) {
+        super();
+        this.client = client;
+        this.context = new BasicHttpContext();
+        this.post = new HttpPost(cfg.getURI().toString());
+        this.sent = false;
+
+        try {
+            String xml = request.toXML();
+            byte[] data = xml.getBytes(CHARSET);
+
+            String encoding = null;
+            if (cfg.isCompressionEnabled() && params != null) {
+                AttrAccept accept = params.getAccept();
+                if (accept != null) {
+                    if (accept.isAccepted(ZLIBCodec.getID())) {
+                        encoding = ZLIBCodec.getID();
+                        data = ZLIBCodec.encode(data);
+                    } else if (accept.isAccepted(GZIPCodec.getID())) {
+                        encoding = GZIPCodec.getID();
+                        data = GZIPCodec.encode(data);
+                    }
+                }
+            }
+
+            ByteArrayEntity entity = new ByteArrayEntity(data);
+            entity.setContentType(CONTENT_TYPE);
+            if (encoding != null) {
+                entity.setContentEncoding(encoding);
+            }
+            post.setEntity(entity);
+            if (cfg.isCompressionEnabled()) {
+                post.setHeader(ACCEPT_ENCODING, ACCEPT_ENCODING_VAL);
+            }
+        } catch (Exception e) {
+            toThrow = new BOSHException("Could not generate request", e);
+        }
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    // HTTPResponse interface methods:
+
+    /**
+     * Abort the client transmission and response processing.
+     */
+    public void abort() {
+        if (post != null) {
+            post.abort();
+            toThrow = new BOSHException("HTTP request aborted");
+        }
+    }
+
+    /**
+     * Wait for and then return the response body.
+     *
+     * @return body of the response
+     * @throws InterruptedException if interrupted while awaiting the response
+     * @throws BOSHException on communication failure
+     */
+    public AbstractBody getBody() throws InterruptedException, BOSHException {
+        if (toThrow != null) {
+            throw(toThrow);
+        }
+        lock.lock();
+        try {
+            if (!sent) {
+                awaitResponse();
+            }
+        } finally {
+            lock.unlock();
+        }
+        return body;
+    }
+
+    /**
+     * Wait for and then return the response HTTP status code.
+     *
+     * @return HTTP status code of the response
+     * @throws InterruptedException if interrupted while awaiting the response
+     * @throws BOSHException on communication failure
+     */
+    public int getHTTPStatus() throws InterruptedException, BOSHException {
+        if (toThrow != null) {
+            throw(toThrow);
+        }
+        lock.lock();
+        try {
+            if (!sent) {
+                awaitResponse();
+            }
+        } finally {
+            lock.unlock();
+        }
+        return statusCode;
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Package-private methods:
+
+    /**
+     * Await the response, storing the result in the instance variables of
+     * this class when they arrive.
+     *
+     * @throws InterruptedException if interrupted while awaiting the response
+     * @throws BOSHException on communication failure
+     */
+    private synchronized void awaitResponse() throws BOSHException {
+        HttpEntity entity = null;
+        try {
+            HttpResponse httpResp = client.execute(post, context);
+            entity = httpResp.getEntity();
+            byte[] data = EntityUtils.toByteArray(entity);
+            String encoding = entity.getContentEncoding() != null ?
+                    entity.getContentEncoding().getValue() :
+                    null;
+            if (ZLIBCodec.getID().equalsIgnoreCase(encoding)) {
+                data = ZLIBCodec.decode(data);
+            } else if (GZIPCodec.getID().equalsIgnoreCase(encoding)) {
+                data = GZIPCodec.decode(data);
+            }
+            body = StaticBody.fromString(new String(data, CHARSET));
+            statusCode = httpResp.getStatusLine().getStatusCode();
+            sent = true;
+        } catch (IOException iox) {
+            abort();
+            toThrow = new BOSHException("Could not obtain response", iox);
+            throw(toThrow);
+        } catch (RuntimeException ex) {
+            abort();
+            throw(ex);
+        }
+    }
+}
diff --git com/kenai/jbosh/ApacheHTTPSender.java com/kenai/jbosh/ApacheHTTPSender.java
new file mode 100644
index 0000000..2abb4ee
--- /dev/null
+++ com/kenai/jbosh/ApacheHTTPSender.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2009 Guenther Niess
+ *
+ * Licensed 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 com.kenai.jbosh;
+
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.apache.http.HttpHost;
+import org.apache.http.HttpVersion;
+import org.apache.http.client.HttpClient;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.params.ConnManagerParams;
+import org.apache.http.conn.params.ConnRoutePNames;
+import org.apache.http.conn.scheme.PlainSocketFactory;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
+import org.apache.http.params.BasicHttpParams;
+import org.apache.http.params.HttpParams;
+import org.apache.http.params.HttpProtocolParams;
+
+/**
+ * Implementation of the {@code HTTPSender} interface which uses the
+ * Apache HttpClient API to send messages to the connection manager.
+ */
+final class ApacheHTTPSender implements HTTPSender {
+
+    /**
+     * Lock used for internal synchronization.
+     */
+    private final Lock lock = new ReentrantLock();
+
+    /**
+     * Session configuration.
+     */
+    private BOSHClientConfig cfg;
+
+    /**
+     * HttpClient instance to use to communicate.
+     */
+    private HttpClient httpClient;
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Constructors:
+
+    /**
+     * Prevent construction apart from our package.
+     */
+    ApacheHTTPSender() {
+        // Load Apache HTTP client class
+        HttpClient.class.getName();
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    // HTTPSender interface methods:
+
+    /**
+     * {@inheritDoc}
+     */
+    public void init(final BOSHClientConfig session) {
+        lock.lock();
+        try {
+            cfg = session;
+            httpClient = initHttpClient(session);
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void destroy() {
+        lock.lock();
+        try {
+            if (httpClient != null) {
+                httpClient.getConnectionManager().shutdown();
+            }
+        } finally {
+            cfg = null;
+            httpClient = null;
+            lock.unlock();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public HTTPResponse send(
+            final CMSessionParams params,
+            final AbstractBody body) {
+        HttpClient mClient;
+        BOSHClientConfig mCfg;
+        lock.lock();
+        try {
+            if (httpClient == null) {
+                httpClient = initHttpClient(cfg);
+            }
+            mClient = httpClient;
+            mCfg = cfg;
+        } finally {
+            lock.unlock();
+        }
+        return new ApacheHTTPResponse(mClient, mCfg, params, body);
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Package-private methods:
+
+    private synchronized HttpClient initHttpClient(final BOSHClientConfig config) {
+        // Create and initialize HTTP parameters
+        HttpParams params = new BasicHttpParams();
+        ConnManagerParams.setMaxTotalConnections(params, 100);
+        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
+        HttpProtocolParams.setUseExpectContinue(params, false);
+        if (config != null &&
+                config.getProxyHost() != null &&
+                config.getProxyPort() != 0) {
+            HttpHost proxy = new HttpHost(
+                    config.getProxyHost(),
+                    config.getProxyPort());
+            params.setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
+        }
+
+        // Create and initialize scheme registry 
+        SchemeRegistry schemeRegistry = new SchemeRegistry();
+        schemeRegistry.register(
+                new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
+            SSLSocketFactory sslFactory = SSLSocketFactory.getSocketFactory();
+            sslFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
+            schemeRegistry.register(
+                    new Scheme("https", sslFactory, 443));
+
+        // Create an HttpClient with the ThreadSafeClientConnManager.
+        // This connection manager must be used if more than one thread will
+        // be using the HttpClient.
+        ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
+        return new DefaultHttpClient(cm, params);
+    }
+}
diff --git com/kenai/jbosh/BodyParserXmlPull.java com/kenai/jbosh/BodyParserXmlPull.java
index cc95236..5f23b06 100644
--- com/kenai/jbosh/BodyParserXmlPull.java
+++ com/kenai/jbosh/BodyParserXmlPull.java
@@ -22,7 +22,6 @@ import java.lang.ref.SoftReference;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import javax.xml.XMLConstants;
-import javax.xml.namespace.QName;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlPullParserFactory;
diff --git com/kenai/jbosh/BodyQName.java com/kenai/jbosh/BodyQName.java
index fc7ab0c..83acdf1 100644
--- com/kenai/jbosh/BodyQName.java
+++ com/kenai/jbosh/BodyQName.java
@@ -16,8 +16,6 @@
 
 package com.kenai.jbosh;
 
-import javax.xml.namespace.QName;
-
 /**
  * Qualified name of an attribute of the wrapper element.  This class is
  * analagous to the {@code javax.xml.namespace.QName} class.