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 2021/10/31 02:43:48 UTC

[cxf] branch 3.4.x-fixes updated (2c93636 -> 2d065f3)

This is an automated email from the ASF dual-hosted git repository.

reta pushed a change to branch 3.4.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git.


    from 2c93636  CXF-8610:Add null check to IOUtils to avoid null CCL (#867)
     new 7ce2fd8  CXF-8605: Introduce HTTP/2 Transport: server-side support (#861)
     new 08d05f5  CXF-8605: Introduce HTTP/2 Transport: server-side support. Fixing basic_http2_jetty/pom.xml
     new ca9bd0d   CXF-8605: Introduce HTTP/2 Transport: server-side support. Fixing distribution/javadoc
     new 54ecc5e   CXF-8605: Introduce HTTP/2 Transport: server-side support. Fixing dependency scopes for jax_rs/basic_http2_jetty example
     new 2d065f3  Recording .gitmergeinfo Changes

The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .gitmergeinfo                                      |   1 +
 distribution/javadoc/pom.xml                       |  13 +
 .../samples/jax_rs/basic_http2_jetty/README.txt    |  92 +++++
 .../samples/jax_rs/basic_http2_jetty/pom.xml       | 131 +++++++
 .../src/main/config/KeyREADME.txt                  |   8 +
 .../src/main/config/serviceKeystore.jks            | Bin 0 -> 3743 bytes
 .../src/main/java/http2demo/common/Customer.java   |  43 +++
 .../java/http2demo/common/CustomerService.java     |  52 +++
 .../java/http2demo/server/CustomerServiceImpl.java |  89 +++++
 .../src/main/java/http2demo/server/h2/Server.java  |  59 +++
 .../src/main/java/http2demo/server/h2c/Server.java |  59 +++
 .../src/main/resources/ServerConfig.xml            |  48 +++
 .../samples/jax_rs/basic_http2_netty/README.txt    |  92 +++++
 .../samples/jax_rs/basic_http2_netty/pom.xml       | 100 +++++
 .../src/main/config/KeyREADME.txt                  |   8 +
 .../src/main/config/serviceKeystore.jks            | Bin 0 -> 3742 bytes
 .../src/main/java/http2demo/common/Customer.java   |  43 +++
 .../java/http2demo/common/CustomerService.java     |  52 +++
 .../java/http2demo/server/CustomerServiceImpl.java |  89 +++++
 .../src/main/java/http2demo/server/h2/Server.java  |  59 +++
 .../src/main/java/http2demo/server/h2c/Server.java |  59 +++
 .../src/main/resources/ServerConfig.xml            |  48 +++
 .../samples/jax_rs/basic_http2_undertow/README.txt |  93 +++++
 .../samples/jax_rs/basic_http2_undertow/pom.xml    |  95 +++++
 .../src/main/config/KeyREADME.txt                  |   8 +
 .../src/main/config/serviceKeystore.jks            | Bin 0 -> 3742 bytes
 .../src/main/java/http2demo/common/Customer.java   |  43 +++
 .../java/http2demo/common/CustomerService.java     |  52 +++
 .../java/http2demo/server/CustomerServiceImpl.java |  89 +++++
 .../src/main/java/http2demo/server/h2/Server.java  |  59 +++
 .../src/main/java/http2demo/server/h2c/Server.java |  59 +++
 .../src/main/resources/ServerConfig.xml            |  48 +++
 distribution/src/main/release/samples/pom.xml      |   6 +-
 parent/pom.xml                                     |  10 +
 rt/transports/http-jetty/pom.xml                   |  10 +
 .../http_jetty/JettyHTTPServerEngine.java          |  43 ++-
 rt/transports/http-netty/netty-server/pom.xml      |   6 +
 .../http/netty/server/NettyHttpServerEngine.java   |  27 +-
 .../netty/server/NettyHttpServerEngineFactory.java |   2 +-
 .../server/NettyHttpServletPipelineFactory.java    | 230 +++++++++++-
 .../NettyHttpServerEngineBeanDefinitionParser.java |  14 +-
 .../http_undertow/UndertowHTTPServerEngine.java    |  32 +-
 .../transport/http/HttpServerEngineSupport.java    |  47 +++
 .../transport/https/SSLContextInitParameters.java  |  44 +++
 .../org/apache/cxf/transport/https/SSLUtils.java   |  34 +-
 systests/pom.xml                                   |   1 +
 systests/{transports => transport-netty}/pom.xml   | 194 ++--------
 .../http2/netty/AbstractBookServerHttp2.java       |  64 ++++
 .../netty/AbstractNettyClientServerHttp2Test.java  | 118 ++++++
 .../org/apache/cxf/systest/http2/netty/Book.java   |  69 ++++
 .../cxf/systest/http2/netty/BookServerHttp2.java   |  47 +++
 .../cxf/systest/http2/netty/BookServerHttp2c.java  |  45 +++
 .../apache/cxf/systest/http2/netty/BookStore.java  |  68 ++++
 .../cxf/systest/http2/netty/Http2TestClient.java   | 401 +++++++++++++++++++++
 .../http2/netty/NettyClientServerHttp2Test.java    |  48 +++
 .../http2/netty/NettyClientServerHttp2cTest.java   |  47 +++
 .../apache/cxf/systest/http2_netty/server-tls.xml  |  41 +++
 .../org/apache/cxf/systest/http2_netty/server.xml  |  32 ++
 .../http2/AbstractBookServerHttp2.java             |  66 ++++
 .../AbstractUndertowClientServerHttp2Test.java     | 120 ++++++
 .../http_undertow/http2/BookServerHttp2.java       |  45 +++
 .../http_undertow/http2/BookServerHttp2c.java      |  45 +++
 .../http_undertow/http2/Http2TestClient.java       | 184 ++++++++++
 .../http2/UndertowClientServerHttp2Test.java       |  48 +++
 .../http2/UndertowClientServerHttp2cTest.java      |  48 +++
 .../cxf/systest/http_undertow/http2/server-tls.xml |  41 +++
 .../cxf/systest/http_undertow/http2/server.xml     |  32 ++
 systests/transports/pom.xml                        |  56 +++
 .../http2_jetty/AbstractBookServerHttp2.java       |  64 ++++
 .../AbstractJettyClientServerHttp2Test.java        | 119 ++++++
 .../org/apache/cxf/systest/http2_jetty/Book.java   |  69 ++++
 .../cxf/systest/http2_jetty/BookServerHttp2.java   |  47 +++
 .../cxf/systest/http2_jetty/BookServerHttp2c.java  |  45 +++
 .../apache/cxf/systest/http2_jetty/BookStore.java  |  68 ++++
 .../cxf/systest/http2_jetty/Http2TestClient.java   | 212 +++++++++++
 .../http2_jetty/JettyClientServerHttp2Test.java    |  48 +++
 .../http2_jetty/JettyClientServerHttp2cTest.java   |  47 +++
 .../apache/cxf/systest/http2_jetty/server-tls.xml  |  41 +++
 .../org/apache/cxf/systest/http2_jetty/server.xml  |  32 ++
 79 files changed, 4618 insertions(+), 230 deletions(-)
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_jetty/README.txt
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_jetty/pom.xml
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/config/KeyREADME.txt
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/config/serviceKeystore.jks
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/java/http2demo/common/Customer.java
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/java/http2demo/common/CustomerService.java
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/java/http2demo/server/CustomerServiceImpl.java
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/java/http2demo/server/h2/Server.java
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/java/http2demo/server/h2c/Server.java
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/resources/ServerConfig.xml
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_netty/README.txt
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_netty/pom.xml
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/config/KeyREADME.txt
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/config/serviceKeystore.jks
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/java/http2demo/common/Customer.java
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/java/http2demo/common/CustomerService.java
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/java/http2demo/server/CustomerServiceImpl.java
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/java/http2demo/server/h2/Server.java
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/java/http2demo/server/h2c/Server.java
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/resources/ServerConfig.xml
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_undertow/README.txt
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_undertow/pom.xml
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/config/KeyREADME.txt
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/config/serviceKeystore.jks
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/java/http2demo/common/Customer.java
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/java/http2demo/common/CustomerService.java
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/java/http2demo/server/CustomerServiceImpl.java
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/java/http2demo/server/h2/Server.java
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/java/http2demo/server/h2c/Server.java
 create mode 100644 distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/resources/ServerConfig.xml
 create mode 100644 rt/transports/http/src/main/java/org/apache/cxf/transport/http/HttpServerEngineSupport.java
 create mode 100644 rt/transports/http/src/main/java/org/apache/cxf/transport/https/SSLContextInitParameters.java
 copy systests/{transports => transport-netty}/pom.xml (53%)
 create mode 100644 systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/AbstractBookServerHttp2.java
 create mode 100644 systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/AbstractNettyClientServerHttp2Test.java
 create mode 100644 systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/Book.java
 create mode 100644 systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/BookServerHttp2.java
 create mode 100644 systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/BookServerHttp2c.java
 create mode 100644 systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/BookStore.java
 create mode 100644 systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/Http2TestClient.java
 create mode 100644 systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/NettyClientServerHttp2Test.java
 create mode 100644 systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/NettyClientServerHttp2cTest.java
 create mode 100644 systests/transport-netty/src/test/resources/org/apache/cxf/systest/http2_netty/server-tls.xml
 create mode 100644 systests/transport-netty/src/test/resources/org/apache/cxf/systest/http2_netty/server.xml
 create mode 100644 systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/AbstractBookServerHttp2.java
 create mode 100644 systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/AbstractUndertowClientServerHttp2Test.java
 create mode 100644 systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/BookServerHttp2.java
 create mode 100644 systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/BookServerHttp2c.java
 create mode 100644 systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/Http2TestClient.java
 create mode 100644 systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/UndertowClientServerHttp2Test.java
 create mode 100644 systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/UndertowClientServerHttp2cTest.java
 create mode 100644 systests/transport-undertow/src/test/resources/org/apache/cxf/systest/http_undertow/http2/server-tls.xml
 create mode 100644 systests/transport-undertow/src/test/resources/org/apache/cxf/systest/http_undertow/http2/server.xml
 create mode 100644 systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/AbstractBookServerHttp2.java
 create mode 100644 systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/AbstractJettyClientServerHttp2Test.java
 create mode 100644 systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/Book.java
 create mode 100644 systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/BookServerHttp2.java
 create mode 100644 systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/BookServerHttp2c.java
 create mode 100644 systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/BookStore.java
 create mode 100644 systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/Http2TestClient.java
 create mode 100644 systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/JettyClientServerHttp2Test.java
 create mode 100644 systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/JettyClientServerHttp2cTest.java
 create mode 100644 systests/transports/src/test/resources/org/apache/cxf/systest/http2_jetty/server-tls.xml
 create mode 100644 systests/transports/src/test/resources/org/apache/cxf/systest/http2_jetty/server.xml

[cxf] 01/05: CXF-8605: Introduce HTTP/2 Transport: server-side support (#861)

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

reta pushed a commit to branch 3.4.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git

commit 7ce2fd8dc57ff230af1e200a2d4cdd3357724766
Author: Andriy Redko <dr...@gmail.com>
AuthorDate: Sat Oct 30 11:28:48 2021 -0400

    CXF-8605: Introduce HTTP/2 Transport: server-side support (#861)
    
    (cherry picked from commit 965e1bb9e9658f4024f33bf832308f8b8dfce4b6)
    
    # Conflicts:
    #	distribution/src/main/release/samples/pom.xml
    #	rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPServerEngine.java
    #	systests/transports/pom.xml
---
 .../samples/jax_rs/basic_http2_jetty/README.txt    |  92 +++++
 .../samples/jax_rs/basic_http2_jetty/pom.xml       | 136 +++++++
 .../src/main/config/KeyREADME.txt                  |   8 +
 .../src/main/config/serviceKeystore.jks            | Bin 0 -> 3743 bytes
 .../src/main/java/http2demo/common/Customer.java   |  43 +++
 .../java/http2demo/common/CustomerService.java     |  52 +++
 .../java/http2demo/server/CustomerServiceImpl.java |  89 +++++
 .../src/main/java/http2demo/server/h2/Server.java  |  59 +++
 .../src/main/java/http2demo/server/h2c/Server.java |  59 +++
 .../src/main/resources/ServerConfig.xml            |  48 +++
 .../samples/jax_rs/basic_http2_netty/README.txt    |  92 +++++
 .../samples/jax_rs/basic_http2_netty/pom.xml       | 100 +++++
 .../src/main/config/KeyREADME.txt                  |   8 +
 .../src/main/config/serviceKeystore.jks            | Bin 0 -> 3742 bytes
 .../src/main/java/http2demo/common/Customer.java   |  43 +++
 .../java/http2demo/common/CustomerService.java     |  52 +++
 .../java/http2demo/server/CustomerServiceImpl.java |  89 +++++
 .../src/main/java/http2demo/server/h2/Server.java  |  59 +++
 .../src/main/java/http2demo/server/h2c/Server.java |  59 +++
 .../src/main/resources/ServerConfig.xml            |  48 +++
 .../samples/jax_rs/basic_http2_undertow/README.txt |  93 +++++
 .../samples/jax_rs/basic_http2_undertow/pom.xml    |  95 +++++
 .../src/main/config/KeyREADME.txt                  |   8 +
 .../src/main/config/serviceKeystore.jks            | Bin 0 -> 3742 bytes
 .../src/main/java/http2demo/common/Customer.java   |  43 +++
 .../java/http2demo/common/CustomerService.java     |  52 +++
 .../java/http2demo/server/CustomerServiceImpl.java |  89 +++++
 .../src/main/java/http2demo/server/h2/Server.java  |  59 +++
 .../src/main/java/http2demo/server/h2c/Server.java |  59 +++
 .../src/main/resources/ServerConfig.xml            |  48 +++
 distribution/src/main/release/samples/pom.xml      |   6 +-
 parent/pom.xml                                     |  10 +
 rt/transports/http-jetty/pom.xml                   |  10 +
 .../http_jetty/JettyHTTPServerEngine.java          |  43 ++-
 rt/transports/http-netty/netty-server/pom.xml      |   6 +
 .../http/netty/server/NettyHttpServerEngine.java   |  27 +-
 .../netty/server/NettyHttpServerEngineFactory.java |   2 +-
 .../server/NettyHttpServletPipelineFactory.java    | 230 +++++++++++-
 .../NettyHttpServerEngineBeanDefinitionParser.java |  14 +-
 .../http_undertow/UndertowHTTPServerEngine.java    |  32 +-
 .../transport/http/HttpServerEngineSupport.java    |  47 +++
 .../transport/https/SSLContextInitParameters.java  |  44 +++
 .../org/apache/cxf/transport/https/SSLUtils.java   |  34 +-
 systests/pom.xml                                   |   1 +
 systests/{transports => transport-netty}/pom.xml   | 194 ++--------
 .../http2/netty/AbstractBookServerHttp2.java       |  64 ++++
 .../netty/AbstractNettyClientServerHttp2Test.java  | 118 ++++++
 .../org/apache/cxf/systest/http2/netty/Book.java   |  69 ++++
 .../cxf/systest/http2/netty/BookServerHttp2.java   |  47 +++
 .../cxf/systest/http2/netty/BookServerHttp2c.java  |  45 +++
 .../apache/cxf/systest/http2/netty/BookStore.java  |  68 ++++
 .../cxf/systest/http2/netty/Http2TestClient.java   | 401 +++++++++++++++++++++
 .../http2/netty/NettyClientServerHttp2Test.java    |  48 +++
 .../http2/netty/NettyClientServerHttp2cTest.java   |  47 +++
 .../apache/cxf/systest/http2_netty/server-tls.xml  |  41 +++
 .../org/apache/cxf/systest/http2_netty/server.xml  |  32 ++
 .../http2/AbstractBookServerHttp2.java             |  66 ++++
 .../AbstractUndertowClientServerHttp2Test.java     | 120 ++++++
 .../http_undertow/http2/BookServerHttp2.java       |  45 +++
 .../http_undertow/http2/BookServerHttp2c.java      |  45 +++
 .../http_undertow/http2/Http2TestClient.java       | 184 ++++++++++
 .../http2/UndertowClientServerHttp2Test.java       |  48 +++
 .../http2/UndertowClientServerHttp2cTest.java      |  48 +++
 .../cxf/systest/http_undertow/http2/server-tls.xml |  41 +++
 .../cxf/systest/http_undertow/http2/server.xml     |  32 ++
 systests/transports/pom.xml                        |  56 +++
 .../http2_jetty/AbstractBookServerHttp2.java       |  64 ++++
 .../AbstractJettyClientServerHttp2Test.java        | 119 ++++++
 .../org/apache/cxf/systest/http2_jetty/Book.java   |  69 ++++
 .../cxf/systest/http2_jetty/BookServerHttp2.java   |  47 +++
 .../cxf/systest/http2_jetty/BookServerHttp2c.java  |  45 +++
 .../apache/cxf/systest/http2_jetty/BookStore.java  |  68 ++++
 .../cxf/systest/http2_jetty/Http2TestClient.java   | 212 +++++++++++
 .../http2_jetty/JettyClientServerHttp2Test.java    |  48 +++
 .../http2_jetty/JettyClientServerHttp2cTest.java   |  47 +++
 .../apache/cxf/systest/http2_jetty/server-tls.xml  |  41 +++
 .../org/apache/cxf/systest/http2_jetty/server.xml  |  32 ++
 77 files changed, 4609 insertions(+), 230 deletions(-)

diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/README.txt b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/README.txt
new file mode 100644
index 0000000..df1bc1f
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/README.txt
@@ -0,0 +1,92 @@
+JAX-RS Basic Demo With HTTPS communications
+===========================================
+
+This demo takes the JAX-RS basic demo a step further 
+by doing the communication using HTTP/2 over TLS and
+HTTP/2 over cleartext using Jetty container.
+
+Building and running the demo using Maven
+-----------------------------------------
+From the base directory of this sample (i.e., where this README file is
+located), the Maven pom.xml file can be used to build and run the demo. 
+
+Using either UNIX or Windows:
+
+  mvn install
+  mvn -Ph2-server  (HTTP/2 over TLS)
+  mvn -Ph2c-server  (HTTP/2 over cleartext)
+    
+To remove the target dir, run "mvn clean".
+
+Certificates
+------------
+See the src/main/config folder for the sample keys used (don't use
+these keys in production!) as well as scripts used for their creation.
+
+HTTP/2 over cleartext
+------------
+
+- Upgrade from HTTP/1.1 to HTTP/2 (cleartext)
+
+    $ curl http://localhost:9001/customerservice/customers/123 --http2 -i
+  
+    HTTP/1.1 101 Switching Protocols
+    HTTP/2 200
+    server: Jetty(9.4.44.v20210927)
+    date: Thu, 14 Oct 2021 01:35:58 GMT
+    content-type: application/xml
+    content-length: 105
+ 
+    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Customer><id>123</id><name>John</name></Customer>
+
+- Use HTTP/2 prior knowledge (cleartext)
+
+    $ curl http://localhost:9001/customerservice/customers/123 --http2-prior-knowledge -i
+  
+    HTTP/2 200
+    server: Jetty(9.4.44.v20210927)
+    date: Thu, 14 Oct 2021 01:36:44 GMT
+    content-type: application/xml
+    content-length: 105
+
+    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Customer><id>123</id><name>John</name></Customer>
+  
+- Force HTTP/1.1 usage (cleartext)
+
+    $ curl http://localhost:9001/customerservice/customers/123 --http1.1 -i
+  
+    HTTP/1.1 200 OK
+    Date: Thu, 14 Oct 2021 01:37:06 GMT
+    Content-Type: application/xml
+    Content-Length: 105
+    Server: Jetty(9.4.44.v20210927)
+  
+    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Customer><id>123</id><name>John</name></Customer>
+    
+HTTP/2 over TLS
+------------
+
+- Use HTTP/2
+
+    $ curl https://localhost:9000/customerservice/customers/123 --http2 -ik
+  
+    HTTP/2 200
+    server: Jetty(9.4.44.v20210927)
+    date: Thu, 14 Oct 2021 01:25:26 GMT
+    content-type: application/xml
+    content-length: 105
+
+    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Customer><id>123</id><name>John</name></Customer>
+  
+- Force HTTP/1.1 usage
+
+    $ curl https://localhost:9000/customerservice/customers/123 --http1.1 -ik
+  
+    HTTP/1.1 200 OK
+    Date: Thu, 14 Oct 2021 01:26:06 GMT
+    Content-Type: application/xml
+    Content-Length: 105
+    Server: Jetty(9.4.44.v20210927)
+  
+    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Customer><id>123</id><name>John</name></Customer>
+
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/pom.xml b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/pom.xml
new file mode 100644
index 0000000..3691cd0
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/pom.xml
@@ -0,0 +1,136 @@
+<?xml version="1.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.
+-->
+<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>
+    <artifactId>jax_rs_basic_http2_jetty</artifactId>
+    <name>JAX-RS Basic Demo With HTTP/2 communications</name>
+    <description>JAX-RS Basic Demo With HTTP/2 communications</description>
+    <parent>
+        <groupId>org.apache.cxf.samples</groupId>
+        <artifactId>cxf-samples</artifactId>
+        <version>3.4.6-SNAPSHOT</version>
+        <relativePath>../..</relativePath>
+    </parent>
+    <profiles>
+        <profile>
+            <id>h2-server</id>
+            <build>
+                <defaultGoal>test</defaultGoal>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>test</phase>
+                                <goals>
+                                    <goal>java</goal>
+                                </goals>
+                                <configuration>
+                                    <mainClass>http2demo.server.h2.Server</mainClass>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>h2c-server</id>
+            <build>
+                <defaultGoal>test</defaultGoal>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>test</phase>
+                                <goals>
+                                    <goal>java</goal>
+                                </goals>
+                                <configuration>
+                                    <mainClass>http2demo.server.h2c.Server</mainClass>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-transports-http-jetty</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty.http2</groupId>
+            <artifactId>http2-server</artifactId>
+            <version>${cxf.jetty9.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-alpn-server</artifactId>
+            <version>${cxf.jetty9.version}</version>
+        </dependency>
+    </dependencies>
+    
+    <profiles>
+        <profile>
+            <id>jdk8</id>
+            <activation>
+                <jdk>1.8</jdk>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-alpn-openjdk8-server</artifactId>
+                    <version>${cxf.jetty9.version}</version>
+                    <scope>test</scope>
+                </dependency>
+            </dependencies>
+        </profile>
+        <profile>
+            <id>jdk9+</id>
+            <activation>
+                <jdk>[9,)</jdk>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-alpn-java-server</artifactId>
+                    <version>${cxf.jetty9.version}</version>
+                    <scope>test</scope>
+                </dependency>
+            </dependencies>
+        </profile>
+    </profiles>
+</project>
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/config/KeyREADME.txt b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/config/KeyREADME.txt
new file mode 100644
index 0000000..97f20fa
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/config/KeyREADME.txt
@@ -0,0 +1,8 @@
+# The below scripts show the commands used to generate the self-signed keys for this sample.
+# If you use the below script to create your own keys be sure to change the passwords used here
+# DO NOT USE THE SUPPLIED KEYS IN PRODUCTION--everyone has them!!
+# For production recommended to use keys signed by a third-party certificate authority (CA)
+
+# Create the combination keystore/truststore for the server.
+keytool -genkeypair -keyalg RSA -keysize 4096 -validity 730 -alias myservicekey -keystore serviceKeystore.jks -dname "cn=localhost" -keypass skpass -storepass sspass
+
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/config/serviceKeystore.jks b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/config/serviceKeystore.jks
new file mode 100644
index 0000000..7801717
Binary files /dev/null and b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/config/serviceKeystore.jks differ
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/java/http2demo/common/Customer.java b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/java/http2demo/common/Customer.java
new file mode 100644
index 0000000..81ce3c5
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/java/http2demo/common/Customer.java
@@ -0,0 +1,43 @@
+/**
+ * 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 http2demo.common;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "Customer")
+public class Customer {
+    private long id;
+    private String name;
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/java/http2demo/common/CustomerService.java b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/java/http2demo/common/CustomerService.java
new file mode 100644
index 0000000..890ade3
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/java/http2demo/common/CustomerService.java
@@ -0,0 +1,52 @@
+/**
+ * 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 http2demo.common;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Response;
+
+/**
+ * This interface describes a JAX-RS root resource. All the JAXRS annotations (except those overridden) will
+ * be inherited by classes implementing it.
+ */
+@Path("/customerservice/")
+public interface CustomerService {
+
+    @GET
+    @Path("/customers/{id}/")
+    Customer getCustomer(@PathParam("id") String id);
+
+    @PUT
+    @Path("/customers/")
+    Response updateCustomer(Customer customer);
+
+    @POST
+    @Path("/customers/")
+    Response addCustomer(Customer customer);
+
+    @DELETE
+    @Path("/customers/{id}/")
+    Response deleteCustomer(@PathParam("id") String id);
+
+}
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/java/http2demo/server/CustomerServiceImpl.java b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/java/http2demo/server/CustomerServiceImpl.java
new file mode 100644
index 0000000..171d27b
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/java/http2demo/server/CustomerServiceImpl.java
@@ -0,0 +1,89 @@
+/**
+ * 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 http2demo.server;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.core.Response;
+
+import http2demo.common.Customer;
+import http2demo.common.CustomerService;
+
+public class CustomerServiceImpl implements CustomerService {
+    long currentId = 123;
+    Map<Long, Customer> customers = new HashMap<>();
+
+    public CustomerServiceImpl() {
+        init();
+    }
+
+    public Customer getCustomer(String id) {
+        System.out.println("----invoking getCustomer, Customer id is: " + id);
+        long idNumber = Long.parseLong(id);
+        return customers.get(idNumber);
+    }
+
+    public Response updateCustomer(Customer customer) {
+        System.out.println("----invoking updateCustomer, Customer name is: " + customer.getName());
+        Customer c = customers.get(customer.getId());
+        Response r;
+        if (c != null) {
+            customers.put(customer.getId(), customer);
+            r = Response.ok().build();
+        } else {
+            r = Response.notModified().build();
+        }
+
+        return r;
+    }
+
+    public Response addCustomer(Customer customer) {
+        System.out.println("----invoking addCustomer, Customer name is: " + customer.getName());
+        customer.setId(++currentId);
+
+        customers.put(customer.getId(), customer);
+
+        return Response.ok(customer).build();
+    }
+
+    public Response deleteCustomer(String id) {
+        System.out.println("----invoking deleteCustomer, Customer id is: " + id);
+        long idNumber = Long.parseLong(id);
+        Customer c = customers.get(idNumber);
+
+        Response r;
+        if (c != null) {
+            r = Response.ok().build();
+            customers.remove(idNumber);
+        } else {
+            r = Response.notModified().build();
+        }
+
+        return r;
+    }
+
+    final void init() {
+        Customer c = new Customer();
+        c.setName("John");
+        c.setId(123);
+        customers.put(c.getId(), c);
+    }
+
+}
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/java/http2demo/server/h2/Server.java b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/java/http2demo/server/h2/Server.java
new file mode 100644
index 0000000..d821996
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/java/http2demo/server/h2/Server.java
@@ -0,0 +1,59 @@
+/**
+ * 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 http2demo.server.h2;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
+import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
+import org.apache.cxf.transport.http.HttpServerEngineSupport;
+
+import http2demo.server.CustomerServiceImpl;
+
+public class Server {
+
+    static {
+        // set the configuration file
+        SpringBusFactory factory = new SpringBusFactory();
+        Bus bus = factory.createBus("ServerConfig.xml");
+        bus.setProperty(HttpServerEngineSupport.ENABLE_HTTP2, true);
+        BusFactory.setDefaultBus(bus);
+    }
+
+    protected Server() throws Exception {
+        JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
+        sf.setResourceClasses(CustomerServiceImpl.class);
+        sf.setResourceProvider(CustomerServiceImpl.class,
+            new SingletonResourceProvider(new CustomerServiceImpl()));
+        sf.setAddress("https://localhost:9000/");
+
+        sf.create();
+    }
+
+    public static void main(String[] args) throws Exception {
+        new Server();
+        System.out.println("Server ready...");
+
+        Thread.sleep(5 * 60 * 1000);
+        System.out.println("Server exiting");
+        System.exit(0);
+    }
+}
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/java/http2demo/server/h2c/Server.java b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/java/http2demo/server/h2c/Server.java
new file mode 100644
index 0000000..d86ef95
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/java/http2demo/server/h2c/Server.java
@@ -0,0 +1,59 @@
+/**
+ * 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 http2demo.server.h2c;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
+import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
+import org.apache.cxf.transport.http.HttpServerEngineSupport;
+
+import http2demo.server.CustomerServiceImpl;
+
+public class Server {
+
+    static {
+        // set the configuration file
+        SpringBusFactory factory = new SpringBusFactory();
+        Bus bus = factory.createBus();
+        bus.setProperty(HttpServerEngineSupport.ENABLE_HTTP2, true);
+        BusFactory.setDefaultBus(bus);
+    }
+
+    protected Server() throws Exception {
+        JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
+        sf.setResourceClasses(CustomerServiceImpl.class);
+        sf.setResourceProvider(CustomerServiceImpl.class,
+            new SingletonResourceProvider(new CustomerServiceImpl()));
+        sf.setAddress("http://localhost:9001/");
+
+        sf.create();
+    }
+
+    public static void main(String[] args) throws Exception {
+        new Server();
+        System.out.println("Server ready...");
+
+        Thread.sleep(5 * 60 * 1000);
+        System.out.println("Server exiting");
+        System.exit(0);
+    }
+}
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/resources/ServerConfig.xml b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/resources/ServerConfig.xml
new file mode 100644
index 0000000..6ef1e90
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/src/main/resources/ServerConfig.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<!-- 
+  ** This file configures the Server which exposes the REST endpoint.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:sec="http://cxf.apache.org/configuration/security"
+    xmlns:http="http://cxf.apache.org/transports/http/configuration"
+    xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration"
+    xsi:schemaLocation="http://cxf.apache.org/configuration/security 
+            http://cxf.apache.org/schemas/configuration/security.xsd 
+            http://cxf.apache.org/transports/http/configuration 
+            http://cxf.apache.org/schemas/configuration/http-conf.xsd 
+            http://cxf.apache.org/transports/http-jetty/configuration 
+            http://cxf.apache.org/schemas/configuration/http-jetty.xsd 
+            http://www.springframework.org/schema/beans 
+            http://www.springframework.org/schema/beans/spring-beans.xsd">
+    <httpj:engine-factory bus="cxf">
+        <httpj:engine port="9000">
+            <httpj:tlsServerParameters>
+                <sec:keyManagers keyPassword="skpass">
+                    <sec:keyStore file="src/main/config/serviceKeystore.jks" password="sspass" type="JKS"/>
+                </sec:keyManagers>
+                <sec:trustManagers>
+                    <sec:keyStore file="src/main/config/serviceKeystore.jks" password="sspass" type="JKS"/>
+                </sec:trustManagers>
+            </httpj:tlsServerParameters>
+        </httpj:engine>
+    </httpj:engine-factory>
+</beans>
\ No newline at end of file
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_netty/README.txt b/distribution/src/main/release/samples/jax_rs/basic_http2_netty/README.txt
new file mode 100644
index 0000000..cfc5b91
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_netty/README.txt
@@ -0,0 +1,92 @@
+JAX-RS Basic Demo With HTTPS communications
+===========================================
+
+This demo takes the JAX-RS basic demo a step further 
+by doing the communication using HTTP/2 over TLS and
+HTTP/2 over cleartext using Netty container.
+
+Building and running the demo using Maven
+-----------------------------------------
+From the base directory of this sample (i.e., where this README file is
+located), the Maven pom.xml file can be used to build and run the demo. 
+
+Using either UNIX or Windows:
+
+  mvn install
+  mvn -Ph2-server  (HTTP/2 over TLS)
+  mvn -Ph2c-server  (HTTP/2 over cleartext)
+    
+To remove the target dir, run "mvn clean".
+
+Certificates
+------------
+See the src/main/config folder for the sample keys used (don't use
+these keys in production!) as well as scripts used for their creation.
+
+HTTP/2 over cleartext
+------------
+
+- Upgrade from HTTP/1.1 to HTTP/2 (cleartext)
+
+    $ curl http://localhost:9001/customerservice/customers/123 --http2 -i
+  
+    HTTP/1.1 101 Switching Protocols
+    connection: upgrade
+    upgrade: h2c
+
+    HTTP/2 200
+    content-type: application/xml
+    date: Thu, 14 Oct 2021 01:48:35 GMT
+    content-length: 105
+
+    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Customer><id>123</id><name>John</name></Customer>
+
+- Use HTTP/2 prior knowledge (cleartext)
+
+    $ curl http://localhost:9001/customerservice/customers/123 --http2-prior-knowledge -i
+  
+    HTTP/2 200
+    content-type: application/xml
+    date: Thu, 14 Oct 2021 01:49:08 GMT
+    content-length: 105
+
+    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Customer><id>123</id><name>John</name></Customer>
+  
+- Force HTTP/1.1 usage (cleartext)
+
+    $ curl http://localhost:9001/customerservice/customers/123 --http1.1 -i
+  
+    HTTP/1.1 200 OK
+    Content-Type: application/xml
+    Date: Thu, 14 Oct 2021 01:49:35 GMT
+    content-length: 105
+    connection: keep-alive
+  
+    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Customer><id>123</id><name>John</name></Customer>
+    
+HTTP/2 over TLS
+------------
+
+- Use HTTP/2
+
+    $ curl https://localhost:9000/customerservice/customers/123 --http2 -ik
+  
+    HTTP/2 200
+    content-type: application/xml
+    date: Thu, 14 Oct 2021 01:46:59 GMT
+    content-length: 105
+
+    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Customer><id>123</id><name>John</name></Customer>
+  
+- Force HTTP/1.1 usage
+
+    $ curl https://localhost:9000/customerservice/customers/123 --http1.1 -ik
+  
+    HTTP/1.1 200 OK
+    Content-Type: application/xml
+    Date: Thu, 14 Oct 2021 01:47:51 GMT
+    content-length: 105
+    connection: keep-alive
+  
+    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Customer><id>123</id><name>John</name></Customer>
+
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_netty/pom.xml b/distribution/src/main/release/samples/jax_rs/basic_http2_netty/pom.xml
new file mode 100644
index 0000000..2d5bff8
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_netty/pom.xml
@@ -0,0 +1,100 @@
+<?xml version="1.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.
+-->
+<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>
+    <artifactId>jax_rs_basic_http2_netty</artifactId>
+    <name>JAX-RS Basic Demo With HTTP/2 communications</name>
+    <description>JAX-RS Basic Demo With HTTP/2 communications</description>
+    <parent>
+        <groupId>org.apache.cxf.samples</groupId>
+        <artifactId>cxf-samples</artifactId>
+        <version>3.4.6-SNAPSHOT</version>
+        <relativePath>../..</relativePath>
+    </parent>
+    <profiles>
+        <profile>
+            <id>h2-server</id>
+            <build>
+                <defaultGoal>test</defaultGoal>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>test</phase>
+                                <goals>
+                                    <goal>java</goal>
+                                </goals>
+                                <configuration>
+                                    <mainClass>http2demo.server.h2.Server</mainClass>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>h2c-server</id>
+            <build>
+                <defaultGoal>test</defaultGoal>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>test</phase>
+                                <goals>
+                                    <goal>java</goal>
+                                </goals>
+                                <configuration>
+                                    <mainClass>http2demo.server.h2c.Server</mainClass>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-transports-http-netty-server</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-codec-http2</artifactId>
+            <version>${cxf.netty.version}</version>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/config/KeyREADME.txt b/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/config/KeyREADME.txt
new file mode 100644
index 0000000..97f20fa
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/config/KeyREADME.txt
@@ -0,0 +1,8 @@
+# The below scripts show the commands used to generate the self-signed keys for this sample.
+# If you use the below script to create your own keys be sure to change the passwords used here
+# DO NOT USE THE SUPPLIED KEYS IN PRODUCTION--everyone has them!!
+# For production recommended to use keys signed by a third-party certificate authority (CA)
+
+# Create the combination keystore/truststore for the server.
+keytool -genkeypair -keyalg RSA -keysize 4096 -validity 730 -alias myservicekey -keystore serviceKeystore.jks -dname "cn=localhost" -keypass skpass -storepass sspass
+
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/config/serviceKeystore.jks b/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/config/serviceKeystore.jks
new file mode 100644
index 0000000..e3dd4b4
Binary files /dev/null and b/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/config/serviceKeystore.jks differ
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/java/http2demo/common/Customer.java b/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/java/http2demo/common/Customer.java
new file mode 100644
index 0000000..81ce3c5
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/java/http2demo/common/Customer.java
@@ -0,0 +1,43 @@
+/**
+ * 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 http2demo.common;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "Customer")
+public class Customer {
+    private long id;
+    private String name;
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/java/http2demo/common/CustomerService.java b/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/java/http2demo/common/CustomerService.java
new file mode 100644
index 0000000..890ade3
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/java/http2demo/common/CustomerService.java
@@ -0,0 +1,52 @@
+/**
+ * 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 http2demo.common;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Response;
+
+/**
+ * This interface describes a JAX-RS root resource. All the JAXRS annotations (except those overridden) will
+ * be inherited by classes implementing it.
+ */
+@Path("/customerservice/")
+public interface CustomerService {
+
+    @GET
+    @Path("/customers/{id}/")
+    Customer getCustomer(@PathParam("id") String id);
+
+    @PUT
+    @Path("/customers/")
+    Response updateCustomer(Customer customer);
+
+    @POST
+    @Path("/customers/")
+    Response addCustomer(Customer customer);
+
+    @DELETE
+    @Path("/customers/{id}/")
+    Response deleteCustomer(@PathParam("id") String id);
+
+}
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/java/http2demo/server/CustomerServiceImpl.java b/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/java/http2demo/server/CustomerServiceImpl.java
new file mode 100644
index 0000000..171d27b
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/java/http2demo/server/CustomerServiceImpl.java
@@ -0,0 +1,89 @@
+/**
+ * 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 http2demo.server;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.core.Response;
+
+import http2demo.common.Customer;
+import http2demo.common.CustomerService;
+
+public class CustomerServiceImpl implements CustomerService {
+    long currentId = 123;
+    Map<Long, Customer> customers = new HashMap<>();
+
+    public CustomerServiceImpl() {
+        init();
+    }
+
+    public Customer getCustomer(String id) {
+        System.out.println("----invoking getCustomer, Customer id is: " + id);
+        long idNumber = Long.parseLong(id);
+        return customers.get(idNumber);
+    }
+
+    public Response updateCustomer(Customer customer) {
+        System.out.println("----invoking updateCustomer, Customer name is: " + customer.getName());
+        Customer c = customers.get(customer.getId());
+        Response r;
+        if (c != null) {
+            customers.put(customer.getId(), customer);
+            r = Response.ok().build();
+        } else {
+            r = Response.notModified().build();
+        }
+
+        return r;
+    }
+
+    public Response addCustomer(Customer customer) {
+        System.out.println("----invoking addCustomer, Customer name is: " + customer.getName());
+        customer.setId(++currentId);
+
+        customers.put(customer.getId(), customer);
+
+        return Response.ok(customer).build();
+    }
+
+    public Response deleteCustomer(String id) {
+        System.out.println("----invoking deleteCustomer, Customer id is: " + id);
+        long idNumber = Long.parseLong(id);
+        Customer c = customers.get(idNumber);
+
+        Response r;
+        if (c != null) {
+            r = Response.ok().build();
+            customers.remove(idNumber);
+        } else {
+            r = Response.notModified().build();
+        }
+
+        return r;
+    }
+
+    final void init() {
+        Customer c = new Customer();
+        c.setName("John");
+        c.setId(123);
+        customers.put(c.getId(), c);
+    }
+
+}
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/java/http2demo/server/h2/Server.java b/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/java/http2demo/server/h2/Server.java
new file mode 100644
index 0000000..d821996
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/java/http2demo/server/h2/Server.java
@@ -0,0 +1,59 @@
+/**
+ * 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 http2demo.server.h2;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
+import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
+import org.apache.cxf.transport.http.HttpServerEngineSupport;
+
+import http2demo.server.CustomerServiceImpl;
+
+public class Server {
+
+    static {
+        // set the configuration file
+        SpringBusFactory factory = new SpringBusFactory();
+        Bus bus = factory.createBus("ServerConfig.xml");
+        bus.setProperty(HttpServerEngineSupport.ENABLE_HTTP2, true);
+        BusFactory.setDefaultBus(bus);
+    }
+
+    protected Server() throws Exception {
+        JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
+        sf.setResourceClasses(CustomerServiceImpl.class);
+        sf.setResourceProvider(CustomerServiceImpl.class,
+            new SingletonResourceProvider(new CustomerServiceImpl()));
+        sf.setAddress("https://localhost:9000/");
+
+        sf.create();
+    }
+
+    public static void main(String[] args) throws Exception {
+        new Server();
+        System.out.println("Server ready...");
+
+        Thread.sleep(5 * 60 * 1000);
+        System.out.println("Server exiting");
+        System.exit(0);
+    }
+}
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/java/http2demo/server/h2c/Server.java b/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/java/http2demo/server/h2c/Server.java
new file mode 100644
index 0000000..d86ef95
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/java/http2demo/server/h2c/Server.java
@@ -0,0 +1,59 @@
+/**
+ * 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 http2demo.server.h2c;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
+import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
+import org.apache.cxf.transport.http.HttpServerEngineSupport;
+
+import http2demo.server.CustomerServiceImpl;
+
+public class Server {
+
+    static {
+        // set the configuration file
+        SpringBusFactory factory = new SpringBusFactory();
+        Bus bus = factory.createBus();
+        bus.setProperty(HttpServerEngineSupport.ENABLE_HTTP2, true);
+        BusFactory.setDefaultBus(bus);
+    }
+
+    protected Server() throws Exception {
+        JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
+        sf.setResourceClasses(CustomerServiceImpl.class);
+        sf.setResourceProvider(CustomerServiceImpl.class,
+            new SingletonResourceProvider(new CustomerServiceImpl()));
+        sf.setAddress("http://localhost:9001/");
+
+        sf.create();
+    }
+
+    public static void main(String[] args) throws Exception {
+        new Server();
+        System.out.println("Server ready...");
+
+        Thread.sleep(5 * 60 * 1000);
+        System.out.println("Server exiting");
+        System.exit(0);
+    }
+}
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/resources/ServerConfig.xml b/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/resources/ServerConfig.xml
new file mode 100644
index 0000000..8506180
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_netty/src/main/resources/ServerConfig.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<!-- 
+  ** This file configures the Server which exposes the REST endpoint.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:sec="http://cxf.apache.org/configuration/security"
+    xmlns:http="http://cxf.apache.org/transports/http/configuration"
+    xmlns:httpj="http://cxf.apache.org/transports/http-netty-server/configuration"
+    xsi:schemaLocation="http://cxf.apache.org/configuration/security 
+        http://cxf.apache.org/schemas/configuration/security.xsd 
+        http://cxf.apache.org/transports/http/configuration 
+        http://cxf.apache.org/schemas/configuration/http-conf.xsd 
+        http://cxf.apache.org/transports/http-netty-server/configuration 
+        http://cxf.apache.org/schemas/configuration/http-netty-server.xsd 
+        http://www.springframework.org/schema/beans 
+        http://www.springframework.org/schema/beans/spring-beans.xsd">
+    <httpj:engine-factory bus="cxf">
+        <httpj:engine port="9000">
+            <httpj:tlsServerParameters>
+                <sec:keyManagers keyPassword="skpass">
+                    <sec:keyStore file="src/main/config/serviceKeystore.jks" password="sspass" type="JKS"/>
+                </sec:keyManagers>
+                <sec:trustManagers>
+                    <sec:keyStore file="src/main/config/serviceKeystore.jks" password="sspass" type="JKS"/>
+                </sec:trustManagers>
+            </httpj:tlsServerParameters>
+        </httpj:engine>
+    </httpj:engine-factory>
+</beans>
\ No newline at end of file
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/README.txt b/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/README.txt
new file mode 100644
index 0000000..bb2cb62
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/README.txt
@@ -0,0 +1,93 @@
+JAX-RS Basic Demo With HTTPS communications
+===========================================
+
+This demo takes the JAX-RS basic demo a step further 
+by doing the communication using HTTP/2 over TLS and
+HTTP/2 over cleartext using Undertow container.
+
+Building and running the demo using Maven
+-----------------------------------------
+From the base directory of this sample (i.e., where this README file is
+located), the Maven pom.xml file can be used to build and run the demo. 
+
+Using either UNIX or Windows:
+
+  mvn install
+  mvn -Ph2-server  (HTTP/2 over TLS)
+  mvn -Ph2c-server  (HTTP/2 over cleartext)
+    
+To remove the target dir, run "mvn clean".
+
+Certificates
+------------
+See the src/main/config folder for the sample keys used (don't use
+these keys in production!) as well as scripts used for their creation.
+
+HTTP/2 over cleartext
+------------
+
+- Upgrade from HTTP/1.1 to HTTP/2 (cleartext)
+
+    $ curl http://localhost:9001/customerservice/customers/123 --http2 -i
+  
+    HTTP/1.1 101 Switching Protocols
+    Connection: Upgrade
+    Upgrade: h2c
+    Date: Thu, 14 Oct 2021 00:51:50 GMT
+  
+    HTTP/2 200
+    content-type: application/xml
+    content-length: 105
+    date: Thu, 14 Oct 2021 00:51:50 GMT
+
+    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Customer><id>123</id><name>John</name></Customer>
+
+- Use HTTP/2 prior knowledge (cleartext)
+
+    $ curl http://localhost:9001/customerservice/customers/123 --http2-prior-knowledge -i
+  
+    HTTP/2 200
+    content-type: application/xml
+    content-length: 105
+    date: Thu, 14 Oct 2021 00:55:35 GMT
+
+    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Customer><id>123</id><name>John</name></Customer>
+  
+- Force HTTP/1.1 usage (cleartext)
+
+    $ curl http://localhost:9001/customerservice/customers/123 --http1.1 -i
+  
+    HTTP/1.1 200 OK
+    Connection: keep-alive
+    Content-Type: application/xml
+    Content-Length: 105
+    Date: Thu, 14 Oct 2021 00:50:50 GMT
+  
+    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Customer><id>123</id><name>John</name></Customer>
+    
+HTTP/2 over TLS
+------------
+
+- Use HTTP/2
+
+    $ curl https://localhost:9000/customerservice/customers/123 --http2 -ik
+  
+    HTTP/2 200
+    content-type: application/xml
+    content-length: 105
+    date: Thu, 14 Oct 2021 01:04:34 GMT
+
+    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Customer><id>123</id><name>John</name></Customer>
+  
+- Force HTTP/1.1 usage
+
+    $ curl https://localhost:9000/customerservice/customers/123 --http1.1 -ik
+  
+    HTTP/1.1 200 OK
+    Connection: keep-alive
+    Content-Type: application/xml
+    Content-Length: 105
+    Date: Thu, 14 Oct 2021 01:06:34 GMT
+  
+    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Customer><id>123</id><name>John</name></Customer>
+
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/pom.xml b/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/pom.xml
new file mode 100644
index 0000000..41304e2
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/pom.xml
@@ -0,0 +1,95 @@
+<?xml version="1.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.
+-->
+<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>
+    <artifactId>jax_rs_basic_http2_undertow</artifactId>
+    <name>JAX-RS Basic Demo With HTTP/2 communications</name>
+    <description>JAX-RS Basic Demo With HTTP/2 communications</description>
+    <parent>
+        <groupId>org.apache.cxf.samples</groupId>
+        <artifactId>cxf-samples</artifactId>
+        <version>3.4.6-SNAPSHOT</version>
+        <relativePath>../..</relativePath>
+    </parent>
+    <profiles>
+        <profile>
+            <id>h2-server</id>
+            <build>
+                <defaultGoal>test</defaultGoal>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>test</phase>
+                                <goals>
+                                    <goal>java</goal>
+                                </goals>
+                                <configuration>
+                                    <mainClass>http2demo.server.h2.Server</mainClass>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>h2c-server</id>
+            <build>
+                <defaultGoal>test</defaultGoal>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>test</phase>
+                                <goals>
+                                    <goal>java</goal>
+                                </goals>
+                                <configuration>
+                                    <mainClass>http2demo.server.h2c.Server</mainClass>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-transports-http-undertow</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/config/KeyREADME.txt b/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/config/KeyREADME.txt
new file mode 100644
index 0000000..97f20fa
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/config/KeyREADME.txt
@@ -0,0 +1,8 @@
+# The below scripts show the commands used to generate the self-signed keys for this sample.
+# If you use the below script to create your own keys be sure to change the passwords used here
+# DO NOT USE THE SUPPLIED KEYS IN PRODUCTION--everyone has them!!
+# For production recommended to use keys signed by a third-party certificate authority (CA)
+
+# Create the combination keystore/truststore for the server.
+keytool -genkeypair -keyalg RSA -keysize 4096 -validity 730 -alias myservicekey -keystore serviceKeystore.jks -dname "cn=localhost" -keypass skpass -storepass sspass
+
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/config/serviceKeystore.jks b/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/config/serviceKeystore.jks
new file mode 100644
index 0000000..8d40c61
Binary files /dev/null and b/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/config/serviceKeystore.jks differ
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/java/http2demo/common/Customer.java b/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/java/http2demo/common/Customer.java
new file mode 100644
index 0000000..81ce3c5
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/java/http2demo/common/Customer.java
@@ -0,0 +1,43 @@
+/**
+ * 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 http2demo.common;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "Customer")
+public class Customer {
+    private long id;
+    private String name;
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/java/http2demo/common/CustomerService.java b/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/java/http2demo/common/CustomerService.java
new file mode 100644
index 0000000..890ade3
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/java/http2demo/common/CustomerService.java
@@ -0,0 +1,52 @@
+/**
+ * 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 http2demo.common;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Response;
+
+/**
+ * This interface describes a JAX-RS root resource. All the JAXRS annotations (except those overridden) will
+ * be inherited by classes implementing it.
+ */
+@Path("/customerservice/")
+public interface CustomerService {
+
+    @GET
+    @Path("/customers/{id}/")
+    Customer getCustomer(@PathParam("id") String id);
+
+    @PUT
+    @Path("/customers/")
+    Response updateCustomer(Customer customer);
+
+    @POST
+    @Path("/customers/")
+    Response addCustomer(Customer customer);
+
+    @DELETE
+    @Path("/customers/{id}/")
+    Response deleteCustomer(@PathParam("id") String id);
+
+}
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/java/http2demo/server/CustomerServiceImpl.java b/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/java/http2demo/server/CustomerServiceImpl.java
new file mode 100644
index 0000000..171d27b
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/java/http2demo/server/CustomerServiceImpl.java
@@ -0,0 +1,89 @@
+/**
+ * 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 http2demo.server;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.core.Response;
+
+import http2demo.common.Customer;
+import http2demo.common.CustomerService;
+
+public class CustomerServiceImpl implements CustomerService {
+    long currentId = 123;
+    Map<Long, Customer> customers = new HashMap<>();
+
+    public CustomerServiceImpl() {
+        init();
+    }
+
+    public Customer getCustomer(String id) {
+        System.out.println("----invoking getCustomer, Customer id is: " + id);
+        long idNumber = Long.parseLong(id);
+        return customers.get(idNumber);
+    }
+
+    public Response updateCustomer(Customer customer) {
+        System.out.println("----invoking updateCustomer, Customer name is: " + customer.getName());
+        Customer c = customers.get(customer.getId());
+        Response r;
+        if (c != null) {
+            customers.put(customer.getId(), customer);
+            r = Response.ok().build();
+        } else {
+            r = Response.notModified().build();
+        }
+
+        return r;
+    }
+
+    public Response addCustomer(Customer customer) {
+        System.out.println("----invoking addCustomer, Customer name is: " + customer.getName());
+        customer.setId(++currentId);
+
+        customers.put(customer.getId(), customer);
+
+        return Response.ok(customer).build();
+    }
+
+    public Response deleteCustomer(String id) {
+        System.out.println("----invoking deleteCustomer, Customer id is: " + id);
+        long idNumber = Long.parseLong(id);
+        Customer c = customers.get(idNumber);
+
+        Response r;
+        if (c != null) {
+            r = Response.ok().build();
+            customers.remove(idNumber);
+        } else {
+            r = Response.notModified().build();
+        }
+
+        return r;
+    }
+
+    final void init() {
+        Customer c = new Customer();
+        c.setName("John");
+        c.setId(123);
+        customers.put(c.getId(), c);
+    }
+
+}
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/java/http2demo/server/h2/Server.java b/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/java/http2demo/server/h2/Server.java
new file mode 100644
index 0000000..d821996
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/java/http2demo/server/h2/Server.java
@@ -0,0 +1,59 @@
+/**
+ * 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 http2demo.server.h2;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
+import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
+import org.apache.cxf.transport.http.HttpServerEngineSupport;
+
+import http2demo.server.CustomerServiceImpl;
+
+public class Server {
+
+    static {
+        // set the configuration file
+        SpringBusFactory factory = new SpringBusFactory();
+        Bus bus = factory.createBus("ServerConfig.xml");
+        bus.setProperty(HttpServerEngineSupport.ENABLE_HTTP2, true);
+        BusFactory.setDefaultBus(bus);
+    }
+
+    protected Server() throws Exception {
+        JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
+        sf.setResourceClasses(CustomerServiceImpl.class);
+        sf.setResourceProvider(CustomerServiceImpl.class,
+            new SingletonResourceProvider(new CustomerServiceImpl()));
+        sf.setAddress("https://localhost:9000/");
+
+        sf.create();
+    }
+
+    public static void main(String[] args) throws Exception {
+        new Server();
+        System.out.println("Server ready...");
+
+        Thread.sleep(5 * 60 * 1000);
+        System.out.println("Server exiting");
+        System.exit(0);
+    }
+}
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/java/http2demo/server/h2c/Server.java b/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/java/http2demo/server/h2c/Server.java
new file mode 100644
index 0000000..d86ef95
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/java/http2demo/server/h2c/Server.java
@@ -0,0 +1,59 @@
+/**
+ * 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 http2demo.server.h2c;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
+import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
+import org.apache.cxf.transport.http.HttpServerEngineSupport;
+
+import http2demo.server.CustomerServiceImpl;
+
+public class Server {
+
+    static {
+        // set the configuration file
+        SpringBusFactory factory = new SpringBusFactory();
+        Bus bus = factory.createBus();
+        bus.setProperty(HttpServerEngineSupport.ENABLE_HTTP2, true);
+        BusFactory.setDefaultBus(bus);
+    }
+
+    protected Server() throws Exception {
+        JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
+        sf.setResourceClasses(CustomerServiceImpl.class);
+        sf.setResourceProvider(CustomerServiceImpl.class,
+            new SingletonResourceProvider(new CustomerServiceImpl()));
+        sf.setAddress("http://localhost:9001/");
+
+        sf.create();
+    }
+
+    public static void main(String[] args) throws Exception {
+        new Server();
+        System.out.println("Server ready...");
+
+        Thread.sleep(5 * 60 * 1000);
+        System.out.println("Server exiting");
+        System.exit(0);
+    }
+}
diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/resources/ServerConfig.xml b/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/resources/ServerConfig.xml
new file mode 100644
index 0000000..fff566f
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_undertow/src/main/resources/ServerConfig.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<!-- 
+  ** This file configures the Server which exposes the REST endpoint.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:sec="http://cxf.apache.org/configuration/security"
+    xmlns:http="http://cxf.apache.org/transports/http/configuration"
+    xmlns:httpj="http://cxf.apache.org/transports/http-undertow/configuration"
+    xsi:schemaLocation="http://cxf.apache.org/configuration/security 
+        http://cxf.apache.org/schemas/configuration/security.xsd 
+        http://cxf.apache.org/transports/http/configuration 
+        http://cxf.apache.org/schemas/configuration/http-conf.xsd 
+        http://cxf.apache.org/transports/http-undertow/configuration 
+        http://cxf.apache.org/schemas/configuration/http-undertow.xsd 
+        http://www.springframework.org/schema/beans 
+        http://www.springframework.org/schema/beans/spring-beans.xsd">
+    <httpj:engine-factory bus="cxf">
+        <httpj:engine port="9000">
+            <httpj:tlsServerParameters>
+                <sec:keyManagers keyPassword="skpass">
+                    <sec:keyStore file="src/main/config/serviceKeystore.jks" password="sspass" type="JKS"/>
+                </sec:keyManagers>
+                <sec:trustManagers>
+                    <sec:keyStore file="src/main/config/serviceKeystore.jks" password="sspass" type="JKS"/>
+                </sec:trustManagers>
+            </httpj:tlsServerParameters>
+        </httpj:engine>
+    </httpj:engine-factory>
+</beans>
\ No newline at end of file
diff --git a/distribution/src/main/release/samples/pom.xml b/distribution/src/main/release/samples/pom.xml
index 21438ec..8bd17e1 100644
--- a/distribution/src/main/release/samples/pom.xml
+++ b/distribution/src/main/release/samples/pom.xml
@@ -32,7 +32,8 @@
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <spring.boot.version>2.3.9.RELEASE</spring.boot.version>
         <spring.cloud.eureka.version>2.2.3.RELEASE</spring.cloud.eureka.version>
-        <cxf.jetty9.version>9.4.43.v20210629</cxf.jetty9.version>
+        <cxf.jetty9.version>9.4.44.v20210927</cxf.jetty9.version>
+        <cxf.netty.version>4.1.69.Final</cxf.netty.version>
         <cxf.httpcomponents.client.version>4.5.13</cxf.httpcomponents.client.version>
         <cxf.swagger.ui.version>3.52.1</cxf.swagger.ui.version>
         <cxf.tika.version>1.27</cxf.tika.version>
@@ -151,6 +152,9 @@
         <module>jaxws_graalvm_dynamic/client</module>
         <module>jaxws_graalvm_dynamic/server</module>
         <module>jax_rs/graalvm_basic</module>
+        <module>jax_rs/basic_http2_undertow</module>
+        <module>jax_rs/basic_http2_netty</module>
+        <module>jax_rs/basic_http2_jetty</module>
     </modules>
     <dependencyManagement>
         <dependencies>
diff --git a/parent/pom.xml b/parent/pom.xml
index 65b11d9..929a94e 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -1169,6 +1169,16 @@
                 <version>${cxf.jetty.version}</version>
             </dependency>
             <dependency>
+                <groupId>org.eclipse.jetty.http2</groupId>
+                <artifactId>http2-server</artifactId>
+                <version>${cxf.jetty.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.eclipse.jetty</groupId>
+                <artifactId>jetty-alpn-server</artifactId>
+                <version>${cxf.jetty.version}</version>
+            </dependency>
+            <dependency>
                  <groupId>io.undertow</groupId>
                  <artifactId>undertow-core</artifactId>
                  <version>${cxf.undertow.version}</version>
diff --git a/rt/transports/http-jetty/pom.xml b/rt/transports/http-jetty/pom.xml
index e04be7c..d819e97 100644
--- a/rt/transports/http-jetty/pom.xml
+++ b/rt/transports/http-jetty/pom.xml
@@ -128,6 +128,16 @@
             <artifactId>jetty-http</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.eclipse.jetty.http2</groupId>
+            <artifactId>http2-server</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-alpn-server</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
             <scope>runtime</scope>
diff --git a/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPServerEngine.java b/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPServerEngine.java
index 2636913..1366b44 100644
--- a/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPServerEngine.java
+++ b/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPServerEngine.java
@@ -54,7 +54,11 @@ import org.apache.cxf.configuration.security.ClientAuthentication;
 import org.apache.cxf.helpers.JavaUtils;
 import org.apache.cxf.interceptor.Fault;
 import org.apache.cxf.transport.HttpUriMapper;
+import org.apache.cxf.transport.http.HttpServerEngineSupport;
+import org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory;
 import org.eclipse.jetty.http.HttpStatus;
+import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory;
+import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
 import org.eclipse.jetty.security.SecurityHandler;
 import org.eclipse.jetty.server.AbstractConnector;
 import org.eclipse.jetty.server.ConnectionFactory;
@@ -84,7 +88,7 @@ import org.eclipse.jetty.util.thread.ThreadPool;
  * work off of a designated port. The port will be enabled for
  * "http" or "https" depending upon its successful configuration.
  */
-public class JettyHTTPServerEngine implements ServerEngine {
+public class JettyHTTPServerEngine implements ServerEngine, HttpServerEngineSupport {
     public static final String DO_NOT_CHECK_URL_PROP = "org.apache.cxf.transports.http_jetty.DontCheckUrl";
 
     private static final Logger LOG = LogUtils.getL7dLogger(JettyHTTPServerEngine.class);
@@ -145,15 +149,12 @@ public class JettyHTTPServerEngine implements ServerEngine {
     /**
      * This constructor is called by the JettyHTTPServerEngineFactory.
      */
-    public JettyHTTPServerEngine(
-        Container.Listener mBeanContainer,
-        String host,
-        int port) {
+    public JettyHTTPServerEngine(Container.Listener mBeanContainer, String host, int port) {
         this.host = host;
         this.port = port;
         this.mBeanContainer = mBeanContainer;
     }
-
+    
     public JettyHTTPServerEngine() {
 
     }
@@ -398,7 +399,7 @@ public class JettyHTTPServerEngine implements ServerEngine {
             addServerMBean();
 
             if (connector == null) {
-                connector = createConnector(getHost(), getPort());
+                connector = createConnector(getHost(), getPort(), handler.getBus());
                 if (LOG.isLoggable(Level.FINER)) {
                     logConnector((ServerConnector)connector);
                 }
@@ -621,7 +622,7 @@ public class JettyHTTPServerEngine implements ServerEngine {
     }
 
     
-    private Connector createConnector(String hosto, int porto) {
+    private Connector createConnector(String hosto, int porto, final Bus bus) {
         // now we just use the SelectChannelConnector as the default connector
         SslContextFactory sslcf = null;
         if (tlsServerParameters != null) {
@@ -649,8 +650,7 @@ public class JettyHTTPServerEngine implements ServerEngine {
             // unparsable version
         }
 
-        result = (ServerConnector)createConnectorJetty(sslcf, hosto, porto, major, minor);
-
+        result = (ServerConnector)createConnectorJetty(sslcf, hosto, porto, major, minor, bus);
 
         try {
             result.setPort(porto);
@@ -667,7 +667,8 @@ public class JettyHTTPServerEngine implements ServerEngine {
         return result;
     }
 
-    AbstractConnector createConnectorJetty(SslContextFactory sslcf, String hosto, int porto, int major, int minor) {
+    AbstractConnector createConnectorJetty(SslContextFactory sslcf, String hosto, int porto, 
+            int major, int minor, final Bus bus) {
         AbstractConnector result = null;
         try {
             HttpConfiguration httpConfig = new HttpConfiguration();
@@ -680,10 +681,26 @@ public class JettyHTTPServerEngine implements ServerEngine {
 
             if (tlsServerParameters != null) {
                 httpConfig.addCustomizer(new org.eclipse.jetty.server.SecureRequestCustomizer());
-                SslConnectionFactory scf = new SslConnectionFactory(sslcf, "HTTP/1.1");
-                connectionFactories.add(scf);
+
+                if (!isHttp2Enabled(bus)) {
+                    final SslConnectionFactory scf = new SslConnectionFactory(sslcf, httpFactory.getProtocol());
+                    connectionFactories.add(scf);
+                } else {
+                    // The ALPN processors are application specific (as per Jetty docs) and are pluggable as
+                    // additional dependency.
+                    final ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory();
+                    alpn.setDefaultProtocol(httpFactory.getProtocol());
+                    
+                    final SslConnectionFactory scf = new SslConnectionFactory(sslcf, alpn.getProtocol());
+                    connectionFactories.add(scf);
+                    connectionFactories.add(alpn);
+                    connectionFactories.add(new HTTP2ServerConnectionFactory(httpConfig));
+                }
+
                 String proto = (major > 9 || (major == 9 && minor >= 3)) ? "SSL" : "SSL-HTTP/1.1";
                 result.setDefaultProtocol(proto);
+            } else if (isHttp2Enabled(bus)) {
+                connectionFactories.add(new HTTP2CServerConnectionFactory(httpConfig));
             }
             connectionFactories.add(httpFactory);
             result.setConnectionFactories(connectionFactories);
diff --git a/rt/transports/http-netty/netty-server/pom.xml b/rt/transports/http-netty/netty-server/pom.xml
index 36595b1..9169808 100644
--- a/rt/transports/http-netty/netty-server/pom.xml
+++ b/rt/transports/http-netty/netty-server/pom.xml
@@ -62,6 +62,12 @@
             <version>${cxf.netty.version}</version>
         </dependency>
         <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-codec-http2</artifactId>
+            <version>${cxf.netty.version}</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
             <!-- we don't implement the servlet 3.0 specification here -->
             <groupId>org.apache.geronimo.specs</groupId>
             <artifactId>geronimo-servlet_2.5_spec</artifactId>
diff --git a/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/NettyHttpServerEngine.java b/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/NettyHttpServerEngine.java
index 182d997..c198fb2 100644
--- a/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/NettyHttpServerEngine.java
+++ b/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/NettyHttpServerEngine.java
@@ -29,11 +29,13 @@ import java.util.logging.Logger;
 
 import javax.annotation.PostConstruct;
 
+import org.apache.cxf.Bus;
 import org.apache.cxf.common.i18n.Message;
 import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.configuration.jsse.TLSServerParameters;
 import org.apache.cxf.interceptor.Fault;
 import org.apache.cxf.transport.HttpUriMapper;
+import org.apache.cxf.transport.http.HttpServerEngineSupport;
 
 import io.netty.bootstrap.ServerBootstrap;
 import io.netty.channel.Channel;
@@ -44,7 +46,7 @@ import io.netty.channel.socket.nio.NioServerSocketChannel;
 import io.netty.util.concurrent.DefaultEventExecutorGroup;
 import io.netty.util.concurrent.EventExecutorGroup;
 
-public class NettyHttpServerEngine implements ServerEngine {
+public class NettyHttpServerEngine implements ServerEngine, HttpServerEngineSupport {
 
     private static final Logger LOG =
             LogUtils.getL7dLogger(NettyHttpServerEngine.class);
@@ -95,22 +97,37 @@ public class NettyHttpServerEngine implements ServerEngine {
     private EventLoopGroup bossGroup;
     private EventLoopGroup workerGroup;
     private EventExecutorGroup applicationExecutor;
+    
+    private Bus bus;
 
+    
     public NettyHttpServerEngine() {
 
     }
 
-    public NettyHttpServerEngine(
-            String host,
-            int port) {
+    @Deprecated
+    public NettyHttpServerEngine(String host, int port) {
+        this(host, port, null);
+    }
+
+    public NettyHttpServerEngine(String host, int port, Bus bus) {
         this.host = host;
         this.port = port;
+        this.bus = bus;
     }
 
     @PostConstruct
     public void finalizeConfig() {
         // need to check if we need to any other thing other than Setting the TLSServerParameter
     }
+    
+    public void setBus(Bus bus) {
+        this.bus = bus;
+    }
+    
+    public Bus getBus() {
+        return bus;
+    }
 
     /**
      * This method is used to programmatically set the TLSServerParameters.
@@ -163,7 +180,7 @@ public class NettyHttpServerEngine implements ServerEngine {
             new NettyHttpServletPipelineFactory(
                  tlsServerParameters, sessionSupport,
                  maxChunkContentSize, handlerMap,
-                 this, applicationExecutor);
+                 this, applicationExecutor, isHttp2Enabled(bus));
         // Start the servletPipeline's timer
         servletPipeline.start();
         bootstrap.childHandler(servletPipeline);
diff --git a/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/NettyHttpServerEngineFactory.java b/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/NettyHttpServerEngineFactory.java
index 93bb2ca..7c3712f 100644
--- a/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/NettyHttpServerEngineFactory.java
+++ b/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/NettyHttpServerEngineFactory.java
@@ -151,7 +151,7 @@ public class NettyHttpServerEngineFactory implements BusLifeCycleListener {
 
         NettyHttpServerEngine ref = portMap.get(port);
         if (ref == null) {
-            ref = new NettyHttpServerEngine(host, port);
+            ref = new NettyHttpServerEngine(host, port, factory.getBus());
             if (tlsParams != null) {
                 ref.setTlsServerParameters(tlsParams);
             }
diff --git a/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/NettyHttpServletPipelineFactory.java b/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/NettyHttpServletPipelineFactory.java
index f92a16e..cdc9350 100644
--- a/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/NettyHttpServletPipelineFactory.java
+++ b/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/NettyHttpServletPipelineFactory.java
@@ -19,31 +19,64 @@
 
 package org.apache.cxf.transport.http.netty.server;
 
+import java.util.Arrays;
 import java.util.Map;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLEngine;
+import javax.net.ssl.TrustManager;
 
 import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.configuration.jsse.TLSServerParameters;
+import org.apache.cxf.configuration.security.ClientAuthentication;
 import org.apache.cxf.transport.http.netty.server.interceptor.ChannelInterceptor;
 import org.apache.cxf.transport.http.netty.server.interceptor.HttpSessionInterceptor;
 import org.apache.cxf.transport.http.netty.server.session.DefaultHttpSessionStore;
 import org.apache.cxf.transport.http.netty.server.session.HttpSessionStore;
+import org.apache.cxf.transport.https.SSLContextInitParameters;
 import org.apache.cxf.transport.https.SSLUtils;
 
 import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelInitializer;
 import io.netty.channel.ChannelPipeline;
+import io.netty.channel.SimpleChannelInboundHandler;
 import io.netty.channel.group.ChannelGroup;
 import io.netty.channel.group.DefaultChannelGroup;
 import io.netty.handler.codec.http.HttpContentCompressor;
+import io.netty.handler.codec.http.HttpMessage;
 import io.netty.handler.codec.http.HttpObjectAggregator;
 import io.netty.handler.codec.http.HttpRequestDecoder;
 import io.netty.handler.codec.http.HttpResponseEncoder;
+import io.netty.handler.codec.http.HttpServerCodec;
+import io.netty.handler.codec.http.HttpServerUpgradeHandler;
+import io.netty.handler.codec.http.HttpServerUpgradeHandler.UpgradeCodec;
+import io.netty.handler.codec.http.HttpServerUpgradeHandler.UpgradeCodecFactory;
+import io.netty.handler.codec.http2.CleartextHttp2ServerUpgradeHandler;
+import io.netty.handler.codec.http2.Http2CodecUtil;
+import io.netty.handler.codec.http2.Http2FrameCodecBuilder;
+import io.netty.handler.codec.http2.Http2MultiplexHandler;
+import io.netty.handler.codec.http2.Http2SecurityUtil;
+import io.netty.handler.codec.http2.Http2ServerUpgradeCodec;
+import io.netty.handler.codec.http2.Http2StreamFrameToHttpObjectCodec;
+import io.netty.handler.ssl.ApplicationProtocolConfig;
+import io.netty.handler.ssl.ApplicationProtocolConfig.Protocol;
+import io.netty.handler.ssl.ApplicationProtocolConfig.SelectedListenerFailureBehavior;
+import io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBehavior;
+import io.netty.handler.ssl.ApplicationProtocolNames;
+import io.netty.handler.ssl.ApplicationProtocolNegotiationHandler;
+import io.netty.handler.ssl.ClientAuth;
+import io.netty.handler.ssl.SslContext;
+import io.netty.handler.ssl.SslContextBuilder;
 import io.netty.handler.ssl.SslHandler;
+import io.netty.handler.ssl.SslProvider;
+import io.netty.handler.ssl.SupportedCipherSuiteFilter;
 import io.netty.handler.timeout.IdleStateHandler;
+import io.netty.util.AsciiString;
+import io.netty.util.ReferenceCountUtil;
 import io.netty.util.concurrent.DefaultEventExecutorGroup;
 import io.netty.util.concurrent.EventExecutorGroup;
 import io.netty.util.concurrent.ImmediateEventExecutor;
@@ -68,6 +101,8 @@ public class NettyHttpServletPipelineFactory extends ChannelInitializer<Channel>
     private final EventExecutorGroup applicationExecutor;
 
     private final NettyHttpServerEngine nettyHttpServerEngine;
+    
+    private final boolean enableHttp2; /* enable HTTP2 support */
 
     /**
      * @deprecated use {@link #NettyHttpServletPipelineFactory(TLSServerParameters, boolean, int, Map,
@@ -83,9 +118,18 @@ public class NettyHttpServletPipelineFactory extends ChannelInitializer<Channel>
     }
 
     public NettyHttpServletPipelineFactory(TLSServerParameters tlsServerParameters,
+            boolean supportSession, int maxChunkContentSize,
+            Map<String, NettyHttpContextHandler> handlerMap,
+            NettyHttpServerEngine engine, EventExecutorGroup applicationExecutor) {
+        this(tlsServerParameters, supportSession, maxChunkContentSize, handlerMap, engine,
+            applicationExecutor, false);
+    }
+
+    public NettyHttpServletPipelineFactory(TLSServerParameters tlsServerParameters,
                                            boolean supportSession, int maxChunkContentSize,
                                            Map<String, NettyHttpContextHandler> handlerMap,
-                                           NettyHttpServerEngine engine, EventExecutorGroup applicationExecutor) {
+                                           NettyHttpServerEngine engine, EventExecutorGroup applicationExecutor,
+                                           boolean enableHttp2) {
         this.supportSession = supportSession;
         this.watchdog = new HttpSessionWatchdog();
         this.handlerMap = handlerMap;
@@ -93,6 +137,7 @@ public class NettyHttpServletPipelineFactory extends ChannelInitializer<Channel>
         this.maxChunkContentSize = maxChunkContentSize;
         this.nettyHttpServerEngine = engine;
         this.applicationExecutor = applicationExecutor;
+        this.enableHttp2 = enableHttp2;
     }
 
     public Map<String, NettyHttpContextHandler> getHttpContextHandlerMap() {
@@ -139,12 +184,12 @@ public class NettyHttpServletPipelineFactory extends ChannelInitializer<Channel>
         return handler;
     }
 
-    protected ChannelPipeline getDefaulHttpChannelPipeline(Channel channel) throws Exception {
+    protected ChannelPipeline getDefaultHttpChannelPipeline(Channel channel) throws Exception {
 
         // Create a default pipeline implementation.
         ChannelPipeline pipeline = channel.pipeline();
 
-        SslHandler sslHandler = configureServerSSLOnDemand();
+        SslHandler sslHandler = configureServerHttpSSLOnDemand();
         if (sslHandler != null) {
             LOG.log(Level.FINE,
                     "Server SSL handler configured and added as an interceptor against the ChannelPipeline: {}",
@@ -152,6 +197,18 @@ public class NettyHttpServletPipelineFactory extends ChannelInitializer<Channel>
             pipeline.addLast("ssl", sslHandler);
         }
 
+        configureDefaultHttpPipeline(pipeline);
+
+        return pipeline;
+    }
+    
+    protected void configureDefaultHttp2Pipeline(ChannelPipeline pipeline) {
+        pipeline
+            .addLast(Http2FrameCodecBuilder.forServer().build())
+            .addLast(new Http2MultiplexHandler(createHttp2ChannelInitializer()));
+    }
+
+    protected void configureDefaultHttpPipeline(ChannelPipeline pipeline) {
         pipeline.addLast("decoder", new HttpRequestDecoder());
         pipeline.addLast("encoder", new HttpResponseEncoder());
         pipeline.addLast("aggregator", new HttpObjectAggregator(maxChunkContentSize));
@@ -159,20 +216,74 @@ public class NettyHttpServletPipelineFactory extends ChannelInitializer<Channel>
         // Remove the following line if you don't want automatic content
         // compression.
         pipeline.addLast("deflater", new HttpContentCompressor());
+        
         // Set up the idle handler
         pipeline.addLast("idle", new IdleStateHandler(nettyHttpServerEngine.getReadIdleTime(),
                 nettyHttpServerEngine.getWriteIdleTime(), 0));
-
-        return pipeline;
     }
 
-    private SslHandler configureServerSSLOnDemand() throws Exception {
+    private SslHandler configureServerHttpSSLOnDemand() throws Exception {
         if (tlsServerParameters != null) {
             SSLEngine sslEngine = SSLUtils.createServerSSLEngine(tlsServerParameters);
             return new SslHandler(sslEngine);
         }
         return null;
     }
+    
+    private SslContext configureServerHttp2SSLOnDemand() throws Exception {
+        if (tlsServerParameters != null) {
+            final SSLContextInitParameters initParams = SSLUtils.getSSLContextInitParameters(tlsServerParameters);
+            // Use only JDK provider for now, leaving OpenSsl as an option
+            final SslProvider provider = SslProvider.JDK;
+    
+            final KeyManager[] keyManagers = initParams.getKeyManagers();
+            if (keyManagers == null || keyManagers.length == 0) {
+                throw new IllegalStateException("No KeyManagers are configured, unable "
+                        + "to create Netty's SslContext instance");
+            }
+            
+            final String[] cipherSuites = org.apache.cxf.configuration.jsse.SSLUtils
+                .getCiphersuitesToInclude(
+                        tlsServerParameters.getCipherSuites(), 
+                        tlsServerParameters.getCipherSuitesFilter(),
+                        SSLContext.getDefault().getDefaultSSLParameters().getCipherSuites(),
+                        Http2SecurityUtil.CIPHERS.toArray(new String[] {}),
+                        LOG);
+            
+            final SslContextBuilder builder = SslContextBuilder
+                .forServer(keyManagers[0]) /* only first is used, as with SSLContext::init*/
+                .sslProvider(provider)
+                .ciphers(Arrays.asList(cipherSuites), SupportedCipherSuiteFilter.INSTANCE)
+                .applicationProtocolConfig(
+                    new ApplicationProtocolConfig(
+                        Protocol.ALPN,
+                        // NO_ADVERTISE is currently the only mode supported by both OpenSsl and JDK providers.
+                        SelectorFailureBehavior.NO_ADVERTISE,
+                        // ACCEPT is currently the only mode supported by both OpenSsl and JDK providers.
+                        SelectedListenerFailureBehavior.ACCEPT,
+                        ApplicationProtocolNames.HTTP_2,
+                        ApplicationProtocolNames.HTTP_1_1
+                    ));
+            
+            final TrustManager[] trustManagers = initParams.getTrustManagers();
+            if (trustManagers != null && trustManagers.length > 0) {
+                builder.trustManager(trustManagers[0]);
+            }
+            
+            final ClientAuthentication clientAuth = tlsServerParameters.getClientAuthentication();
+            if (clientAuth != null) {
+                if (clientAuth.isSetRequired() && clientAuth.isRequired()) {
+                    builder.clientAuth(ClientAuth.REQUIRE);
+                } else if (clientAuth.isSetWant() && clientAuth.isWant()) {
+                    builder.clientAuth(ClientAuth.OPTIONAL);
+                }
+            }
+            
+            return builder.build();
+        }
+        
+        return null;
+    }
 
     private class HttpSessionWatchdog implements Runnable {
 
@@ -203,12 +314,115 @@ public class NettyHttpServletPipelineFactory extends ChannelInitializer<Channel>
         }
 
     }
+    
+    /**
+     * Application negotiation handler to select either HTTP 1.1 or HTTP 2 protocol, based
+     * on client/server ALPN negotiations.
+     */
+    private class Http2OrHttpHandler extends ApplicationProtocolNegotiationHandler {
+        protected Http2OrHttpHandler() {
+            super(ApplicationProtocolNames.HTTP_1_1);
+        }
+
+        @Override
+        protected void configurePipeline(ChannelHandlerContext ctx, String protocol) throws Exception {
+            if (ApplicationProtocolNames.HTTP_2.equals(protocol)) {
+                configureDefaultHttp2Pipeline(ctx.pipeline());
+            } else if (ApplicationProtocolNames.HTTP_1_1.equals(protocol)) {
+                configureDefaultHttpPipeline(ctx.pipeline());
+                ctx.pipeline().addLast(applicationExecutor, "handler", getServletHandler());
+            } else {
+                throw new IllegalStateException("Unknown application protocol: " + protocol);
+            }
+        }
+    }
 
     @Override
     protected void initChannel(Channel ch) throws Exception {
-        ChannelPipeline pipeline = getDefaulHttpChannelPipeline(ch);
+        if (!enableHttp2) {
+            final ChannelPipeline pipeline = getDefaultHttpChannelPipeline(ch);
+            pipeline.addLast(applicationExecutor, "handler", this.getServletHandler());
+        } else {
+            getDefaultHttp2ChannelPipeline(ch);
+        }
+    }
+    
+    protected ChannelPipeline getDefaultHttp2ChannelPipeline(Channel channel) throws Exception {
+        // Create a default pipeline implementation with HTTP/2 support
+        ChannelPipeline pipeline = channel.pipeline();
+
+        SslContext sslCtx = configureServerHttp2SSLOnDemand();
+        if (sslCtx != null) {
+            final SslHandler sslHandler = sslCtx.newHandler(channel.alloc());
 
-        pipeline.addLast(applicationExecutor, "handler", this.getServletHandler());
+            LOG.log(Level.FINE,
+                    "Server SSL handler configured and added as an interceptor against the ChannelPipeline: {}",
+                    sslHandler);
+            
+            pipeline.addLast(sslHandler, new Http2OrHttpHandler());
+            return pipeline;
+        }
+        
+        final UpgradeCodecFactory upgradeCodecFactory = new UpgradeCodecFactory() {
+            @Override
+            public UpgradeCodec newUpgradeCodec(CharSequence protocol) {
+                if (AsciiString.contentEquals(Http2CodecUtil.HTTP_UPGRADE_PROTOCOL_NAME, protocol)) {
+                    return new Http2ServerUpgradeCodec(
+                        Http2FrameCodecBuilder.forServer().build(),
+                        new Http2MultiplexHandler(createHttp2ChannelInitializer()));
+                } else {
+                    return null;
+                }
+            }
+        };
+        
+        final HttpServerCodec sourceCodec = new HttpServerCodec();
+        final HttpServerUpgradeHandler upgradeHandler = new HttpServerUpgradeHandler(sourceCodec, upgradeCodecFactory);
+        final CleartextHttp2ServerUpgradeHandler cleartextUpgradeHandler = new CleartextHttp2ServerUpgradeHandler(
+            sourceCodec, upgradeHandler, createHttp2ChannelInitializerPriorKnowledge());
+
+        pipeline.addLast(cleartextUpgradeHandler);
+        pipeline.addLast(new SimpleChannelInboundHandler<HttpMessage>() {
+            @Override
+            protected void channelRead0(ChannelHandlerContext ctx, HttpMessage msg) throws Exception {
+                // If this handler is hit then no upgrade has been attempted and the client is just talking HTTP
+                final ChannelPipeline pipeline = ctx.pipeline();
+                
+                pipeline.addAfter(applicationExecutor, ctx.name(), "handler", getServletHandler());
+                pipeline.replace(this, "aggregator", new HttpObjectAggregator(maxChunkContentSize));
+
+                // Remove the following line if you don't want automatic content compression.
+                pipeline.addLast("deflater", new HttpContentCompressor());
+
+                // Set up the idle handler
+                pipeline.addLast("idle", new IdleStateHandler(nettyHttpServerEngine.getReadIdleTime(),
+                        nettyHttpServerEngine.getWriteIdleTime(), 0));
+
+                ctx.fireChannelRead(ReferenceCountUtil.retain(msg));
+            }
+        });
+        
+        return pipeline;
     }
 
+    private ChannelInitializer<Channel> createHttp2ChannelInitializer() {
+        return new ChannelInitializer<Channel>() {
+            @Override
+            protected void initChannel(Channel childChannel) throws Exception {
+                childChannel.pipeline()
+                    .addLast(new Http2StreamFrameToHttpObjectCodec(true))
+                    .addLast("aggregator", new HttpObjectAggregator(maxChunkContentSize))
+                    .addLast(applicationExecutor, getServletHandler());
+            }
+        };
+    }
+    
+    private ChannelInitializer<Channel> createHttp2ChannelInitializerPriorKnowledge() {
+        return new ChannelInitializer<Channel>() {
+            @Override
+            protected void initChannel(Channel childChannel) throws Exception {
+                configureDefaultHttp2Pipeline(childChannel.pipeline());
+            }
+        };
+    }
 }
diff --git a/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/spring/NettyHttpServerEngineBeanDefinitionParser.java b/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/spring/NettyHttpServerEngineBeanDefinitionParser.java
index 2ef975e..8e8daf9 100644
--- a/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/spring/NettyHttpServerEngineBeanDefinitionParser.java
+++ b/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/spring/NettyHttpServerEngineBeanDefinitionParser.java
@@ -229,7 +229,6 @@ public class NettyHttpServerEngineBeanDefinitionParser extends AbstractBeanDefin
 
         String threadingRef;
         String tlsRef;
-        Bus bus;
         NettyHttpServerEngineFactory factory;
 
         public SpringNettyHttpServerEngine(
@@ -237,8 +236,7 @@ public class NettyHttpServerEngineBeanDefinitionParser extends AbstractBeanDefin
             Bus b,
             String host,
             int port) {
-            super(host, port);
-            bus = b;
+            super(host, port, b);
             factory = fac;
         }
 
@@ -247,15 +245,15 @@ public class NettyHttpServerEngineBeanDefinitionParser extends AbstractBeanDefin
         }
 
         public void setBus(Bus b) {
-            bus = b;
-            if (null != bus && null == factory) {
-                factory = bus.getExtension(NettyHttpServerEngineFactory.class);
+            super.setBus(b);
+            if (null != getBus() && null == factory) {
+                factory = getBus().getExtension(NettyHttpServerEngineFactory.class);
             }
         }
 
         public void setApplicationContext(ApplicationContext ctx) throws BeansException {
-            if (bus == null) {
-                bus = BusWiringBeanFactoryPostProcessor.addDefaultBus(ctx);
+            if (getBus() == null) {
+                setBus(BusWiringBeanFactoryPostProcessor.addDefaultBus(ctx));
             }
         }
 
diff --git a/rt/transports/http-undertow/src/main/java/org/apache/cxf/transport/http_undertow/UndertowHTTPServerEngine.java b/rt/transports/http-undertow/src/main/java/org/apache/cxf/transport/http_undertow/UndertowHTTPServerEngine.java
index e684f6f..b8971ba 100644
--- a/rt/transports/http-undertow/src/main/java/org/apache/cxf/transport/http_undertow/UndertowHTTPServerEngine.java
+++ b/rt/transports/http-undertow/src/main/java/org/apache/cxf/transport/http_undertow/UndertowHTTPServerEngine.java
@@ -43,6 +43,7 @@ import org.apache.cxf.common.util.SystemPropertyAction;
 import org.apache.cxf.configuration.jsse.TLSServerParameters;
 import org.apache.cxf.interceptor.Fault;
 import org.apache.cxf.transport.HttpUriMapper;
+import org.apache.cxf.transport.http.HttpServerEngineSupport;
 import org.apache.cxf.transport.https.AliasedX509ExtendedKeyManager;
 import org.xnio.Options;
 import org.xnio.Sequence;
@@ -64,10 +65,14 @@ import io.undertow.servlet.handlers.ServletPathMatches;
 import io.undertow.util.CopyOnWriteMap;
 
 
-public class UndertowHTTPServerEngine implements ServerEngine {
+public class UndertowHTTPServerEngine implements ServerEngine, HttpServerEngineSupport {
 
     public static final String DO_NOT_CHECK_URL_PROP = "org.apache.cxf.transports.http_undertow.DontCheckUrl";
     
+    /**
+     * Please use {@link HttpServerEngineSupport#ENABLE_HTTP2} instead.
+     */
+    @Deprecated
     public static final String ENABLE_HTTP2_PROP = "org.apache.cxf.transports.http_undertow.EnableHttp2";
     
     public static final String ENABLE_RECORD_REQUEST_START_TIME_PROP = 
@@ -183,6 +188,17 @@ public class UndertowHTTPServerEngine implements ServerEngine {
         servantCount = servantCount + 1;
     }
 
+    @Override
+    public boolean isHttp2Enabled(Bus bus) {
+        Object prop = null;
+        if (bus != null) {
+            prop = bus.getProperty(ENABLE_HTTP2_PROP);
+        }
+        if (prop == null) {
+            prop = SystemPropertyAction.getPropertyOrNull(ENABLE_HTTP2_PROP);
+        }
+        return PropertyUtils.isTrue(prop) || HttpServerEngineSupport.super.isHttp2Enabled(bus);
+    }
 
     private ServletContext buildServletContext(String contextName)
         throws ServletException {
@@ -203,7 +219,7 @@ public class UndertowHTTPServerEngine implements ServerEngine {
     private Undertow createServer(URL url, UndertowHTTPHandler undertowHTTPHandler) throws Exception {
         Undertow.Builder result = Undertow.builder();
         result.setServerOption(UndertowOptions.IDLE_TIMEOUT, getMaxIdleTime());
-        if (this.shouldEnableHttp2(undertowHTTPHandler.getBus())) {
+        if (this.isHttp2Enabled(undertowHTTPHandler.getBus())) {
             result.setServerOption(UndertowOptions.ENABLE_HTTP2, Boolean.TRUE);
         }
         if (this.shouldEnableRecordRequestStartTime(undertowHTTPHandler.getBus())) {
@@ -313,18 +329,6 @@ public class UndertowHTTPServerEngine implements ServerEngine {
         return !PropertyUtils.isTrue(prop);
     }
     
-    private boolean shouldEnableHttp2(Bus bus) {
-
-        Object prop = null;
-        if (bus != null) {
-            prop = bus.getProperty(ENABLE_HTTP2_PROP);
-        }
-        if (prop == null) {
-            prop = SystemPropertyAction.getPropertyOrNull(ENABLE_HTTP2_PROP);
-        }
-        return PropertyUtils.isTrue(prop);
-    }
-    
     private boolean shouldEnableRecordRequestStartTime(Bus bus) {
 
         Object prop = null;
diff --git a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HttpServerEngineSupport.java b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HttpServerEngineSupport.java
new file mode 100644
index 0000000..fd4762e
--- /dev/null
+++ b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HttpServerEngineSupport.java
@@ -0,0 +1,47 @@
+/**
+ * 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;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.common.util.PropertyUtils;
+import org.apache.cxf.common.util.SystemPropertyAction;
+
+/**
+ * Support class for HTTP server engines: holds common properties and commonly
+ * used methods, shared across all HTTP server engine implementations (Tomcat, Jetty,
+ * Undertow, Netty, ...).
+ */
+public interface HttpServerEngineSupport {
+    String ENABLE_HTTP2 = "org.apache.cxf.transports.http2.enabled";
+    
+    default boolean isHttp2Enabled(Bus bus) {
+        Object value = null;
+        
+        if (bus != null) {
+            value = bus.getProperty(ENABLE_HTTP2);
+        }
+        
+        if (value == null) {
+            value = SystemPropertyAction.getPropertyOrNull(ENABLE_HTTP2);
+        }
+        
+        return PropertyUtils.isTrue(value);
+    }
+}
diff --git a/rt/transports/http/src/main/java/org/apache/cxf/transport/https/SSLContextInitParameters.java b/rt/transports/http/src/main/java/org/apache/cxf/transport/https/SSLContextInitParameters.java
new file mode 100644
index 0000000..2182962
--- /dev/null
+++ b/rt/transports/http/src/main/java/org/apache/cxf/transport/https/SSLContextInitParameters.java
@@ -0,0 +1,44 @@
+/**
+ * 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.https;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.TrustManager;
+
+public final class SSLContextInitParameters {
+    private KeyManager[] keyManagers;
+    private TrustManager[] trustManagers;
+
+    public void setKeyManagers(KeyManager[] keyManagers) {
+        this.keyManagers = keyManagers; 
+    }
+    
+    public KeyManager[] getKeyManagers() {
+        return keyManagers;
+    }
+
+    public void setTrustManagers(TrustManager[] trustManagers) {
+        this.trustManagers = trustManagers;
+    }
+    
+    public TrustManager[] getTrustManagers() {
+        return trustManagers;
+    }
+}
diff --git a/rt/transports/http/src/main/java/org/apache/cxf/transport/https/SSLUtils.java b/rt/transports/http/src/main/java/org/apache/cxf/transport/https/SSLUtils.java
index 49242ac..f43253f 100644
--- a/rt/transports/http/src/main/java/org/apache/cxf/transport/https/SSLUtils.java
+++ b/rt/transports/http/src/main/java/org/apache/cxf/transport/https/SSLUtils.java
@@ -59,16 +59,11 @@ public final class SSLUtils {
         }
         return verifier;
     }
-
-    public static SSLContext getSSLContext(TLSParameterBase parameters) throws GeneralSecurityException {
-        // TODO do we need to cache the context
-        String provider = parameters.getJsseProvider();
-
-        String protocol = parameters.getSecureSocketProtocol() != null ? parameters
-            .getSecureSocketProtocol() : "TLS";
-
-        SSLContext ctx = provider == null ? SSLContext.getInstance(protocol) : SSLContext
-            .getInstance(protocol, provider);
+    
+    public static SSLContextInitParameters getSSLContextInitParameters(TLSParameterBase parameters) 
+            throws GeneralSecurityException {
+        
+        final SSLContextInitParameters contextParameters = new SSLContextInitParameters();
 
         KeyManager[] keyManagers = parameters.getKeyManagers();
         if (keyManagers == null && parameters instanceof TLSClientParameters) {
@@ -80,8 +75,25 @@ public final class SSLUtils {
         if (trustManagers == null && parameters instanceof TLSClientParameters) {
             trustManagers = org.apache.cxf.configuration.jsse.SSLUtils.getDefaultTrustStoreManagers(LOG);
         }
+        
+        contextParameters.setKeyManagers(configuredKeyManagers);
+        contextParameters.setTrustManagers(trustManagers);
+        
+        return contextParameters;
+    }
+
+    public static SSLContext getSSLContext(TLSParameterBase parameters) throws GeneralSecurityException {
+        // TODO do we need to cache the context
+        String provider = parameters.getJsseProvider();
+
+        String protocol = parameters.getSecureSocketProtocol() != null ? parameters
+            .getSecureSocketProtocol() : "TLS";
+
+        SSLContext ctx = provider == null ? SSLContext.getInstance(protocol) : SSLContext
+            .getInstance(protocol, provider);
 
-        ctx.init(configuredKeyManagers, trustManagers, parameters.getSecureRandom());
+        final SSLContextInitParameters initParams = getSSLContextInitParameters(parameters);
+        ctx.init(initParams.getKeyManagers(), initParams.getTrustManagers(), parameters.getSecureRandom());
 
         if (parameters instanceof TLSClientParameters && ctx.getClientSessionContext() != null) {
             ctx.getClientSessionContext().setSessionTimeout(((TLSClientParameters)parameters).getSslCacheTimeout());
diff --git a/systests/pom.xml b/systests/pom.xml
index 4cd65db..dd5cacf 100644
--- a/systests/pom.xml
+++ b/systests/pom.xml
@@ -55,5 +55,6 @@
         <module>rs-sse</module>
         <module>microprofile</module>
         <module>spring-boot</module>
+        <module>transport-netty</module>
     </modules>
 </project>
diff --git a/systests/transports/pom.xml b/systests/transport-netty/pom.xml
similarity index 53%
copy from systests/transports/pom.xml
copy to systests/transport-netty/pom.xml
index 1c7a9a0..5ea8818 100644
--- a/systests/transports/pom.xml
+++ b/systests/transport-netty/pom.xml
@@ -26,14 +26,15 @@
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.apache.cxf.systests</groupId>
-    <artifactId>cxf-systests-transports</artifactId>
-    <name>Apache CXF Transport System Tests</name>
-    <description>Apache CXF Transport System Tests</description>
+    <artifactId>cxf-systests-transport-netty</artifactId>
+    <name>Apache CXF Netty Transport System Tests</name>
+    <description>Apache CXF Netty Transport System Tests</description>
     <url>https://cxf.apache.org</url>
+    
     <properties>
-        <cxf.surefire.fork.vmargs>-Djdk.http.auth.tunneling.disabledSchemes=""</cxf.surefire.fork.vmargs>
-        <cxf.module.name>org.apache.cxf.systests.transport</cxf.module.name>
+        <cxf.module.name>org.apache.cxf.systests.transport.netty</cxf.module.name>
     </properties>
+    
     <build>
         <testSourceDirectory>${basedir}/src/test/java</testSourceDirectory>
         <testResources>
@@ -103,63 +104,38 @@
         </dependency>
         <dependency>
             <groupId>org.apache.cxf</groupId>
-            <artifactId>cxf-rt-frontend-jaxws</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.cxf</groupId>
-            <artifactId>cxf-rt-frontend-js</artifactId>
+            <artifactId>cxf-rt-transports-http</artifactId>
             <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.cxf</groupId>
-            <artifactId>cxf-rt-bindings-soap</artifactId>
+            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
             <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.cxf</groupId>
-            <artifactId>cxf-rt-databinding-aegis</artifactId>
+            <artifactId>cxf-rt-rs-client</artifactId>
             <version>${project.version}</version>
         </dependency>
         <dependency>
-            <groupId>org.apache.cxf</groupId>
-            <artifactId>cxf-rt-transports-http</artifactId>
-            <version>${project.version}</version>
+            <groupId>com.fasterxml.jackson.jaxrs</groupId>
+            <artifactId>jackson-jaxrs-json-provider</artifactId>
+            <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.apache.cxf</groupId>
-            <artifactId>cxf-rt-transports-http-hc</artifactId>
-            <version>${project.version}</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>jcl-over-slf4j</artifactId>
-                </exclusion>
-            </exclusions>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-annotations</artifactId>
+            <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.cxf</groupId>
-            <artifactId>cxf-rt-transports-udp</artifactId>
+            <artifactId>cxf-rt-rs-extension-providers</artifactId>
             <version>${project.version}</version>
         </dependency>
         <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-servlet</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-webapp</artifactId>
-        </dependency>
-        <dependency>
             <groupId>org.apache.cxf</groupId>
-            <artifactId>cxf-rt-transports-http-jetty</artifactId>
+            <artifactId>cxf-rt-transports-http-netty-server</artifactId>
             <version>${project.version}</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>javax.servlet</groupId>
-                    <artifactId>javax.servlet-api</artifactId>
-                </exclusion>
-            </exclusions>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
@@ -173,175 +149,55 @@
         </dependency>
         <dependency>
             <groupId>org.apache.cxf</groupId>
-            <artifactId>cxf-rt-transports-local</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.cxf</groupId>
-            <artifactId>cxf-rt-ws-policy</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.cxf</groupId>
-            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.cxf</groupId>
-            <artifactId>cxf-rt-features-logging</artifactId>
+            <artifactId>cxf-testutils</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>
+            <classifier>keys</classifier>
         </dependency>
         <dependency>
             <groupId>org.apache.cxf</groupId>
-            <artifactId>cxf-testutils</artifactId>
+            <artifactId>cxf-rt-features-logging</artifactId>
             <version>${project.version}</version>
             <scope>test</scope>
-            <classifier>keys</classifier>
         </dependency>
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-web</artifactId>
-            <scope>test</scope>
             <version>${cxf.spring.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-webmvc</artifactId>
             <scope>test</scope>
-            <version>${cxf.spring.version}</version>
         </dependency>
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-beans</artifactId>
-            <scope>test</scope>
             <version>${cxf.spring.version}</version>
+            <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-context</artifactId>
-            <scope>test</scope>
             <version>${cxf.spring.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>httpunit</groupId>
-            <artifactId>httpunit</artifactId>
-            <version>1.7</version>
             <scope>test</scope>
-            <exclusions>
-                <exclusion>
-                    <groupId>javax.servlet</groupId>
-                    <artifactId>servlet-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>xerces</groupId>
-                    <artifactId>xercesImpl</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>xerces</groupId>
-                    <artifactId>xmlParserAPIs</artifactId>
-                </exclusion>
-            </exclusions>
         </dependency>
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-core</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>${cxf.spring.mock}</artifactId>
-            <version>${cxf.spring.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.security</groupId>
-            <artifactId>spring-security-config</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.security</groupId>
-            <artifactId>spring-security-web</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-test</artifactId>
-            <version>${cxf.spring.boot.version}</version>
-            <scope>test</scope>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.springframework.boot</groupId>
-                    <artifactId>spring-boot-starter-logging</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-web</artifactId>
-            <version>${cxf.spring.boot.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.cxf</groupId>
-            <artifactId>cxf-rt-rs-client</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-j2ee-connector_1.5_spec</artifactId>
-        </dependency>
-        <!-- make http://java.sun.com/dtd/web-app_2_3.dtd et al locally available during the tests -->
-        <dependency>
-            <groupId>${cxf.servlet-api.group}</groupId>
-            <artifactId>${cxf.servlet-api.artifact}</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>rhino</groupId>
-            <artifactId>js</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jettison</groupId>
-            <artifactId>jettison</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.littleshoot</groupId>
-            <artifactId>littleproxy</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.glassfish.jaxb</groupId>
-            <artifactId>jaxb-xjc</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bctls-jdk15on</artifactId>
-            <version>${cxf.bcprov.version}</version>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-codec-http2</artifactId>
+            <version>${cxf.netty.version}</version>
             <scope>test</scope>
         </dependency>
     </dependencies>
-
-    <profiles>
-        <profile>
-            <id>jdk16</id>
-            <activation>
-                <jdk>[16,)</jdk>
-            </activation>
-            <properties>
-                <cxf.surefire.fork.vmargs>--add-opens java.xml/com.sun.org.apache.xerces.internal.dom=ALL-UNNAMED -Djdk.http.auth.tunneling.disabledSchemes=""</cxf.surefire.fork.vmargs>
-            </properties>
-        </profile>
-    </profiles>
 </project>
diff --git a/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/AbstractBookServerHttp2.java b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/AbstractBookServerHttp2.java
new file mode 100644
index 0000000..1a07c9d
--- /dev/null
+++ b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/AbstractBookServerHttp2.java
@@ -0,0 +1,64 @@
+/**
+ * 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.http2.netty;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.customer.book.Book;
+import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
+import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
+import org.apache.cxf.jaxrs.provider.StreamingResponseProvider;
+import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
+import org.apache.cxf.transport.http.HttpServerEngineSupport;
+
+abstract class AbstractBookServerHttp2 extends AbstractBusTestServerBase {
+    org.apache.cxf.endpoint.Server server;
+
+    private final String port;
+    private final String context;
+    private final String scheme;
+
+    AbstractBookServerHttp2(String port, String context, String scheme) {
+        this.port = port;
+        this.context = context;
+        this.scheme = scheme;
+    }
+
+    protected void run() {
+        SpringBusFactory factory = new SpringBusFactory();
+        Bus bus = factory.createBus(context);
+        bus.setProperty(HttpServerEngineSupport.ENABLE_HTTP2, true);
+        setBus(bus);
+        JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
+        sf.setBus(bus);
+        sf.setResourceClasses(BookStore.class);
+        sf.setProvider(new StreamingResponseProvider<Book>());
+        sf.setResourceProvider(BookStore.class,
+            new SingletonResourceProvider(new BookStore(), true));
+        sf.setAddress(scheme + "://localhost:" + port + "/http2");
+        server = sf.create();
+    }
+
+    public void tearDown() throws Exception {
+        server.stop();
+        server.destroy();
+        server = null;
+    }
+}
diff --git a/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/AbstractNettyClientServerHttp2Test.java b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/AbstractNettyClientServerHttp2Test.java
new file mode 100644
index 0000000..1263377
--- /dev/null
+++ b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/AbstractNettyClientServerHttp2Test.java
@@ -0,0 +1,118 @@
+/**
+ * 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.http2.netty;
+
+import javax.ws.rs.core.Response;
+
+import org.apache.cxf.configuration.jsse.TLSClientParameters;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.systest.http2.netty.Http2TestClient.ClientResponse;
+import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
+import org.apache.cxf.transport.http.HTTPConduit;
+import org.apache.cxf.transport.https.InsecureTrustManager;
+
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+abstract class AbstractNettyClientServerHttp2Test extends AbstractBusClientServerTestBase {
+    @Test
+    public void testBookNotFoundWithHttp2() throws Exception {
+        final Http2TestClient client = new Http2TestClient(isSecure());
+        
+        final ClientResponse response = client
+            .request(getAddress())
+            .accept("text/plain")
+            .path(getContext() + "/web/bookstore/notFound")
+            .http2()
+            .get();
+        
+        assertThat(response.getResponseCode(), equalTo(404));
+        assertThat(response.getProtocol(), equalTo("HTTP/2.0"));
+    }
+    
+    @Test
+    public void testBookWithHttp2() throws Exception {
+        final Http2TestClient client = new Http2TestClient(isSecure());
+        
+        final ClientResponse response = client
+            .request(getAddress())
+            .accept("text/plain")
+            .path(getContext() + "/web/bookstore/booknames")
+            .http2()
+            .get();
+        
+        assertThat(response.getResponseCode(), equalTo(200));
+        assertThat(response.getProtocol(), equalTo("HTTP/2.0"));
+        assertEquals("CXF in Action", response.getBody());
+    }
+
+    @Test
+    public void testGetBookStreamHttp2() throws Exception {
+        final Http2TestClient client = new Http2TestClient(isSecure());
+        
+        final ClientResponse response = client
+            .request(getAddress())
+            .accept("application/xml")
+            .path(getContext() + "/web/bookstore/bookstream")
+            .http2()
+            .get();
+
+        assertThat(response.getResponseCode(), equalTo(200));
+        assertThat(response.getProtocol(), equalTo("HTTP/2.0"));
+        assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
+            + "<Book><id>1</id><name>Book1</name></Book>", response.getBody());
+    }
+
+    @Test
+    public void testBookWithHttp() throws Exception {
+        final WebClient wc = WebClient
+            .create(getAddress() + getContext() + "/web/bookstore/booknames")
+            .accept("text/plain");
+        
+        if (isSecure()) {
+            final HTTPConduit conduit = WebClient.getConfig(wc).getHttpConduit();
+            TLSClientParameters params = conduit.getTlsClientParameters();
+
+            if (params == null)  {
+                params = new TLSClientParameters();
+                conduit.setTlsClientParameters(params);
+            }
+
+            // Create TrustManager instance which trusts all clients and servers
+            params.setTrustManagers(InsecureTrustManager.getNoOpX509TrustManagers()); 
+            params.setDisableCNCheck(true);
+        }
+        
+        try (Response resp = wc.get()) {
+            assertThat(resp.getStatus(), equalTo(200));
+            assertEquals("CXF in Action", resp.readEntity(String.class));
+        }
+    }
+
+    protected abstract String getAddress();
+    protected abstract String getContext();
+
+    protected boolean isSecure() {
+        return getAddress().startsWith("https");
+    }
+}
\ No newline at end of file
diff --git a/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/Book.java b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/Book.java
new file mode 100644
index 0000000..9d95c5d
--- /dev/null
+++ b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/Book.java
@@ -0,0 +1,69 @@
+/**
+ * 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.http2.netty;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
+import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
+
+@JsonTypeInfo(use = Id.CLASS, include = As.PROPERTY, property = "class")
+@XmlRootElement(name = "Book")
+public class Book {
+    private String name;
+    private long id;
+
+    public Book() {
+    }
+
+    public Book(String name, long id) {
+        this.name = name;
+        this.id = id;
+    }
+
+    public void setName(String n) {
+        name = n;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setId(long i) {
+        id = i;
+    }
+    public long getId() {
+        return id;
+    }
+
+    @PUT
+    public void cloneState(Book book) {
+        id = book.getId();
+        name = book.getName();
+    }
+
+    @GET
+    public Book retrieveState() {
+        return this;
+    }
+}
diff --git a/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/BookServerHttp2.java b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/BookServerHttp2.java
new file mode 100644
index 0000000..51be2c2
--- /dev/null
+++ b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/BookServerHttp2.java
@@ -0,0 +1,47 @@
+/**
+ * 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.http2.netty;
+
+public class BookServerHttp2 extends AbstractBookServerHttp2 {
+    public static final String PORT = allocatePort(BookServerHttp2.class);
+
+    org.apache.cxf.endpoint.Server server;
+
+    public BookServerHttp2() {
+        this(PORT);
+    }
+
+    public BookServerHttp2(String port) {
+        super(port, "org/apache/cxf/systest/http2_netty/server-tls.xml", "https");
+    }
+
+    public static void main(String[] args) {
+        try {
+            BookServerHttp2 s = new BookServerHttp2();
+            s.start();
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            System.exit(-1);
+        } finally {
+            System.out.println("done!");
+        }
+    }
+
+}
diff --git a/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/BookServerHttp2c.java b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/BookServerHttp2c.java
new file mode 100644
index 0000000..73ca51c
--- /dev/null
+++ b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/BookServerHttp2c.java
@@ -0,0 +1,45 @@
+/**
+ * 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.http2.netty;
+
+public class BookServerHttp2c extends AbstractBookServerHttp2 {
+    public static final String PORT = allocatePort(BookServerHttp2c.class);
+
+    public BookServerHttp2c() {
+        this(PORT);
+    }
+
+    public BookServerHttp2c(String port) {
+        super(port, "org/apache/cxf/systest/http2_netty/server.xml", "http");
+    }
+
+    public static void main(String[] args) {
+        try {
+            BookServerHttp2c s = new BookServerHttp2c();
+            s.start();
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            System.exit(-1);
+        } finally {
+            System.out.println("done!");
+        }
+    }
+
+}
diff --git a/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/BookStore.java b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/BookStore.java
new file mode 100644
index 0000000..4b4e1ca
--- /dev/null
+++ b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/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.http2.netty;
+
+import java.io.IOException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+import org.apache.cxf.jaxrs.ext.StreamingResponse;
+
+@Path("/web/bookstore")
+public class BookStore {
+    private static ExecutorService executor = Executors.newSingleThreadExecutor();
+
+    @GET
+    @Path("/booknames")
+    @Produces("text/plain")
+    public byte[] getBookName() {
+        return "CXF in Action".getBytes();
+    }
+
+    @GET
+    @Path("/bookstream")
+    @Produces("application/xml")
+    public StreamingResponse<Book> getBookStream() {
+        return new StreamingResponse<Book>() {
+            public void writeTo(final StreamingResponse.Writer<Book> out) throws IOException {
+                out.write(new Book("Book1", 1));
+                executor.execute(new Runnable() {
+                    public void run() {
+                        try {
+                            for (int i = 2; i <= 5; i++) {
+                                Thread.sleep(500);
+                                out.write(new Book("Book" + i, i));
+                                out.getEntityStream().flush();
+                            }
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+                    }
+                });
+            }
+        };
+    }
+}
+
+
diff --git a/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/Http2TestClient.java b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/Http2TestClient.java
new file mode 100644
index 0000000..32e4e64
--- /dev/null
+++ b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/Http2TestClient.java
@@ -0,0 +1,401 @@
+/**
+ * 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.http2.netty;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.AbstractMap.SimpleEntry;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.core.MediaType;
+
+import io.netty.bootstrap.Bootstrap;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.ChannelPromise;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioSocketChannel;
+import io.netty.handler.codec.http.DefaultFullHttpRequest;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.FullHttpResponse;
+import io.netty.handler.codec.http.HttpClientCodec;
+import io.netty.handler.codec.http.HttpClientUpgradeHandler;
+import io.netty.handler.codec.http.HttpHeaderNames;
+import io.netty.handler.codec.http.HttpMethod;
+import io.netty.handler.codec.http.HttpVersion;
+import io.netty.handler.codec.http2.DefaultHttp2Connection;
+import io.netty.handler.codec.http2.DelegatingDecompressorFrameListener;
+import io.netty.handler.codec.http2.Http2ClientUpgradeCodec;
+import io.netty.handler.codec.http2.Http2Connection;
+import io.netty.handler.codec.http2.Http2ConnectionHandler;
+import io.netty.handler.codec.http2.Http2SecurityUtil;
+import io.netty.handler.codec.http2.Http2Settings;
+import io.netty.handler.codec.http2.HttpConversionUtil;
+import io.netty.handler.codec.http2.HttpToHttp2ConnectionHandlerBuilder;
+import io.netty.handler.codec.http2.InboundHttp2ToHttpAdapterBuilder;
+import io.netty.handler.ssl.ApplicationProtocolConfig;
+import io.netty.handler.ssl.ApplicationProtocolConfig.Protocol;
+import io.netty.handler.ssl.ApplicationProtocolConfig.SelectedListenerFailureBehavior;
+import io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBehavior;
+import io.netty.handler.ssl.ApplicationProtocolNames;
+import io.netty.handler.ssl.SslContext;
+import io.netty.handler.ssl.SslProvider;
+import io.netty.handler.ssl.SupportedCipherSuiteFilter;
+import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
+import io.netty.util.internal.PlatformDependent;
+
+/**
+ * TODO: Use CXF client once https://issues.apache.org/jira/browse/CXF-8606 is dones
+ */
+public class Http2TestClient implements AutoCloseable {
+    private final SslContext ssl;
+    
+    public Http2TestClient(boolean secure) throws Exception {
+        if (secure) {
+            ssl = SslContext.newClientContext(
+                SslProvider.JDK,
+                null, 
+                InsecureTrustManagerFactory.INSTANCE,
+                Http2SecurityUtil.CIPHERS,
+                SupportedCipherSuiteFilter.INSTANCE,
+                new ApplicationProtocolConfig(
+                        Protocol.ALPN,
+                        SelectorFailureBehavior.FATAL_ALERT,
+                        SelectedListenerFailureBehavior.FATAL_ALERT,
+                        ApplicationProtocolNames.HTTP_2,
+                        ApplicationProtocolNames.HTTP_1_1),
+                0, 0);
+        } else {
+            ssl = null;
+        }
+    }
+    
+    public static class ClientResponse {
+        private String body;
+        private String protocol;
+        private int responseCode;
+        
+        public ClientResponse(int responseCode, String protocol) {
+            this.responseCode = responseCode;
+            this.protocol = protocol;
+        }
+
+        public void setBody(String body) {
+            this.body = body;
+        }
+        
+        public String getBody() {
+            return body;
+        }
+        
+        public void setResponseCode(int rc) {
+            this.responseCode = rc;
+        }
+
+        public int getResponseCode() {
+            return responseCode;
+        }
+
+        public String getProtocol() {
+            return protocol;
+        }
+        
+        public void setProtocol(String protocol) {
+            this.protocol = protocol;
+        }
+    }
+    
+    public class RequestBuilder {
+        private final String address;
+        private String path = "";
+        private String accept = MediaType.WILDCARD;
+        private HttpVersion version = HttpVersion.HTTP_1_1;
+
+        public RequestBuilder(final String address) {
+            this.address = address;
+        }
+        
+        public RequestBuilder path(final String p) {
+            this.path = p;
+            return this;
+        }
+        
+        
+        public RequestBuilder accept(final String a) {
+            this.accept = a;
+            return this;
+        }
+        
+        public RequestBuilder http2() {
+            version = null;
+            return this;
+        }
+        
+        public ClientResponse get() throws Exception {
+            return request(address, path, version, HttpMethod.GET, accept);
+        }
+    }
+    
+    public RequestBuilder request(final String address) throws IOException {
+        return new RequestBuilder(address);
+    }
+
+    public ClientResponse request(final String address, final String path, 
+            final HttpVersion version, final HttpMethod method, final String accept) 
+                throws Exception {
+
+        final URI uri = URI.create(address);
+                
+        final Http2ClientInitializer initializer = new Http2ClientInitializer(Integer.MAX_VALUE);
+        final NioEventLoopGroup worker = new NioEventLoopGroup();
+        
+        final Bootstrap bootstrap = new Bootstrap();
+        bootstrap.group(worker);
+        bootstrap.channel(NioSocketChannel.class);
+        bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
+        bootstrap.remoteAddress(uri.getHost(), uri.getPort());
+        bootstrap.handler(initializer);
+
+        final Channel channel = bootstrap.connect().syncUninterruptibly().channel();
+        final HttpResponseHandler responseHandler = initializer.getResponseHandler();
+        final Http2SettingsHandler http2SettingsHandler = initializer.getSettingsHandler();
+
+        try {
+            final FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, method, path);
+            request.headers().add(HttpHeaderNames.HOST, uri.getHost());
+            request.headers().add(HttpHeaderNames.ACCEPT, accept);
+            request.headers().add(HttpConversionUtil.ExtensionHeaderNames.SCHEME.text(), uri.getScheme());
+
+            http2SettingsHandler.awaitSettings(5, TimeUnit.SECONDS);
+            responseHandler.put(3, channel.write(request), channel.newPromise());
+            
+            channel.flush();
+            responseHandler.awaitResponses(15, TimeUnit.SECONDS);
+        } finally {
+            channel.close().awaitUninterruptibly();
+            worker.shutdownGracefully();
+        }
+        
+        
+        final List<ClientResponse> responses = responseHandler.responses();
+        if (responses.size() != 1) {
+            throw new IllegalStateException("Expected exactly one response, but got 0 or more");
+        }
+        
+        return responses.get(0);
+    }
+    
+    @Override
+    public void close() throws Exception {
+    }
+    
+    private class Http2SettingsHandler extends SimpleChannelInboundHandler<Http2Settings> {
+        private ChannelPromise promise;
+
+        Http2SettingsHandler(ChannelPromise promise) {
+            this.promise = promise;
+        }
+
+        /**
+         * Wait for this handler to be added after the upgrade to HTTP/2, and for initial preface
+         * handshake to complete.
+         */
+        void awaitSettings(long timeout, TimeUnit unit) throws Exception {
+            if (!promise.awaitUninterruptibly(timeout, unit)) {
+                throw new IllegalStateException("Timed out waiting for settings");
+            }
+            if (!promise.isSuccess()) {
+                throw new RuntimeException(promise.cause());
+            }
+        }
+        
+        @Override
+        protected void channelRead0(ChannelHandlerContext ctx, Http2Settings msg) throws Exception {
+            promise.setSuccess();
+            ctx.pipeline().remove(this);
+        }
+    }
+    
+    private class HttpResponseHandler extends SimpleChannelInboundHandler<FullHttpResponse> {
+        private final Map<Integer, Entry<ChannelFuture, ChannelPromise>> streamidPromiseMap;
+        private final List<ClientResponse> responses = new CopyOnWriteArrayList<>(); 
+        
+        HttpResponseHandler() {
+            streamidPromiseMap = PlatformDependent.newConcurrentHashMap();
+        }
+
+        Entry<ChannelFuture, ChannelPromise> put(int streamId, ChannelFuture writeFuture, ChannelPromise promise) {
+            return streamidPromiseMap.put(streamId, new SimpleEntry<>(writeFuture, promise));
+        }
+
+        void awaitResponses(long timeout, TimeUnit unit) {
+            final Iterator<Entry<Integer, Entry<ChannelFuture, ChannelPromise>>> itr = streamidPromiseMap
+                .entrySet()
+                .iterator();
+            
+            while (itr.hasNext()) {
+                final Entry<Integer, Entry<ChannelFuture, ChannelPromise>> entry = itr.next();
+
+                final ChannelFuture writeFuture = entry.getValue().getKey();
+                if (!writeFuture.awaitUninterruptibly(timeout, unit)) {
+                    throw new IllegalStateException("Timed out waiting to write for stream id " + entry.getKey());
+                }
+                
+                if (!writeFuture.isSuccess()) {
+                    throw new RuntimeException(writeFuture.cause());
+                }
+                
+                final ChannelPromise promise = entry.getValue().getValue();
+                if (!promise.awaitUninterruptibly(timeout, unit)) {
+                    throw new IllegalStateException("Timed out waiting for response on stream id " + entry.getKey());
+                }
+                
+                if (!promise.isSuccess()) {
+                    throw new RuntimeException(promise.cause());
+                }
+
+                itr.remove();
+            }
+        }
+        
+        List<ClientResponse> responses() {
+            return responses;
+        }
+
+        @Override
+        protected void channelRead0(ChannelHandlerContext ctx, FullHttpResponse msg) throws Exception {
+            Integer streamId = msg.headers().getInt(HttpConversionUtil.ExtensionHeaderNames.STREAM_ID.text());
+            if (streamId == null) {
+                System.err.println("HttpResponseHandler unexpected message received: " + msg);
+                return;
+            }
+
+            final Entry<ChannelFuture, ChannelPromise> entry = streamidPromiseMap.get(streamId);
+            if (entry == null) {
+                System.err.println("Message received for unknown stream id " + streamId);
+            } else {
+                final ByteBuf content = msg.content();
+                final ClientResponse response = new ClientResponse(msg.status().code(), "HTTP/2.0");
+                
+                if (content.isReadable()) {
+                    int contentLength = content.readableBytes();
+                    byte[] arr = new byte[contentLength];
+                    content.readBytes(arr);
+                    response.setBody(new String(arr));
+                }
+
+                responses.add(response);
+                entry.getValue().setSuccess();
+            }
+        }
+    }
+    
+    private class Http2ClientInitializer extends ChannelInitializer<SocketChannel> {
+        private final int maxContentLength;
+        private HttpResponseHandler responseHandler;
+        private Http2SettingsHandler settingsHandler;
+        private Http2ConnectionHandler connectionHandler;
+
+        Http2ClientInitializer(int maxContentLength) {
+            this.maxContentLength = maxContentLength;
+        }
+
+        @Override
+        public void initChannel(SocketChannel ch) throws Exception {
+            final Http2Connection connection = new DefaultHttp2Connection(false);
+
+            responseHandler = new HttpResponseHandler();
+            settingsHandler = new Http2SettingsHandler(ch.newPromise());
+            
+            connectionHandler = new HttpToHttp2ConnectionHandlerBuilder()
+                .connection(connection)
+                .frameListener(new DelegatingDecompressorFrameListener(connection,
+                    new InboundHttp2ToHttpAdapterBuilder(connection)
+                        .maxContentLength(maxContentLength)
+                        .propagateSettings(true)
+                        .build()))
+                .build();
+
+            if (ssl != null) {
+                ch.pipeline().addLast(ssl.newHandler(ch.alloc()));
+                ch.pipeline().addLast(connectionHandler);
+                ch.pipeline().addLast(settingsHandler);
+                ch.pipeline().addLast(responseHandler);
+            } else {
+                final HttpClientCodec sourceCodec = new HttpClientCodec();
+                final Http2ClientUpgradeCodec upgradeCodec = new Http2ClientUpgradeCodec(connectionHandler);
+                final HttpClientUpgradeHandler upgradeHandler = new HttpClientUpgradeHandler(sourceCodec, 
+                    upgradeCodec, 65536);
+
+                ch.pipeline().addLast(sourceCodec);
+                ch.pipeline().addLast(upgradeHandler);
+                ch.pipeline().addLast(new UpgradeRequestHandler(settingsHandler, responseHandler));
+            }
+        }
+        
+        HttpResponseHandler getResponseHandler() {
+            return responseHandler;
+        }
+        
+        Http2SettingsHandler getSettingsHandler() {
+            return settingsHandler;
+        }
+    }
+    
+    /**
+     * A handler that triggers the cleartext upgrade to HTTP/2 by sending an 
+     * initial HTTP request.
+     */
+    private class UpgradeRequestHandler extends ChannelInboundHandlerAdapter {
+        private final Http2SettingsHandler settingsHandler;
+        private final HttpResponseHandler responseHandler;
+
+        UpgradeRequestHandler(final Http2SettingsHandler settingsHandler, final HttpResponseHandler responseHandler) {
+            this.settingsHandler = settingsHandler;
+            this.responseHandler = responseHandler;
+        }
+        
+        @Override
+        public void channelActive(ChannelHandlerContext ctx) throws Exception {
+            final FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/");
+            request.headers().add(HttpHeaderNames.HOST, "localhost");
+            request.headers().add(HttpConversionUtil.ExtensionHeaderNames.SCHEME.text(), "http");
+
+            ctx.writeAndFlush(request);
+            ctx.fireChannelActive();
+            
+            ctx.pipeline().remove(this);
+            ctx.pipeline().addLast(settingsHandler);
+            ctx.pipeline().addLast(responseHandler);
+        }
+    }
+}
diff --git a/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/NettyClientServerHttp2Test.java b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/NettyClientServerHttp2Test.java
new file mode 100644
index 0000000..d29fe7a
--- /dev/null
+++ b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/NettyClientServerHttp2Test.java
@@ -0,0 +1,48 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.systest.http2.netty;
+
+import org.apache.cxf.jaxrs.model.AbstractResourceInfo;
+
+import org.junit.BeforeClass;
+
+import static org.junit.Assert.assertTrue;
+
+public class NettyClientServerHttp2Test extends AbstractNettyClientServerHttp2Test {
+    private static final String PORT = BookServerHttp2.PORT;
+
+    @BeforeClass
+    public static void startServers() throws Exception {
+        AbstractResourceInfo.clearAllMaps();
+        assertTrue("server did not launch correctly", launchServer(new BookServerHttp2()));
+        createStaticBus();
+    }
+
+    
+    @Override
+    protected String getAddress() {
+        return "https://localhost:" + PORT;
+    }
+    
+    @Override
+    protected String getContext() {
+        return "/http2";
+    }
+}
diff --git a/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/NettyClientServerHttp2cTest.java b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/NettyClientServerHttp2cTest.java
new file mode 100644
index 0000000..b7d7f5a
--- /dev/null
+++ b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/NettyClientServerHttp2cTest.java
@@ -0,0 +1,47 @@
+/**
+ * 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.http2.netty;
+
+import org.apache.cxf.jaxrs.model.AbstractResourceInfo;
+
+import org.junit.BeforeClass;
+
+import static org.junit.Assert.assertTrue;
+
+public class NettyClientServerHttp2cTest extends AbstractNettyClientServerHttp2Test {
+    private static final String PORT = BookServerHttp2c.PORT;
+
+    @BeforeClass
+    public static void startServers() throws Exception {
+        AbstractResourceInfo.clearAllMaps();
+        assertTrue("server did not launch correctly", launchServer(new BookServerHttp2c()));
+        createStaticBus();
+    }
+
+    @Override
+    protected String getAddress() {
+        return "http://localhost:" + PORT;
+    }
+    
+    @Override
+    protected String getContext() {
+        return "/http2";
+    }
+}
diff --git a/systests/transport-netty/src/test/resources/org/apache/cxf/systest/http2_netty/server-tls.xml b/systests/transport-netty/src/test/resources/org/apache/cxf/systest/http2_netty/server-tls.xml
new file mode 100644
index 0000000..dd9ebf7
--- /dev/null
+++ b/systests/transport-netty/src/test/resources/org/apache/cxf/systest/http2_netty/server-tls.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:http-netty="http://cxf.apache.org/transports/http-netty-server/configuration"
+    xmlns:sec="http://cxf.apache.org/configuration/security"
+    xsi:schemaLocation="http://cxf.apache.org/transports/http-netty-server/configuration 
+        http://cxf.apache.org/schemas/configuration/http-netty-server.xsd 
+        http://www.springframework.org/schema/beans 
+        http://www.springframework.org/schema/beans/spring-beans.xsd
+        http://cxf.apache.org/configuration/security 
+        http://cxf.apache.org/schemas/configuration/security.xsd">
+    <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"/>
+    <http-netty:engine-factory bus="cxf">
+        <http-netty:engine port="${testutil.ports.org.apache.cxf.systest.http2.netty.BookServerHttp2}">
+            <http-netty:tlsServerParameters>
+                <sec:keyManagers keyPassword="password">
+                    <sec:keyStore type="jks" password="password" resource="keys/Bethal.jks"/>
+                </sec:keyManagers>
+                <sec:clientAuthentication want="false" required="false"/>
+            </http-netty:tlsServerParameters>
+        </http-netty:engine>
+    </http-netty:engine-factory>
+</beans>
\ No newline at end of file
diff --git a/systests/transport-netty/src/test/resources/org/apache/cxf/systest/http2_netty/server.xml b/systests/transport-netty/src/test/resources/org/apache/cxf/systest/http2_netty/server.xml
new file mode 100644
index 0000000..5ff63d1
--- /dev/null
+++ b/systests/transport-netty/src/test/resources/org/apache/cxf/systest/http2_netty/server.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:http-netty="http://cxf.apache.org/transports/http-netty-server/configuration"
+    xsi:schemaLocation="http://cxf.apache.org/transports/http-netty-server/configuration 
+        http://cxf.apache.org/schemas/configuration/http-netty-server.xsd 
+        http://www.springframework.org/schema/beans 
+        http://www.springframework.org/schema/beans/spring-beans.xsd">
+    <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"/>
+    <http-netty:engine-factory bus="cxf">
+        <http-netty:engine port="${testutil.ports.org.apache.cxf.systest.http2.netty.BookServerHttp2c}">
+        </http-netty:engine>
+    </http-netty:engine-factory>
+</beans>
\ No newline at end of file
diff --git a/systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/AbstractBookServerHttp2.java b/systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/AbstractBookServerHttp2.java
new file mode 100644
index 0000000..e6601db
--- /dev/null
+++ b/systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/AbstractBookServerHttp2.java
@@ -0,0 +1,66 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.systest.http_undertow.http2;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.customer.book.Book;
+import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
+import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
+import org.apache.cxf.jaxrs.provider.StreamingResponseProvider;
+import org.apache.cxf.systest.http_undertow.websocket.BookStorePerRequest;
+import org.apache.cxf.systest.http_undertow.websocket.BookStoreWebSocket;
+import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
+import org.apache.cxf.transport.http.HttpServerEngineSupport;
+
+abstract class AbstractBookServerHttp2 extends AbstractBusTestServerBase {
+    org.apache.cxf.endpoint.Server server;
+
+    private final String port;
+    private final String scheme;
+    private final String context;
+
+    AbstractBookServerHttp2(String port, String context, String scheme) {
+        this.port = port;
+        this.context = context;
+        this.scheme = scheme;
+    }
+
+    protected void run() {
+        SpringBusFactory factory = new SpringBusFactory();
+        Bus bus = factory.createBus(context);
+        bus.setProperty(HttpServerEngineSupport.ENABLE_HTTP2, true);
+        setBus(bus);
+        JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
+        sf.setBus(bus);
+        sf.setResourceClasses(BookStoreWebSocket.class, BookStorePerRequest.class);
+        sf.setProvider(new StreamingResponseProvider<Book>());
+        sf.setResourceProvider(BookStoreWebSocket.class,
+            new SingletonResourceProvider(new BookStoreWebSocket(), true));
+        sf.setAddress(scheme + "://localhost:" + port + "/http2");
+        server = sf.create();
+    }
+
+    public void tearDown() throws Exception {
+        server.stop();
+        server.destroy();
+        server = null;
+    }
+}
diff --git a/systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/AbstractUndertowClientServerHttp2Test.java b/systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/AbstractUndertowClientServerHttp2Test.java
new file mode 100644
index 0000000..c3b3470
--- /dev/null
+++ b/systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/AbstractUndertowClientServerHttp2Test.java
@@ -0,0 +1,120 @@
+/**
+ * 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.http_undertow.http2;
+
+import javax.ws.rs.core.Response;
+
+import org.apache.cxf.configuration.jsse.TLSClientParameters;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
+import org.apache.cxf.transport.http.HTTPConduit;
+import org.apache.cxf.transport.https.InsecureTrustManager;
+
+import io.undertow.client.ClientResponse;
+import io.undertow.util.Protocols;
+
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+abstract class AbstractUndertowClientServerHttp2Test extends AbstractBusClientServerTestBase {
+    @Test
+    public void testBookNotFoundWithHttp2() throws Exception {
+        final Http2TestClient client = new Http2TestClient(isSecure());
+        
+        final ClientResponse response = client
+            .request(getAddress())
+            .accept("text/plain")
+            .path(getContext() + "/web/bookstore/notFound")
+            .http2()
+            .get();
+        
+        assertThat(response.getResponseCode(), equalTo(404));
+        assertThat(response.getProtocol(), equalTo(Protocols.HTTP_2_0));
+    }
+    
+    @Test
+    public void testBookWithHttp2() throws Exception {
+        final Http2TestClient client = new Http2TestClient(isSecure());
+        
+        final ClientResponse response = client
+            .request(getAddress())
+            .accept("text/plain")
+            .path(getContext() + "/web/bookstore/booknames")
+            .http2()
+            .get();
+        
+        assertThat(response.getResponseCode(), equalTo(200));
+        assertThat(response.getProtocol(), equalTo(Protocols.HTTP_2_0));
+        assertEquals("CXF in Action", client.getBody(response));
+    }
+
+    @Test
+    public void testGetBookStreamHttp2() throws Exception {
+        final Http2TestClient client = new Http2TestClient(isSecure());
+        
+        final ClientResponse response = client
+            .request(getAddress())
+            .accept("application/json")
+            .path(getContext() + "/web/bookstore/bookstream")
+            .http2()
+            .get();
+
+        assertThat(response.getResponseCode(), equalTo(200));
+        assertThat(response.getProtocol(), equalTo(Protocols.HTTP_2_0));
+        assertEquals("{\"Book\":{\"id\":1,\"name\":\"WebSocket1\"}}", 
+            client.getBody(response));
+    }
+
+    @Test
+    public void testBookWithHttp() throws Exception {
+        final WebClient wc = WebClient
+            .create(getAddress() + getContext() + "/web/bookstore/booknames")
+            .accept("text/plain");
+        
+        if (isSecure()) {
+            final HTTPConduit conduit = WebClient.getConfig(wc).getHttpConduit();
+            TLSClientParameters params = conduit.getTlsClientParameters();
+
+            if (params == null)  {
+                params = new TLSClientParameters();
+                conduit.setTlsClientParameters(params);
+            }
+
+            // Create TrustManager instance which trusts all clients and servers
+            params.setTrustManagers(InsecureTrustManager.getNoOpX509TrustManagers()); 
+            params.setDisableCNCheck(true);
+        }
+        
+        try (Response resp = wc.get()) {
+            assertThat(resp.getStatus(), equalTo(200));
+            assertEquals("CXF in Action", resp.readEntity(String.class));
+        }
+    }
+
+    protected abstract String getAddress();
+    protected abstract String getContext();
+
+    protected boolean isSecure() {
+        return getAddress().startsWith("https");
+    }
+}
diff --git a/systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/BookServerHttp2.java b/systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/BookServerHttp2.java
new file mode 100644
index 0000000..a1f7872c
--- /dev/null
+++ b/systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/BookServerHttp2.java
@@ -0,0 +1,45 @@
+/**
+ * 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.http_undertow.http2;
+
+public class BookServerHttp2 extends AbstractBookServerHttp2 {
+    public static final String PORT = allocatePort(BookServerHttp2.class);
+
+    public BookServerHttp2() {
+        this(PORT);
+    }
+
+    public BookServerHttp2(String port) {
+        super(port, "org/apache/cxf/systest/http_undertow/http2/server-tls.xml", "https");
+    }
+
+    public static void main(String[] args) {
+        try {
+            BookServerHttp2 s = new BookServerHttp2();
+            s.start();
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            System.exit(-1);
+        } finally {
+            System.out.println("done!");
+        }
+    }
+
+}
diff --git a/systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/BookServerHttp2c.java b/systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/BookServerHttp2c.java
new file mode 100644
index 0000000..d3e02b4
--- /dev/null
+++ b/systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/BookServerHttp2c.java
@@ -0,0 +1,45 @@
+/**
+ * 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.http_undertow.http2;
+
+public class BookServerHttp2c extends AbstractBookServerHttp2 {
+    public static final String PORT = allocatePort(BookServerHttp2c.class);
+
+    public BookServerHttp2c() {
+        this(PORT);
+    }
+
+    public BookServerHttp2c(String port) {
+        super(port, "org/apache/cxf/systest/http_undertow/http2/server.xml", "http");
+    }
+
+    public static void main(String[] args) {
+        try {
+            BookServerHttp2c s = new BookServerHttp2c();
+            s.start();
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            System.exit(-1);
+        } finally {
+            System.out.println("done!");
+        }
+    }
+
+}
diff --git a/systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/Http2TestClient.java b/systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/Http2TestClient.java
new file mode 100644
index 0000000..6d8ed7d
--- /dev/null
+++ b/systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/Http2TestClient.java
@@ -0,0 +1,184 @@
+/**
+ * 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.http_undertow.http2;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.concurrent.CompletableFuture;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
+import javax.ws.rs.core.MediaType;
+
+import org.apache.cxf.transport.https.InsecureTrustManager;
+import org.xnio.IoUtils;
+import org.xnio.OptionMap;
+import org.xnio.Options;
+import org.xnio.Xnio;
+import org.xnio.XnioWorker;
+
+import io.undertow.UndertowOptions;
+import io.undertow.client.ClientCallback;
+import io.undertow.client.ClientConnection;
+import io.undertow.client.ClientExchange;
+import io.undertow.client.ClientRequest;
+import io.undertow.client.ClientResponse;
+import io.undertow.client.UndertowClient;
+import io.undertow.connector.ByteBufferPool;
+import io.undertow.protocols.ssl.UndertowXnioSsl;
+import io.undertow.server.DefaultByteBufferPool;
+import io.undertow.util.AttachmentKey;
+import io.undertow.util.Headers;
+import io.undertow.util.HttpString;
+import io.undertow.util.Methods;
+import io.undertow.util.StringReadChannelListener;
+
+/**
+ * TODO: Use CXF client once https://issues.apache.org/jira/browse/CXF-8606 is dones
+ */
+public class Http2TestClient {
+    private static final int BUFFER_SIZE = Integer.getInteger("test.bufferSize", 1024 * 16 - 20);
+    private static final AttachmentKey<String> RESPONSE_BODY = AttachmentKey.create(String.class);
+    
+    private final UndertowClient client;
+    private final UndertowXnioSsl ssl;
+    private final XnioWorker worker;
+    private final ByteBufferPool pool;
+    
+    public Http2TestClient(boolean secure) throws Exception {
+        client = UndertowClient.getInstance();
+        
+        final Xnio xnio = Xnio.getInstance();
+        worker = xnio.createWorker(null,  
+            OptionMap.builder()
+                .set(Options.WORKER_IO_THREADS, 8)
+                .set(Options.TCP_NODELAY, true)
+                .set(Options.KEEP_ALIVE, true)
+                .set(Options.WORKER_NAME, "TestClient")
+                .getMap());
+        
+        pool = new DefaultByteBufferPool(true, BUFFER_SIZE, 1000, 10, 100);
+        if (secure) {
+            final SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
+            sslContext.init(new KeyManager[] {}, InsecureTrustManager.getNoOpX509TrustManagers(), null);
+            ssl = new UndertowXnioSsl(xnio, OptionMap.EMPTY, sslContext);
+        } else {
+            ssl = null;
+        }
+    }
+    
+    public class RequestBuilder {
+        private final String address;
+        private String path = "";
+        private String accept = MediaType.WILDCARD;
+        private OptionMap options = OptionMap.EMPTY;
+
+        public RequestBuilder(final String address) {
+            this.address = address;
+        }
+        
+        public RequestBuilder path(final String p) {
+            this.path = p;
+            return this;
+        }
+        
+        
+        public RequestBuilder accept(final String a) {
+            this.accept = a;
+            return this;
+        }
+        
+        public RequestBuilder http2() {
+            options = OptionMap.create(UndertowOptions.ENABLE_HTTP2, true);
+            return this;
+        }
+        
+        public ClientResponse get() throws IOException {
+            return request(address, path, options, Methods.GET, accept);
+        }
+    }
+    
+    public RequestBuilder request(final String address) throws IOException {
+        return new RequestBuilder(address);
+    }
+
+    public ClientResponse request(final String address, final String path, final OptionMap options,
+            final HttpString method, final String accept) throws IOException {
+
+        final ClientConnection connection = client
+            .connect(URI.create(address), worker, ssl, pool, options)
+            .get();
+        
+        try {
+            final ClientRequest request = new ClientRequest()
+                .setMethod(method)
+                .setPath(path);
+
+            request.getRequestHeaders().put(Headers.ACCEPT, accept);
+            request.getRequestHeaders().put(Headers.HOST, "localhost");
+            
+            final CompletableFuture<ClientResponse> future = new CompletableFuture<ClientResponse>();
+            connection.sendRequest(request, createClientCallback(future));
+            return future.join();
+        } finally {
+            IoUtils.safeClose(connection);
+        }
+    }
+
+    private ClientCallback<ClientExchange> createClientCallback(final CompletableFuture<ClientResponse> future) {
+        return new ClientCallback<ClientExchange>() {
+            @Override
+            public void completed(ClientExchange result) {
+                result.setResponseListener(new ClientCallback<ClientExchange>() {
+                    @Override
+                    public void completed(final ClientExchange result) {
+                        new StringReadChannelListener(result.getConnection().getBufferPool()) {
+                            @Override
+                            protected void stringDone(String string) {
+                                result.getResponse().putAttachment(RESPONSE_BODY, string);
+                                future.complete(result.getResponse());
+                            }
+
+                            @Override
+                            protected void error(IOException e) {
+                                future.completeExceptionally(e);
+                            }
+                        }.setup(result.getResponseChannel());
+                    }
+
+                    @Override
+                    public void failed(IOException e) {
+                        future.completeExceptionally(e);
+                    }
+                });
+            }
+
+            @Override
+            public void failed(IOException e) {
+                future.completeExceptionally(e);
+            }
+        };
+    }
+
+    public String getBody(ClientResponse response) {
+        return response.getAttachment(RESPONSE_BODY);
+    }
+
+}
diff --git a/systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/UndertowClientServerHttp2Test.java b/systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/UndertowClientServerHttp2Test.java
new file mode 100644
index 0000000..1babfdc
--- /dev/null
+++ b/systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/UndertowClientServerHttp2Test.java
@@ -0,0 +1,48 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.systest.http_undertow.http2;
+
+
+import org.apache.cxf.jaxrs.model.AbstractResourceInfo;
+
+import org.junit.BeforeClass;
+
+import static org.junit.Assert.assertTrue;
+
+public class UndertowClientServerHttp2Test extends AbstractUndertowClientServerHttp2Test {
+    private static final String PORT = BookServerHttp2.PORT;
+
+    @BeforeClass
+    public static void startServers() throws Exception {
+        AbstractResourceInfo.clearAllMaps();
+        assertTrue("server did not launch correctly", launchServer(new BookServerHttp2()));
+        createStaticBus();
+    }
+
+    @Override
+    protected String getAddress() {
+        return "https://localhost:" + PORT;
+    }
+    
+    @Override
+    protected String getContext() {
+        return "/http2";
+    }
+}
diff --git a/systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/UndertowClientServerHttp2cTest.java b/systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/UndertowClientServerHttp2cTest.java
new file mode 100644
index 0000000..b5b752d
--- /dev/null
+++ b/systests/transport-undertow/src/test/java/org/apache/cxf/systest/http_undertow/http2/UndertowClientServerHttp2cTest.java
@@ -0,0 +1,48 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.systest.http_undertow.http2;
+
+
+import org.apache.cxf.jaxrs.model.AbstractResourceInfo;
+
+import org.junit.BeforeClass;
+
+import static org.junit.Assert.assertTrue;
+
+public class UndertowClientServerHttp2cTest extends AbstractUndertowClientServerHttp2Test {
+    private static final String PORT = BookServerHttp2c.PORT;
+
+    @BeforeClass
+    public static void startServers() throws Exception {
+        AbstractResourceInfo.clearAllMaps();
+        assertTrue("server did not launch correctly", launchServer(new BookServerHttp2c()));
+        createStaticBus();
+    }
+
+    @Override
+    protected String getAddress() {
+        return "http://localhost:" + PORT;
+    }
+    
+    @Override
+    protected String getContext() {
+        return "/http2";
+    }
+}
diff --git a/systests/transport-undertow/src/test/resources/org/apache/cxf/systest/http_undertow/http2/server-tls.xml b/systests/transport-undertow/src/test/resources/org/apache/cxf/systest/http_undertow/http2/server-tls.xml
new file mode 100644
index 0000000..cbd3a67
--- /dev/null
+++ b/systests/transport-undertow/src/test/resources/org/apache/cxf/systest/http_undertow/http2/server-tls.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:http-undertow="http://cxf.apache.org/transports/http-undertow/configuration"
+    xmlns:sec="http://cxf.apache.org/configuration/security"
+    xsi:schemaLocation="http://cxf.apache.org/transports/http-undertow/configuration 
+        http://cxf.apache.org/schemas/configuration/http-undertow.xsd 
+        http://www.springframework.org/schema/beans 
+        http://www.springframework.org/schema/beans/spring-beans.xsd
+        http://cxf.apache.org/configuration/security 
+        http://cxf.apache.org/schemas/configuration/security.xsd">
+    <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"/>
+    <http-undertow:engine-factory bus="cxf">
+        <http-undertow:engine port="${testutil.ports.org.apache.cxf.systest.http_undertow.http2.BookServerHttp2}">
+            <http-undertow:tlsServerParameters>
+                <sec:keyManagers keyPassword="password">
+                    <sec:keyStore type="jks" password="password" resource="keys/Bethal.jks"/>
+                </sec:keyManagers>
+                <sec:clientAuthentication want="false" required="false"/>
+            </http-undertow:tlsServerParameters>
+        </http-undertow:engine>
+    </http-undertow:engine-factory>
+</beans>
\ No newline at end of file
diff --git a/systests/transport-undertow/src/test/resources/org/apache/cxf/systest/http_undertow/http2/server.xml b/systests/transport-undertow/src/test/resources/org/apache/cxf/systest/http_undertow/http2/server.xml
new file mode 100644
index 0000000..a35af1a
--- /dev/null
+++ b/systests/transport-undertow/src/test/resources/org/apache/cxf/systest/http_undertow/http2/server.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:http-undertow="http://cxf.apache.org/transports/http-undertow/configuration"
+    xsi:schemaLocation="http://cxf.apache.org/transports/http-undertow/configuration 
+        http://cxf.apache.org/schemas/configuration/http-undertow.xsd 
+        http://www.springframework.org/schema/beans 
+        http://www.springframework.org/schema/beans/spring-beans.xsd">
+    <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"/>
+    <http-undertow:engine-factory bus="cxf">
+        <http-undertow:engine port="${testutil.ports.org.apache.cxf.systest.http_undertow.http2.BookServerHttp2c}">
+        </http-undertow:engine>
+    </http-undertow:engine-factory>
+</beans>
\ No newline at end of file
diff --git a/systests/transports/pom.xml b/systests/transports/pom.xml
index 1c7a9a0..94f3d55 100644
--- a/systests/transports/pom.xml
+++ b/systests/transports/pom.xml
@@ -331,10 +331,66 @@
             <version>${cxf.bcprov.version}</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty.http2</groupId>
+            <artifactId>http2-server</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-alpn-server</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty.http2</groupId>
+            <artifactId>http2-client</artifactId>
+            <version>${cxf.jetty9.version}</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <profiles>
         <profile>
+            <id>jdk8</id>
+            <activation>
+                <jdk>1.8</jdk>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-alpn-openjdk8-server</artifactId>
+                    <version>${cxf.jetty9.version}</version>
+                    <scope>test</scope>
+                </dependency>
+                <dependency>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-alpn-openjdk8-client</artifactId>
+                    <version>${cxf.jetty9.version}</version>
+                    <scope>test</scope>
+                </dependency>
+            </dependencies>
+        </profile>
+        <profile>
+            <id>jdk9+</id>
+            <activation>
+                <jdk>[9,)</jdk>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-alpn-java-server</artifactId>
+                    <version>${cxf.jetty9.version}</version>
+                    <scope>test</scope>
+                </dependency>
+                <dependency>
+                    <groupId>org.eclipse.jetty</groupId>
+                    <artifactId>jetty-alpn-java-client</artifactId>
+                    <version>${cxf.jetty9.version}</version>
+                    <scope>test</scope>
+                </dependency>
+            </dependencies>
+        </profile>
+        <profile>
             <id>jdk16</id>
             <activation>
                 <jdk>[16,)</jdk>
diff --git a/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/AbstractBookServerHttp2.java b/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/AbstractBookServerHttp2.java
new file mode 100644
index 0000000..83d999b
--- /dev/null
+++ b/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/AbstractBookServerHttp2.java
@@ -0,0 +1,64 @@
+/**
+ * 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.http2_jetty;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.customer.book.Book;
+import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
+import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
+import org.apache.cxf.jaxrs.provider.StreamingResponseProvider;
+import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
+import org.apache.cxf.transport.http.HttpServerEngineSupport;
+
+abstract class AbstractBookServerHttp2 extends AbstractBusTestServerBase {
+    org.apache.cxf.endpoint.Server server;
+
+    private final String port;
+    private final String context;
+    private final String scheme;
+
+    AbstractBookServerHttp2(String port, String context, String scheme) {
+        this.port = port;
+        this.context = context;
+        this.scheme = scheme;
+    }
+
+    protected void run() {
+        SpringBusFactory factory = new SpringBusFactory();
+        Bus bus = factory.createBus(context);
+        bus.setProperty(HttpServerEngineSupport.ENABLE_HTTP2, true);
+        setBus(bus);
+        JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
+        sf.setBus(bus);
+        sf.setResourceClasses(BookStore.class);
+        sf.setProvider(new StreamingResponseProvider<Book>());
+        sf.setResourceProvider(BookStore.class,
+            new SingletonResourceProvider(new BookStore(), true));
+        sf.setAddress(scheme + "://localhost:" + port + "/http2");
+        server = sf.create();
+    }
+
+    public void tearDown() throws Exception {
+        server.stop();
+        server.destroy();
+        server = null;
+    }
+}
diff --git a/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/AbstractJettyClientServerHttp2Test.java b/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/AbstractJettyClientServerHttp2Test.java
new file mode 100644
index 0000000..08eba61
--- /dev/null
+++ b/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/AbstractJettyClientServerHttp2Test.java
@@ -0,0 +1,119 @@
+/**
+ * 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.http2_jetty;
+
+import javax.ws.rs.core.Response;
+
+import org.apache.cxf.configuration.jsse.TLSClientParameters;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.systest.http2_jetty.Http2TestClient.ClientResponse;
+import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
+import org.apache.cxf.transport.http.HTTPConduit;
+import org.apache.cxf.transport.https.InsecureTrustManager;
+import org.eclipse.jetty.http.HttpVersion;
+
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+abstract class AbstractJettyClientServerHttp2Test extends AbstractBusClientServerTestBase {
+    @Test
+    public void testBookNotFoundWithHttp2() throws Exception {
+        final Http2TestClient client = new Http2TestClient(isSecure());
+        
+        final ClientResponse response = client
+            .request(getAddress())
+            .accept("text/plain")
+            .path(getContext() + "/web/bookstore/notFound")
+            .http2()
+            .get();
+        
+        assertThat(response.getResponseCode(), equalTo(404));
+        assertThat(response.getProtocol(), equalTo(HttpVersion.HTTP_2));
+    }
+
+    @Test
+    public void testBookWithHttp2() throws Exception {
+        final Http2TestClient client = new Http2TestClient(isSecure());
+        
+        final ClientResponse response = client
+            .request(getAddress())
+            .accept("text/plain")
+            .path(getContext() + "/web/bookstore/booknames")
+            .http2()
+            .get();
+        
+        assertThat(response.getResponseCode(), equalTo(200));
+        assertThat(response.getProtocol(), equalTo(HttpVersion.HTTP_2));
+        assertEquals("CXF in Action", response.getBody());
+    }
+
+    @Test
+    public void testGetBookStreamHttp2() throws Exception {
+        final Http2TestClient client = new Http2TestClient(isSecure());
+        
+        final ClientResponse response = client
+            .request(getAddress())
+            .accept("application/xml")
+            .path(getContext() + "/web/bookstore/bookstream")
+            .http2()
+            .get();
+
+        assertThat(response.getResponseCode(), equalTo(200));
+        assertThat(response.getProtocol(), equalTo(HttpVersion.HTTP_2));
+        assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
+            + "<Book><id>1</id><name>Book1</name></Book>", response.getBody());
+    }
+
+    @Test
+    public void testBookWithHttp() throws Exception {
+        final WebClient wc = WebClient
+            .create(getAddress() + getContext() + "/web/bookstore/booknames")
+            .accept("text/plain");
+        
+        if (isSecure()) {
+            final HTTPConduit conduit = WebClient.getConfig(wc).getHttpConduit();
+            TLSClientParameters params = conduit.getTlsClientParameters();
+
+            if (params == null)  {
+                params = new TLSClientParameters();
+                conduit.setTlsClientParameters(params);
+            }
+
+            // Create TrustManager instance which trusts all clients and servers
+            params.setTrustManagers(InsecureTrustManager.getNoOpX509TrustManagers()); 
+            params.setDisableCNCheck(true);
+        }
+        
+        try (Response resp = wc.get()) {
+            assertThat(resp.getStatus(), equalTo(200));
+            assertEquals("CXF in Action", resp.readEntity(String.class));
+        }
+    }
+
+    protected abstract String getAddress();
+    protected abstract String getContext();
+
+    protected boolean isSecure() {
+        return getAddress().startsWith("https");
+    }
+}
\ No newline at end of file
diff --git a/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/Book.java b/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/Book.java
new file mode 100644
index 0000000..fd80aac
--- /dev/null
+++ b/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/Book.java
@@ -0,0 +1,69 @@
+/**
+ * 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.http2_jetty;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
+import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
+
+@JsonTypeInfo(use = Id.CLASS, include = As.PROPERTY, property = "class")
+@XmlRootElement(name = "Book")
+public class Book {
+    private String name;
+    private long id;
+
+    public Book() {
+    }
+
+    public Book(String name, long id) {
+        this.name = name;
+        this.id = id;
+    }
+
+    public void setName(String n) {
+        name = n;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setId(long i) {
+        id = i;
+    }
+    public long getId() {
+        return id;
+    }
+
+    @PUT
+    public void cloneState(Book book) {
+        id = book.getId();
+        name = book.getName();
+    }
+
+    @GET
+    public Book retrieveState() {
+        return this;
+    }
+}
diff --git a/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/BookServerHttp2.java b/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/BookServerHttp2.java
new file mode 100644
index 0000000..1980e96
--- /dev/null
+++ b/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/BookServerHttp2.java
@@ -0,0 +1,47 @@
+/**
+ * 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.http2_jetty;
+
+public class BookServerHttp2 extends AbstractBookServerHttp2 {
+    public static final String PORT = allocatePort(BookServerHttp2.class);
+
+    org.apache.cxf.endpoint.Server server;
+
+    public BookServerHttp2() {
+        this(PORT);
+    }
+
+    public BookServerHttp2(String port) {
+        super(port, "org/apache/cxf/systest/http2_jetty/server-tls.xml", "https");
+    }
+
+    public static void main(String[] args) {
+        try {
+            BookServerHttp2 s = new BookServerHttp2();
+            s.start();
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            System.exit(-1);
+        } finally {
+            System.out.println("done!");
+        }
+    }
+
+}
diff --git a/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/BookServerHttp2c.java b/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/BookServerHttp2c.java
new file mode 100644
index 0000000..74d7303
--- /dev/null
+++ b/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/BookServerHttp2c.java
@@ -0,0 +1,45 @@
+/**
+ * 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.http2_jetty;
+
+public class BookServerHttp2c extends AbstractBookServerHttp2 {
+    public static final String PORT = allocatePort(BookServerHttp2c.class);
+
+    public BookServerHttp2c() {
+        this(PORT);
+    }
+
+    public BookServerHttp2c(String port) {
+        super(port, "org/apache/cxf/systest/http2_jetty/server.xml", "http");
+    }
+
+    public static void main(String[] args) {
+        try {
+            BookServerHttp2c s = new BookServerHttp2c();
+            s.start();
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            System.exit(-1);
+        } finally {
+            System.out.println("done!");
+        }
+    }
+
+}
diff --git a/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/BookStore.java b/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/BookStore.java
new file mode 100644
index 0000000..5aa5bdd
--- /dev/null
+++ b/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/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.http2_jetty;
+
+import java.io.IOException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+import org.apache.cxf.jaxrs.ext.StreamingResponse;
+
+@Path("/web/bookstore")
+public class BookStore {
+    private static ExecutorService executor = Executors.newSingleThreadExecutor();
+
+    @GET
+    @Path("/booknames")
+    @Produces("text/plain")
+    public byte[] getBookName() {
+        return "CXF in Action".getBytes();
+    }
+
+    @GET
+    @Path("/bookstream")
+    @Produces("application/xml")
+    public StreamingResponse<Book> getBookStream() {
+        return new StreamingResponse<Book>() {
+            public void writeTo(final StreamingResponse.Writer<Book> out) throws IOException {
+                out.write(new Book("Book1", 1));
+                executor.execute(new Runnable() {
+                    public void run() {
+                        try {
+                            for (int i = 2; i <= 5; i++) {
+                                Thread.sleep(500);
+                                out.write(new Book("Book" + i, i));
+                                out.getEntityStream().flush();
+                            }
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+                    }
+                });
+            }
+        };
+    }
+}
+
+
diff --git a/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/Http2TestClient.java b/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/Http2TestClient.java
new file mode 100644
index 0000000..70a388a
--- /dev/null
+++ b/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/Http2TestClient.java
@@ -0,0 +1,212 @@
+/**
+ * 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.http2_jetty;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import javax.ws.rs.ClientErrorException;
+import javax.ws.rs.core.MediaType;
+
+import org.eclipse.jetty.http.HttpFields;
+import org.eclipse.jetty.http.HttpHeader;
+import org.eclipse.jetty.http.HttpURI;
+import org.eclipse.jetty.http.HttpVersion;
+import org.eclipse.jetty.http.MetaData;
+import org.eclipse.jetty.http2.api.Session;
+import org.eclipse.jetty.http2.api.Stream;
+import org.eclipse.jetty.http2.api.server.ServerSessionListener;
+import org.eclipse.jetty.http2.client.HTTP2Client;
+import org.eclipse.jetty.http2.frames.DataFrame;
+import org.eclipse.jetty.http2.frames.HeadersFrame;
+import org.eclipse.jetty.util.Callback;
+import org.eclipse.jetty.util.FuturePromise;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+
+/**
+ * TODO: Use CXF client once https://issues.apache.org/jira/browse/CXF-8606 is dones
+ */
+public class Http2TestClient implements AutoCloseable {
+    private final HTTP2Client client;
+    private final SslContextFactory sslContextFactory;
+    
+    public Http2TestClient(boolean secure) throws Exception {
+        client = new HTTP2Client();
+        if (secure) {
+            sslContextFactory = new SslContextFactory.Client(true);
+            client.addBean(sslContextFactory);
+        } else {
+            sslContextFactory = null;
+        }
+        client.start();
+    }
+    
+    public static class ClientResponse {
+        private String body;
+        private HttpVersion protocol;
+        private int responseCode;
+
+        public void setBody(String body) {
+            this.body = body;
+        }
+        
+        public String getBody() {
+            return body;
+        }
+        
+        public void setResponseCode(int rc) {
+            this.responseCode = rc;
+        }
+
+        public int getResponseCode() {
+            return responseCode;
+        }
+
+        public HttpVersion getProtocol() {
+            return protocol;
+        }
+        
+        public void setProtocol(HttpVersion protocol) {
+            this.protocol = protocol;
+        }
+    }
+    
+    public class RequestBuilder {
+        private final String address;
+        private String path = "";
+        private String accept = MediaType.WILDCARD;
+        private HttpVersion version = HttpVersion.HTTP_1_1;
+
+        public RequestBuilder(final String address) {
+            this.address = address;
+        }
+        
+        public RequestBuilder path(final String p) {
+            this.path = p;
+            return this;
+        }
+        
+        
+        public RequestBuilder accept(final String a) {
+            this.accept = a;
+            return this;
+        }
+        
+        public RequestBuilder http2() {
+            version = HttpVersion.HTTP_2;
+            return this;
+        }
+        
+        public ClientResponse get() throws InterruptedException, ExecutionException, TimeoutException {
+            return request(address, path, version, "GET", accept);
+        }
+    }
+    
+    public RequestBuilder request(final String address) throws IOException {
+        return new RequestBuilder(address);
+    }
+
+    public ClientResponse request(final String address, final String path, 
+            final HttpVersion version, final String method, final String accept) 
+                throws InterruptedException, ExecutionException, TimeoutException {
+
+        final URI uri = URI.create(address);
+        final FuturePromise<Session> sessionPromise = new FuturePromise<>();
+
+        client.connect(sslContextFactory, new InetSocketAddress(uri.getHost(), uri.getPort()), 
+            new ServerSessionListener.Adapter(), sessionPromise);
+        final Session session = sessionPromise.get();
+
+        final HttpFields requestFields = new HttpFields();
+        requestFields.add(HttpHeader.ACCEPT, accept);
+        requestFields.add(HttpHeader.HOST, "localhost");
+
+        final MetaData.Request request = new MetaData.Request(method, new HttpURI(address + path), 
+            version, requestFields);
+
+        final CompletableFuture<ClientResponse> future = new CompletableFuture<>();
+        final Stream.Listener responseListener = new ResponseListener(future);
+        
+        final HeadersFrame headersFrame = new HeadersFrame(request, null, true);
+        session.newStream(headersFrame, new FuturePromise<>(), responseListener);
+        return future.get(5, TimeUnit.SECONDS);
+    }
+    
+    @Override
+    public void close() throws Exception {
+        client.stop();
+    }
+    
+    private final class ResponseListener extends Stream.Listener.Adapter {
+        private final ClientResponse response = new ClientResponse();
+        private final CompletableFuture<ClientResponse> future;
+        
+        ResponseListener(final CompletableFuture<ClientResponse> f) {
+            this.future = f;
+        }
+        
+        @Override
+        public void onHeaders(Stream stream, HeadersFrame frame) {
+            final MetaData metaData = frame.getMetaData();
+            response.setProtocol(metaData.getHttpVersion());
+            if (metaData.isResponse()) {
+                final int status = ((MetaData.Response)metaData).getStatus();
+                response.setResponseCode(status);
+                // Unsuccessful response
+                if (status >= 400) {
+                    future.complete(response);
+                }
+            }
+            super.onHeaders(stream, frame);
+        }
+        
+        @Override
+        public void onData(Stream stream, DataFrame frame, Callback callback) {
+            byte[] bytes = new byte[frame.getData().remaining()];
+            frame.getData().get(bytes);
+            response.setBody(new String(bytes));
+            future.complete(response);
+            super.onData(stream, frame, callback);
+        }
+        
+        @Override
+        public void onTimeout(Stream stream, Throwable x) {
+            future.completeExceptionally(x);
+            super.onTimeout(stream, x);
+        }
+        
+        @Override
+        public void onFailure(Stream stream, int error, String reason, Throwable failure, Callback callback) {
+            future.completeExceptionally(failure);
+            super.onFailure(stream, error, reason, failure, callback);
+        }
+        
+        @Override
+        public void onFailure(Stream stream, int error, String reason, Callback callback) {
+            future.completeExceptionally(new ClientErrorException(reason, error));
+            super.onFailure(stream, error, reason, callback);
+        }
+    }
+}
diff --git a/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/JettyClientServerHttp2Test.java b/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/JettyClientServerHttp2Test.java
new file mode 100644
index 0000000..a707024
--- /dev/null
+++ b/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/JettyClientServerHttp2Test.java
@@ -0,0 +1,48 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.systest.http2_jetty;
+
+import org.apache.cxf.jaxrs.model.AbstractResourceInfo;
+
+import org.junit.BeforeClass;
+
+import static org.junit.Assert.assertTrue;
+
+public class JettyClientServerHttp2Test extends AbstractJettyClientServerHttp2Test {
+    private static final String PORT = BookServerHttp2.PORT;
+
+    @BeforeClass
+    public static void startServers() throws Exception {
+        AbstractResourceInfo.clearAllMaps();
+        assertTrue("server did not launch correctly", launchServer(new BookServerHttp2()));
+        createStaticBus();
+    }
+
+    
+    @Override
+    protected String getAddress() {
+        return "https://localhost:" + PORT;
+    }
+    
+    @Override
+    protected String getContext() {
+        return "/http2";
+    }
+}
diff --git a/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/JettyClientServerHttp2cTest.java b/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/JettyClientServerHttp2cTest.java
new file mode 100644
index 0000000..805367c
--- /dev/null
+++ b/systests/transports/src/test/java/org/apache/cxf/systest/http2_jetty/JettyClientServerHttp2cTest.java
@@ -0,0 +1,47 @@
+/**
+ * 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.http2_jetty;
+
+import org.apache.cxf.jaxrs.model.AbstractResourceInfo;
+
+import org.junit.BeforeClass;
+
+import static org.junit.Assert.assertTrue;
+
+public class JettyClientServerHttp2cTest extends AbstractJettyClientServerHttp2Test {
+    private static final String PORT = BookServerHttp2c.PORT;
+
+    @BeforeClass
+    public static void startServers() throws Exception {
+        AbstractResourceInfo.clearAllMaps();
+        assertTrue("server did not launch correctly", launchServer(new BookServerHttp2c()));
+        createStaticBus();
+    }
+
+    @Override
+    protected String getAddress() {
+        return "http://localhost:" + PORT;
+    }
+    
+    @Override
+    protected String getContext() {
+        return "/http2";
+    }
+}
diff --git a/systests/transports/src/test/resources/org/apache/cxf/systest/http2_jetty/server-tls.xml b/systests/transports/src/test/resources/org/apache/cxf/systest/http2_jetty/server-tls.xml
new file mode 100644
index 0000000..5a0cba8
--- /dev/null
+++ b/systests/transports/src/test/resources/org/apache/cxf/systest/http2_jetty/server-tls.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:http-jetty="http://cxf.apache.org/transports/http-jetty/configuration"
+    xmlns:sec="http://cxf.apache.org/configuration/security"
+    xsi:schemaLocation="http://cxf.apache.org/transports/http-jetty/configuration 
+        http://cxf.apache.org/schemas/configuration/http-jetty.xsd 
+        http://www.springframework.org/schema/beans 
+        http://www.springframework.org/schema/beans/spring-beans.xsd
+        http://cxf.apache.org/configuration/security 
+        http://cxf.apache.org/schemas/configuration/security.xsd">
+    <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"/>
+    <http-jetty:engine-factory bus="cxf">
+        <http-jetty:engine port="${testutil.ports.org.apache.cxf.systest.http2_jetty.BookServerHttp2}">
+            <http-jetty:tlsServerParameters>
+                <sec:keyManagers keyPassword="password">
+                    <sec:keyStore type="jks" password="password" resource="keys/Bethal.jks"/>
+                </sec:keyManagers>
+                <sec:clientAuthentication want="false" required="false"/>
+            </http-jetty:tlsServerParameters>
+        </http-jetty:engine>
+    </http-jetty:engine-factory>
+</beans>
\ No newline at end of file
diff --git a/systests/transports/src/test/resources/org/apache/cxf/systest/http2_jetty/server.xml b/systests/transports/src/test/resources/org/apache/cxf/systest/http2_jetty/server.xml
new file mode 100644
index 0000000..c44bf1e
--- /dev/null
+++ b/systests/transports/src/test/resources/org/apache/cxf/systest/http2_jetty/server.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:http-jetty="http://cxf.apache.org/transports/http-jetty/configuration"
+    xsi:schemaLocation="http://cxf.apache.org/transports/http-jetty/configuration 
+        http://cxf.apache.org/schemas/configuration/http-jetty.xsd 
+        http://www.springframework.org/schema/beans 
+        http://www.springframework.org/schema/beans/spring-beans.xsd">
+    <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"/>
+    <http-jetty:engine-factory bus="cxf">
+        <http-jetty:engine port="${testutil.ports.org.apache.cxf.systest.http2_jetty.BookServerHttp2c}">
+        </http-jetty:engine>
+    </http-jetty:engine-factory>
+</beans>
\ No newline at end of file

[cxf] 03/05: CXF-8605: Introduce HTTP/2 Transport: server-side support. Fixing distribution/javadoc

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

reta pushed a commit to branch 3.4.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git

commit ca9bd0dad7228e8fe3d36c3f3f23900390a79d66
Author: Andriy Redko <dr...@gmail.com>
AuthorDate: Sat Oct 30 13:08:51 2021 -0400

     CXF-8605: Introduce HTTP/2 Transport: server-side support. Fixing distribution/javadoc
    
    (cherry picked from commit 2cdc999a227d6caf4c8712945eb841e86f93b1af)
---
 distribution/javadoc/pom.xml | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/distribution/javadoc/pom.xml b/distribution/javadoc/pom.xml
index 7e9ec19..f9666e0 100644
--- a/distribution/javadoc/pom.xml
+++ b/distribution/javadoc/pom.xml
@@ -368,6 +368,11 @@
             <version>${cxf.netty.version}</version>
         </dependency>
         <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-codec-http2</artifactId>
+            <version>${cxf.netty.version}</version>
+        </dependency>
+        <dependency>
             <groupId>jakarta.persistence</groupId>
             <artifactId>jakarta.persistence-api</artifactId>
             <version>${cxf.persistence-api.version}</version>
@@ -488,6 +493,14 @@
             <artifactId>jetty-plus</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.eclipse.jetty.http2</groupId>
+            <artifactId>http2-server</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-alpn-server</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.jacorb</groupId>
             <artifactId>jacorb</artifactId>
             <version>${cxf.jacorb.version}</version>

[cxf] 05/05: Recording .gitmergeinfo Changes

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

reta pushed a commit to branch 3.4.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git

commit 2d065f32c8aae68b4af8f99f098caab1541b1b5c
Author: Andriy Redko <dr...@gmail.com>
AuthorDate: Sat Oct 30 14:59:08 2021 -0400

    Recording .gitmergeinfo Changes
---
 .gitmergeinfo | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitmergeinfo b/.gitmergeinfo
index 3313902..5590902 100644
--- a/.gitmergeinfo
+++ b/.gitmergeinfo
@@ -176,6 +176,7 @@ M 906ce39eb6de0be51e0e8cc0ea0bd9f3a297cecf
 M 92db608461b62b76f2e9a52551361a75a4f2826d
 M 941ed53ce451b809809f8270b74aa546be681aa6
 M 954085421900efbf89643b5ab8f187a237e42eb4
+M 965e1bb9e9658f4024f33bf832308f8b8dfce4b6
 M 975fc9e2fe226ddb8dfa845bd9565839c7391e2a
 M 9980b0472524e1010aaf7a4a3fe5ff072270efe3
 M 9af4071d27e3f14876061ac067d64de7b43f11d1

[cxf] 02/05: CXF-8605: Introduce HTTP/2 Transport: server-side support. Fixing basic_http2_jetty/pom.xml

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

reta pushed a commit to branch 3.4.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git

commit 08d05f5005581b397f90b7b052f0377509a5caff
Author: Andriy Redko <dr...@gmail.com>
AuthorDate: Sat Oct 30 11:36:02 2021 -0400

    CXF-8605: Introduce HTTP/2 Transport: server-side support. Fixing basic_http2_jetty/pom.xml
    
    (cherry picked from commit cebab67e3f563518cab9e65d0523b61db0ae5023)
---
 .../samples/jax_rs/basic_http2_jetty/pom.xml       | 55 ++++++++++------------
 1 file changed, 26 insertions(+), 29 deletions(-)

diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/pom.xml b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/pom.xml
index 3691cd0..c112739 100644
--- a/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/pom.xml
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/pom.xml
@@ -75,35 +75,6 @@
                 </plugins>
             </build>
         </profile>
-    </profiles>
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.cxf</groupId>
-            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.cxf</groupId>
-            <artifactId>cxf-rt-transports-http-jetty</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-context</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.eclipse.jetty.http2</groupId>
-            <artifactId>http2-server</artifactId>
-            <version>${cxf.jetty9.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-alpn-server</artifactId>
-            <version>${cxf.jetty9.version}</version>
-        </dependency>
-    </dependencies>
-    
-    <profiles>
         <profile>
             <id>jdk8</id>
             <activation>
@@ -133,4 +104,30 @@
             </dependencies>
         </profile>
     </profiles>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-transports-http-jetty</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty.http2</groupId>
+            <artifactId>http2-server</artifactId>
+            <version>${cxf.jetty9.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-alpn-server</artifactId>
+            <version>${cxf.jetty9.version}</version>
+        </dependency>
+    </dependencies>
 </project>

[cxf] 04/05: CXF-8605: Introduce HTTP/2 Transport: server-side support. Fixing dependency scopes for jax_rs/basic_http2_jetty example

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

reta pushed a commit to branch 3.4.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git

commit 54ecc5e5686ab26a233d64ba17f8bf6360227732
Author: Andriy Redko <dr...@gmail.com>
AuthorDate: Sat Oct 30 14:46:36 2021 -0400

     CXF-8605: Introduce HTTP/2 Transport: server-side support. Fixing dependency scopes for jax_rs/basic_http2_jetty example
    
    (cherry picked from commit 18f42c66201573b67e1944671ad32b0001b1f8da)
---
 distribution/src/main/release/samples/jax_rs/basic_http2_jetty/pom.xml | 2 --
 1 file changed, 2 deletions(-)

diff --git a/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/pom.xml b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/pom.xml
index c112739..0806cfb 100644
--- a/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/pom.xml
+++ b/distribution/src/main/release/samples/jax_rs/basic_http2_jetty/pom.xml
@@ -85,7 +85,6 @@
                     <groupId>org.eclipse.jetty</groupId>
                     <artifactId>jetty-alpn-openjdk8-server</artifactId>
                     <version>${cxf.jetty9.version}</version>
-                    <scope>test</scope>
                 </dependency>
             </dependencies>
         </profile>
@@ -99,7 +98,6 @@
                     <groupId>org.eclipse.jetty</groupId>
                     <artifactId>jetty-alpn-java-server</artifactId>
                     <version>${cxf.jetty9.version}</version>
-                    <scope>test</scope>
                 </dependency>
             </dependencies>
         </profile>