CXF-7085: Introduce support for Server Sent Events (Client). Restructured SSE 
test cases to have separate modules for Tomcat and Jetty


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

Branch: refs/heads/master
Commit: 76877054e1a86220fe1a546acde9a12e7c63e10b
Parents: 1257780
Author: reta <drr...@gmail.com>
Authored: Sat Jun 24 13:13:14 2017 -0400
Committer: reta <drr...@gmail.com>
Committed: Sat Jun 24 13:13:14 2017 -0400

----------------------------------------------------------------------
 systests/rs-sse/pom.xml                         |  70 ++--------
 systests/rs-sse/rs-sse-base/pom.xml             |  53 ++++++++
 .../systest/jaxrs/sse/AbstractSseBaseTest.java  |  79 +++++++++++
 .../cxf/systest/jaxrs/sse/AbstractSseTest.java  | 136 +++++++++++++++++++
 .../org/apache/cxf/systest/jaxrs/sse/Book.java  |  71 ++++++++++
 .../apache/cxf/systest/jaxrs/sse/BookStore.java | 136 +++++++++++++++++++
 .../cxf/systest/jaxrs/sse/BookStore2.java       | 135 ++++++++++++++++++
 .../cxf/systest/jaxrs/sse/SseApplication.java   |  38 ++++++
 .../META-INF/cxf/org.apache.cxf.Logger          |   1 +
 .../main/resources/jaxrs_sse/WEB-INF/web.xml    |  28 ++++
 .../rs-sse-base/src/main/resources/logback.xml  |  12 ++
 systests/rs-sse/rs-sse-jetty/pom.xml            |  70 ++++++++++
 .../jaxrs/sse/jetty/AbstractJettyServer.java    |  98 +++++++++++++
 .../jaxrs/sse/jetty/JettyEmbeddedTest.java      |  49 +++++++
 .../systest/jaxrs/sse/jetty/JettyWarTest.java   |  48 +++++++
 systests/rs-sse/rs-sse-tomcat/pom.xml           |  67 +++++++++
 .../jaxrs/sse/tomcat/AbstractTomcatServer.java  | 111 +++++++++++++++
 .../jaxrs/sse/tomcat/TomcatEmbeddedTest.java    |  49 +++++++
 .../systest/jaxrs/sse/tomcat/TomcatWarTest.java |  49 +++++++
 .../jaxrs/sse/AbstractBroadcasterSseTest.java   |  80 -----------
 .../systest/jaxrs/sse/AbstractSseBaseTest.java  |  79 -----------
 .../cxf/systest/jaxrs/sse/AbstractSseTest.java  |  87 ------------
 .../org/apache/cxf/systest/jaxrs/sse/Book.java  |  71 ----------
 .../apache/cxf/systest/jaxrs/sse/BookStore.java | 136 -------------------
 .../cxf/systest/jaxrs/sse/BookStore2.java       | 135 ------------------
 .../cxf/systest/jaxrs/sse/SseApplication.java   |  38 ------
 .../jaxrs/sse/jetty/AbstractJettyServer.java    |  98 -------------
 .../jaxrs/sse/jetty/JettyBroadcasterTest.java   |  49 -------
 .../jaxrs/sse/jetty/JettyEmbeddedTest.java      |  49 -------
 .../systest/jaxrs/sse/jetty/JettyWarTest.java   |  48 -------
 .../jaxrs/sse/tomcat/AbstractTomcatServer.java  | 111 ---------------
 .../jaxrs/sse/tomcat/TomcatBroadcasterTest.java |  51 -------
 .../jaxrs/sse/tomcat/TomcatEmbeddedTest.java    |  49 -------
 .../systest/jaxrs/sse/tomcat/TomcatWarTest.java |  49 -------
 .../META-INF/cxf/org.apache.cxf.Logger          |   1 -
 .../test/resources/jaxrs_sse/WEB-INF/web.xml    |  28 ----
 systests/rs-sse/src/test/resources/logback.xml  |  12 --
 37 files changed, 1241 insertions(+), 1230 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/pom.xml
----------------------------------------------------------------------
diff --git a/systests/rs-sse/pom.xml b/systests/rs-sse/pom.xml
index ce8c56d..c24dd79 100644
--- a/systests/rs-sse/pom.xml
+++ b/systests/rs-sse/pom.xml
@@ -27,40 +27,15 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.apache.cxf.systests</groupId>
     <artifactId>cxf-systests-rs-sse</artifactId>
+    <packaging>pom</packaging>
     <name>Apache CXF SSE Integration System Tests</name>
     <description>Apache CXF SSE Integration System Tests</description>
     <url>http://cxf.apache.org</url>
-    <properties>
-        <cxf.jetty.version>${cxf.jetty9.version}</cxf.jetty.version>
-        <cxf.tomcat.version>8.0.32</cxf.tomcat.version>
-    </properties>
+    
     <dependencies>
         <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-annotations</artifactId>
-            <version>${cxf.jetty.version}</version>
-        </dependency>    
-        <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-server</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-plus</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.eclipse.jetty.websocket</groupId>
-            <artifactId>websocket-server</artifactId>
-            <version>${cxf.jetty.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-webapp</artifactId>
-        </dependency>
-        <dependency>
             <groupId>ch.qos.logback</groupId>
             <artifactId>logback-classic</artifactId>
-            <version>${cxf.logback.classic.version}</version>
             <scope>test</scope>
         </dependency>
         <dependency>
@@ -89,24 +64,8 @@
             <version>${project.version}</version>
         </dependency>
         <dependency>
-            <groupId>org.apache.tomcat.embed</groupId>
-            <artifactId>tomcat-embed-core</artifactId>
-            <version>${cxf.tomcat.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.tomcat.embed</groupId>
-            <artifactId>tomcat-embed-logging-juli</artifactId>
-            <version>${cxf.tomcat.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.tomcat</groupId>
-            <artifactId>tomcat-jasper</artifactId>
-            <version>${cxf.tomcat.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.cxf</groupId>
-            <artifactId>cxf-testutils</artifactId>
-            <version>${project.version}</version>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
@@ -116,25 +75,11 @@
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.fasterxml.jackson.jaxrs</groupId>
-            <artifactId>jackson-jaxrs-json-provider</artifactId>
-        </dependency>
-        <dependency>
             <groupId>org.apache.httpcomponents</groupId>
             <artifactId>httpclient</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-lang3</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
             <groupId>com.ning</groupId>
             <artifactId>async-http-client</artifactId>
             <version>${cxf.ahc.version}</version>
@@ -147,6 +92,7 @@
             </exclusions>
         </dependency>
     </dependencies>
+    
     <build>
         <plugins>
             <plugin>
@@ -162,4 +108,10 @@
             </plugin>
         </plugins>
     </build>
+    
+    <modules>
+        <module>rs-sse-base</module>
+        <module>rs-sse-tomcat</module>
+        <module>rs-sse-jetty</module>
+    </modules>
 </project>

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/rs-sse-base/pom.xml
----------------------------------------------------------------------
diff --git a/systests/rs-sse/rs-sse-base/pom.xml 
b/systests/rs-sse/rs-sse-base/pom.xml
new file mode 100644
index 0000000..c431bd6
--- /dev/null
+++ b/systests/rs-sse/rs-sse-base/pom.xml
@@ -0,0 +1,53 @@
+<?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";>
+    <parent>
+        <groupId>org.apache.cxf.systests</groupId>
+        <artifactId>cxf-systests-rs-sse</artifactId>
+        <version>3.2.0-SNAPSHOT</version>
+        <relativePath>../</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>cxf-systests-rs-sse-base</artifactId>
+    <name>Apache CXF SSE Integration System Tests base classes</name>
+    <description>Apache CXF SSE Integration System base classes</description>
+    <url>http://cxf.apache.org</url>
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.jaxrs</groupId>
+            <artifactId>jackson-jaxrs-json-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-testutils</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/AbstractSseBaseTest.java
----------------------------------------------------------------------
diff --git 
a/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/AbstractSseBaseTest.java
 
b/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/AbstractSseBaseTest.java
new file mode 100644
index 0000000..87425b5
--- /dev/null
+++ 
b/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/AbstractSseBaseTest.java
@@ -0,0 +1,79 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.systest.jaxrs.sse;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
+
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
+
+public abstract class AbstractSseBaseTest extends 
AbstractBusClientServerTestBase {
+    private final ObjectMapper mapper = new ObjectMapper();
+
+    protected String toJson(final String name, final Integer id) throws 
JsonProcessingException {
+        return mapper.writeValueAsString(new Book(name, id));
+    }
+
+    protected WebClient createWebClient(final String url, final String media) {
+        final List< ? > providers = Arrays.asList(new JacksonJsonProvider());
+
+        final WebClient wc = WebClient
+            .create("http://localhost:"; + getPort() + url, providers)
+            .accept(media);
+
+        
WebClient.getConfig(wc).getHttpConduit().getClient().setReceiveTimeout(8000L);
+        return wc;
+    }
+
+    protected WebClient createWebClient(final String url) {
+        return createWebClient(url, MediaType.SERVER_SENT_EVENTS);
+    }
+
+    protected WebTarget createWebTarget(final String url) {
+        return ClientBuilder
+            .newClient()
+            .property("http.receive.timeout", 8000)
+            .register(JacksonJsonProvider.class)
+            .target("http://localhost:"; + getPort() + url);
+    }
+    
+    protected void awaitEvents(long timeout, final Collection<?> events, int 
size) throws InterruptedException {
+        final long sleep = timeout / 10;
+        
+        for (int i = 0; i < timeout; i += sleep) {
+            if (events.size() == size) {
+                break;
+            } else {
+                Thread.sleep(sleep);
+            }
+        }
+    }
+
+    protected abstract int getPort();
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/AbstractSseTest.java
----------------------------------------------------------------------
diff --git 
a/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/AbstractSseTest.java
 
b/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/AbstractSseTest.java
new file mode 100644
index 0000000..053bcb7
--- /dev/null
+++ 
b/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/AbstractSseTest.java
@@ -0,0 +1,136 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.systest.jaxrs.sse;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.UUID;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.sse.InboundSseEvent;
+import javax.ws.rs.sse.SseEventSource;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.hasItems;
+
+public abstract class AbstractSseTest extends AbstractSseBaseTest {
+    @Test
+    public void testBooksStreamIsReturnedFromLastEventId() throws 
InterruptedException {
+        final WebTarget target = createWebTarget("/rest/api/bookstore/sse/" + 
UUID.randomUUID())
+            .property(HttpHeaders.LAST_EVENT_ID_HEADER, 150);
+        final Collection<Book> books = new ArrayList<>();
+        
+        try (final SseEventSource eventSource = 
SseEventSource.target(target).build()) {
+            eventSource.register(collect(books), System.out::println);
+            eventSource.open();
+            // Give the SSE stream some time to collect all events
+            awaitEvents(3000, books, 4);
+        }
+
+        // Easing the test verification here, it does not work well for Atm + 
Jetty
+        assertThat(books, 
+            hasItems(
+                new Book("New Book #151", 151), 
+                new Book("New Book #152", 152), 
+                new Book("New Book #153", 153), 
+                new Book("New Book #154", 154)
+            )
+        );
+    }
+
+    @Test
+    public void testBooksStreamIsReturnedFromInboundSseEvents() throws 
InterruptedException {
+        final WebTarget target = createWebTarget("/rest/api/bookstore/sse/0");
+        final Collection<Book> books = new ArrayList<>();
+        
+        try (final SseEventSource eventSource = 
SseEventSource.target(target).build()) {
+            eventSource.register(collect(books), System.out::println);
+            eventSource.open();
+            // Give the SSE stream some time to collect all events
+            awaitEvents(3000, books, 4);
+        }
+
+        assertThat(books, 
+            hasItems(
+                new Book("New Book #1", 1), 
+                new Book("New Book #2", 2), 
+                new Book("New Book #3", 3), 
+                new Book("New Book #4", 4)
+            )
+        );
+    }
+    
+    @Test
+    public void testBooksStreamIsBroadcasted() throws Exception {
+        final Collection<Future<Response>> results = new ArrayList<>();
+
+        for (int i = 0; i < 2; ++i) {
+            results.add(
+                
createWebClient("/rest/api/bookstore/broadcast/sse").async().get()
+            );
+        }
+
+        createWebClient("/rest/api/bookstore/broadcast/close")
+            .async()
+            .post(null)
+            .get(10, TimeUnit.SECONDS)
+            .close();
+
+        for (final Future<Response> result: results) {
+            final Response r = result.get(3, TimeUnit.SECONDS);
+            assertEquals(Status.OK.getStatusCode(), r.getStatus());
+
+            final String response = r.readEntity(String.class);
+            assertThat(response, containsString("id: 1000"));
+            assertThat(response, containsString("data: " + toJson("New Book 
#1000", 1000)));
+
+            assertThat(response, containsString("id: 2000"));
+            assertThat(response, containsString("data: " + toJson("New Book 
#2000", 2000)));
+
+            r.close();
+        }
+    }
+
+    @Test
+    public void testBooksAreReturned() throws JsonProcessingException {
+        Response r = createWebClient("/rest/api/bookstore", 
MediaType.APPLICATION_JSON).get();
+        assertEquals(Status.OK.getStatusCode(), r.getStatus());
+
+        final Book[] books = r.readEntity(Book[].class);
+        assertThat(Arrays.asList(books), hasItems(new Book("New Book #1", 1), 
new Book("New Book #2", 2)));
+
+        r.close();
+    }
+
+    private static Consumer<InboundSseEvent> collect(final Collection< Book > 
books) {
+        return event -> books.add(event.readData(Book.class, 
MediaType.APPLICATION_JSON_TYPE));
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/Book.java
----------------------------------------------------------------------
diff --git 
a/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/Book.java
 
b/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/Book.java
new file mode 100644
index 0000000..7deb5c0
--- /dev/null
+++ 
b/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/Book.java
@@ -0,0 +1,71 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.systest.jaxrs.sse;
+
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+public class Book {
+    private String name;
+    private Integer id;
+
+    public Book() {
+    }
+
+    public Book(Integer id) {
+        this.id = id;
+    }
+
+    public Book(String name, Integer id) {
+        this.name = name;
+        this.id = id;
+    }
+
+    public void setName(String n) {
+        name = n;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setId(Integer i) {
+        id = i;
+    }
+
+    public Integer getId() {
+        return id;
+    }
+
+    @Override
+    public int hashCode() {
+        return HashCodeBuilder.reflectionHashCode(this);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return EqualsBuilder.reflectionEquals(this, obj);
+    }
+    
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/BookStore.java
----------------------------------------------------------------------
diff --git 
a/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/BookStore.java
 
b/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/BookStore.java
new file mode 100644
index 0000000..c096713
--- /dev/null
+++ 
b/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/BookStore.java
@@ -0,0 +1,136 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.systest.jaxrs.sse;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.sse.OutboundSseEvent;
+import javax.ws.rs.sse.OutboundSseEvent.Builder;
+import javax.ws.rs.sse.Sse;
+import javax.ws.rs.sse.SseBroadcaster;
+import javax.ws.rs.sse.SseEventSink;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Path("/api/bookstore")
+public class BookStore {
+    private static final Logger LOG = LoggerFactory.getLogger(BookStore.class);
+
+    private final CountDownLatch latch = new CountDownLatch(2);
+    private Sse sse;
+    private SseBroadcaster broadcaster;
+
+    @Context 
+    public void setSse(Sse sse) {
+        this.sse = sse;
+        this.broadcaster = sse.newBroadcaster();
+    }
+
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    public Collection<Book> books() {
+        return Arrays.asList(
+                new Book("New Book #1", 1),
+                new Book("New Book #2", 2)
+            );
+    }
+
+    @GET
+    @Path("sse/{id}")
+    @Produces(MediaType.SERVER_SENT_EVENTS)
+    public void forBook(@Context SseEventSink sink, @PathParam("id") final 
String id,
+            @HeaderParam(HttpHeaders.LAST_EVENT_ID_HEADER) @DefaultValue("0") 
final String lastEventId) {
+
+        new Thread() {
+            public void run() {
+                try {
+                    final Integer id = Integer.valueOf(lastEventId);
+                    final Builder builder = sse.newEventBuilder();
+
+                    sink.send(createStatsEvent(builder.name("book"), id + 1));
+                    Thread.sleep(200);
+                    sink.send(createStatsEvent(builder.name("book"), id + 2));
+                    Thread.sleep(200);
+                    sink.send(createStatsEvent(builder.name("book"), id + 3));
+                    Thread.sleep(200);
+                    sink.send(createStatsEvent(builder.name("book"), id + 4));
+                    Thread.sleep(200);
+                    sink.close();
+                } catch (final InterruptedException ex) {
+                    LOG.error("Communication error", ex);
+                }
+            }
+        }.start();
+    }
+
+    @GET
+    @Path("broadcast/sse")
+    @Produces(MediaType.SERVER_SENT_EVENTS)
+    public void broadcast(@Context SseEventSink sink) {
+        try {
+            broadcaster.register(sink);
+        } finally {
+            latch.countDown();
+        }
+    }
+
+    @POST
+    @Path("broadcast/close")
+    public void stop() {
+        try {
+            // Await a least 2 clients to be broadcasted over
+            if (!latch.await(10, TimeUnit.SECONDS)) {
+                LOG.warn("Not enough clients have been connected, closing 
broadcaster anyway");
+            }
+
+            final Builder builder = sse.newEventBuilder();
+            broadcaster.broadcast(createStatsEvent(builder.name("book"), 
1000));
+            broadcaster.broadcast(createStatsEvent(builder.name("book"), 
2000));
+
+        } catch (final InterruptedException ex) {
+            LOG.error("Wait has been interrupted", ex);
+        }
+
+        if (broadcaster != null) {
+            broadcaster.close();
+        }
+    }
+
+    private static OutboundSseEvent createStatsEvent(final 
OutboundSseEvent.Builder builder, final int eventId) {
+        return builder
+            .id(Integer.toString(eventId))
+            .data(Book.class, new Book("New Book #" + eventId, eventId))
+            .mediaType(MediaType.APPLICATION_JSON_TYPE)
+            .build();
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/BookStore2.java
----------------------------------------------------------------------
diff --git 
a/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/BookStore2.java
 
b/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/BookStore2.java
new file mode 100644
index 0000000..a5eeb8e
--- /dev/null
+++ 
b/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/BookStore2.java
@@ -0,0 +1,135 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.systest.jaxrs.sse;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.sse.OutboundSseEvent;
+import javax.ws.rs.sse.OutboundSseEvent.Builder;
+import javax.ws.rs.sse.Sse;
+import javax.ws.rs.sse.SseBroadcaster;
+import javax.ws.rs.sse.SseEventSink;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Path("/api/bookstore")
+public class BookStore2 {
+    private static final Logger LOG = 
LoggerFactory.getLogger(BookStore2.class);
+
+    private final CountDownLatch latch = new CountDownLatch(2);
+    private Sse sse;
+    private SseBroadcaster broadcaster;
+
+    public BookStore2(@Context Sse sse) {
+        this.sse = sse;
+        this.broadcaster = sse.newBroadcaster();
+    }
+
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    public Collection<Book> books() {
+        return Arrays.asList(
+                new Book("New Book #1", 1),
+                new Book("New Book #2", 2)
+            );
+    }
+
+    @GET
+    @Path("sse/{id}")
+    @Produces(MediaType.SERVER_SENT_EVENTS)
+    public void forBook(@Context SseEventSink sink, @PathParam("id") final 
String id,
+            @HeaderParam(HttpHeaders.LAST_EVENT_ID_HEADER) @DefaultValue("0") 
final String lastEventId) {
+
+        new Thread() {
+            public void run() {
+                try {
+                    final Integer id = Integer.valueOf(lastEventId);
+                    final Builder builder = sse.newEventBuilder();
+
+                    sink.send(createStatsEvent(builder.name("book"), id + 1));
+                    Thread.sleep(200);
+                    sink.send(createStatsEvent(builder.name("book"), id + 2));
+                    Thread.sleep(200);
+                    sink.send(createStatsEvent(builder.name("book"), id + 3));
+                    Thread.sleep(200);
+                    sink.send(createStatsEvent(builder.name("book"), id + 4));
+                    Thread.sleep(200);
+                    sink.close();
+                } catch (final InterruptedException ex) {
+                    LOG.error("Communication error", ex);
+                }
+            }
+        }.start();
+    }
+
+    @GET
+    @Path("broadcast/sse")
+    @Produces(MediaType.SERVER_SENT_EVENTS)
+    public void broadcast(@Context SseEventSink sink) {
+        try {
+            broadcaster.register(sink);
+        } finally {
+            latch.countDown();
+        }
+    }
+
+    @POST
+    @Path("broadcast/close")
+    public void stop() {
+        try {
+            // Await a least 2 clients to be broadcasted over
+            if (!latch.await(10, TimeUnit.SECONDS)) {
+                LOG.warn("Not enough clients have been connected, closing 
broadcaster anyway");
+            }
+
+            final Builder builder = sse.newEventBuilder();
+            broadcaster.broadcast(createStatsEvent(builder.name("book"), 
1000));
+            broadcaster.broadcast(createStatsEvent(builder.name("book"), 
2000));
+
+        } catch (final InterruptedException ex) {
+            LOG.error("Wait has been interrupted", ex);
+        }
+
+        if (broadcaster != null) {
+            broadcaster.close();
+        }
+    }
+
+    private static OutboundSseEvent createStatsEvent(final 
OutboundSseEvent.Builder builder, final int eventId) {
+        return builder
+            .id(Integer.toString(eventId))
+            .data(Book.class, new Book("New Book #" + eventId, eventId))
+            .mediaType(MediaType.APPLICATION_JSON_TYPE)
+            .build();
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/SseApplication.java
----------------------------------------------------------------------
diff --git 
a/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/SseApplication.java
 
b/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/SseApplication.java
new file mode 100644
index 0000000..a4a4049
--- /dev/null
+++ 
b/systests/rs-sse/rs-sse-base/src/main/java/org/apache/cxf/systest/jaxrs/sse/SseApplication.java
@@ -0,0 +1,38 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.systest.jaxrs.sse;
+
+import java.util.Collections;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+
+import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
+
+public class SseApplication extends Application {
+    @Override
+    public Set<Class<?>> getClasses() {
+        return Collections.singleton(BookStore2.class);
+    }
+
+    @Override
+    public Set<Object> getSingletons() {
+        return Collections.singleton(new JacksonJsonProvider());
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/rs-sse-base/src/main/resources/META-INF/cxf/org.apache.cxf.Logger
----------------------------------------------------------------------
diff --git 
a/systests/rs-sse/rs-sse-base/src/main/resources/META-INF/cxf/org.apache.cxf.Logger
 
b/systests/rs-sse/rs-sse-base/src/main/resources/META-INF/cxf/org.apache.cxf.Logger
new file mode 100644
index 0000000..27dd788
--- /dev/null
+++ 
b/systests/rs-sse/rs-sse-base/src/main/resources/META-INF/cxf/org.apache.cxf.Logger
@@ -0,0 +1 @@
+org.apache.cxf.common.logging.Slf4jLogger
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/rs-sse-base/src/main/resources/jaxrs_sse/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git 
a/systests/rs-sse/rs-sse-base/src/main/resources/jaxrs_sse/WEB-INF/web.xml 
b/systests/rs-sse/rs-sse-base/src/main/resources/jaxrs_sse/WEB-INF/web.xml
new file mode 100644
index 0000000..64746acb
--- /dev/null
+++ b/systests/rs-sse/rs-sse-base/src/main/resources/jaxrs_sse/WEB-INF/web.xml
@@ -0,0 +1,28 @@
+<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee";
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>
+
+       <servlet>
+               <servlet-name>CXFServlet</servlet-name>
+               <display-name>CXF Servlet</display-name>
+               
<servlet-class>org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet</servlet-class>
    
+               <load-on-startup>1</load-on-startup>
+               <async-supported>true</async-supported>
+               <init-param>
+                       <param-name>transportId</param-name>
+                       
<param-value>http://cxf.apache.org/transports/http/sse</param-value>
+               </init-param>
+               <init-param>
+                       <param-name>javax.ws.rs.Application</param-name>
+                       
<param-value>org.apache.cxf.systest.jaxrs.sse.SseApplication</param-value>
+               </init-param>
+               <init-param>
+                       <param-name>jaxrs.scope</param-name>
+                       <param-value>singleton</param-value>
+               </init-param>
+       </servlet>
+
+       <servlet-mapping>
+               <servlet-name>CXFServlet</servlet-name>
+               <url-pattern>/rest/*</url-pattern>
+       </servlet-mapping>
+</web-app>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/rs-sse-base/src/main/resources/logback.xml
----------------------------------------------------------------------
diff --git a/systests/rs-sse/rs-sse-base/src/main/resources/logback.xml 
b/systests/rs-sse/rs-sse-base/src/main/resources/logback.xml
new file mode 100644
index 0000000..430aa64
--- /dev/null
+++ b/systests/rs-sse/rs-sse-base/src/main/resources/logback.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="5 seconds">
+       <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+               <encoder>
+                       <pattern>[%level] %d{yyyy-MM-dd HH:mm:ss.SSS} 
%logger{36} - [%X] %msg%n</pattern>
+               </encoder>
+       </appender>
+
+       <root level="INFO">
+               <appender-ref ref="STDOUT" />
+       </root>
+</configuration>

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/rs-sse-jetty/pom.xml
----------------------------------------------------------------------
diff --git a/systests/rs-sse/rs-sse-jetty/pom.xml 
b/systests/rs-sse/rs-sse-jetty/pom.xml
new file mode 100644
index 0000000..c786a76
--- /dev/null
+++ b/systests/rs-sse/rs-sse-jetty/pom.xml
@@ -0,0 +1,70 @@
+<?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";>
+    <parent>
+        <groupId>org.apache.cxf.systests</groupId>
+        <artifactId>cxf-systests-rs-sse</artifactId>
+        <version>3.2.0-SNAPSHOT</version>
+        <relativePath>../</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>cxf-systests-rs-sse-jetty</artifactId>
+    <name>Apache CXF SSE Integration System Tests for Jetty</name>
+    <description>Apache CXF SSE Integration System Tests for 
Jetty</description>
+    <url>http://cxf.apache.org</url>
+    <properties>
+        <cxf.jetty.version>${cxf.jetty9.version}</cxf.jetty.version>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-annotations</artifactId>
+            <version>${cxf.jetty.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-server</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-plus</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty.websocket</groupId>
+            <artifactId>websocket-server</artifactId>
+            <version>${cxf.jetty.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-webapp</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf.systests</groupId>
+            <artifactId>cxf-systests-rs-sse-base</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/rs-sse-jetty/src/test/java/org/apache/cxf/systest/jaxrs/sse/jetty/AbstractJettyServer.java
----------------------------------------------------------------------
diff --git 
a/systests/rs-sse/rs-sse-jetty/src/test/java/org/apache/cxf/systest/jaxrs/sse/jetty/AbstractJettyServer.java
 
b/systests/rs-sse/rs-sse-jetty/src/test/java/org/apache/cxf/systest/jaxrs/sse/jetty/AbstractJettyServer.java
new file mode 100644
index 0000000..a47c0c3
--- /dev/null
+++ 
b/systests/rs-sse/rs-sse-jetty/src/test/java/org/apache/cxf/systest/jaxrs/sse/jetty/AbstractJettyServer.java
@@ -0,0 +1,98 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.systest.jaxrs.sse.jetty;
+
+import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
+
+import org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet;
+import org.apache.cxf.systest.jaxrs.sse.BookStore;
+import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
+import org.apache.cxf.transport.sse.SseHttpTransportFactory;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.DefaultHandler;
+import org.eclipse.jetty.server.handler.HandlerCollection;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+public abstract class AbstractJettyServer extends AbstractBusTestServerBase {
+
+    private org.eclipse.jetty.server.Server server;
+    private final String resourcePath;
+    private final String contextPath;
+    private final int port;
+
+    protected AbstractJettyServer(final String contextPath, int portNumber) {
+        this(null, contextPath, portNumber);
+    }
+
+    protected AbstractJettyServer(final String resourcePath, final String 
contextPath, int portNumber) {
+        this.resourcePath = resourcePath;
+        this.contextPath = contextPath;
+        this.port = portNumber;
+    }
+
+    protected void run() {
+        server = new Server(port);
+
+        try {
+            if (resourcePath == null) {
+                // Register and map the dispatcher servlet
+                final ServletHolder holder = new ServletHolder(new 
CXFNonSpringJaxrsServlet());
+                holder.setInitParameter(CXFNonSpringJaxrsServlet.TRANSPORT_ID, 
SseHttpTransportFactory.TRANSPORT_ID);
+                holder.setInitParameter("jaxrs.serviceClasses", 
BookStore.class.getName());
+                holder.setInitParameter("jaxrs.providers", 
JacksonJsonProvider.class.getName());
+                final ServletContextHandler context = new 
ServletContextHandler();
+                context.setContextPath(contextPath);
+                context.addServlet(holder, "/rest/*");
+                server.setHandler(context);
+            } else {
+                final WebAppContext context = new WebAppContext();
+                context.setContextPath(contextPath);
+                
context.setWar(getClass().getResource(resourcePath).toURI().getPath());
+
+                HandlerCollection handlers = new HandlerCollection();
+                handlers.setHandlers(new Handler[] {context, new 
DefaultHandler()});
+                server.setHandler(handlers);
+            }
+
+            configureServer(server);
+            server.start();
+        } catch (final Exception ex) {
+            ex.printStackTrace();
+            fail(ex.getMessage());
+        }
+    }
+
+    protected void configureServer(org.eclipse.jetty.server.Server theserver) 
throws Exception {
+
+    }
+
+    public void tearDown() throws Exception {
+        super.tearDown();
+
+        if (server != null) {
+            server.stop();
+            server.destroy();
+            server = null;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/rs-sse-jetty/src/test/java/org/apache/cxf/systest/jaxrs/sse/jetty/JettyEmbeddedTest.java
----------------------------------------------------------------------
diff --git 
a/systests/rs-sse/rs-sse-jetty/src/test/java/org/apache/cxf/systest/jaxrs/sse/jetty/JettyEmbeddedTest.java
 
b/systests/rs-sse/rs-sse-jetty/src/test/java/org/apache/cxf/systest/jaxrs/sse/jetty/JettyEmbeddedTest.java
new file mode 100644
index 0000000..cafdeec
--- /dev/null
+++ 
b/systests/rs-sse/rs-sse-jetty/src/test/java/org/apache/cxf/systest/jaxrs/sse/jetty/JettyEmbeddedTest.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.systest.jaxrs.sse.jetty;
+
+import org.apache.cxf.jaxrs.model.AbstractResourceInfo;
+import org.apache.cxf.systest.jaxrs.sse.AbstractSseTest;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+
+public class JettyEmbeddedTest extends AbstractSseTest {
+    @Ignore
+    public static class EmbeddedJettyServer extends AbstractJettyServer {
+        public static final int PORT = 
allocatePortAsInt(EmbeddedJettyServer.class);
+
+        public EmbeddedJettyServer() {
+            super("/", PORT);
+        }
+    }
+
+    @BeforeClass
+    public static void startServers() throws Exception {
+        AbstractResourceInfo.clearAllMaps();
+        //keep out of process due to stack traces testing failures
+        assertTrue("server did not launch correctly", 
launchServer(EmbeddedJettyServer.class, true));
+        createStaticBus();
+    }
+
+    @Override
+    protected int getPort() {
+        return EmbeddedJettyServer.PORT;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/rs-sse-jetty/src/test/java/org/apache/cxf/systest/jaxrs/sse/jetty/JettyWarTest.java
----------------------------------------------------------------------
diff --git 
a/systests/rs-sse/rs-sse-jetty/src/test/java/org/apache/cxf/systest/jaxrs/sse/jetty/JettyWarTest.java
 
b/systests/rs-sse/rs-sse-jetty/src/test/java/org/apache/cxf/systest/jaxrs/sse/jetty/JettyWarTest.java
new file mode 100644
index 0000000..10f435b
--- /dev/null
+++ 
b/systests/rs-sse/rs-sse-jetty/src/test/java/org/apache/cxf/systest/jaxrs/sse/jetty/JettyWarTest.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.jaxrs.sse.jetty;
+
+import org.apache.cxf.jaxrs.model.AbstractResourceInfo;
+import org.apache.cxf.systest.jaxrs.sse.AbstractSseTest;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+
+public class JettyWarTest extends AbstractSseTest {
+    @Ignore
+    public static class EmbeddedJettyServer extends AbstractJettyServer {
+        public static final int PORT = 
allocatePortAsInt(EmbeddedJettyServer.class);
+
+        public EmbeddedJettyServer() {
+            super("/jaxrs_sse", "/", PORT);
+        }
+    }
+
+    @BeforeClass
+    public static void startServers() throws Exception {
+        AbstractResourceInfo.clearAllMaps();
+        assertTrue("server did not launch correctly", 
launchServer(EmbeddedJettyServer.class, true));
+        createStaticBus();
+    }
+
+    @Override
+    protected int getPort() {
+        return EmbeddedJettyServer.PORT;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/rs-sse-tomcat/pom.xml
----------------------------------------------------------------------
diff --git a/systests/rs-sse/rs-sse-tomcat/pom.xml 
b/systests/rs-sse/rs-sse-tomcat/pom.xml
new file mode 100644
index 0000000..e59a7b7
--- /dev/null
+++ b/systests/rs-sse/rs-sse-tomcat/pom.xml
@@ -0,0 +1,67 @@
+<?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";>
+    <parent>
+        <groupId>org.apache.cxf.systests</groupId>
+        <artifactId>cxf-systests-rs-sse</artifactId>
+        <version>3.2.0-SNAPSHOT</version>
+        <relativePath>../</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>cxf-systests-rs-sse-tomcat</artifactId>
+    <name>Apache CXF SSE Integration System Tests for Tomcat</name>
+    <description>Apache CXF SSE Integration System Tests Tomcat</description>
+    <url>http://cxf.apache.org</url>
+    <properties>
+        <cxf.tomcat.version>8.0.32</cxf.tomcat.version>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.tomcat.embed</groupId>
+            <artifactId>tomcat-embed-core</artifactId>
+            <version>${cxf.tomcat.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tomcat.embed</groupId>
+            <artifactId>tomcat-embed-logging-juli</artifactId>
+            <version>${cxf.tomcat.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tomcat</groupId>
+            <artifactId>tomcat-jasper</artifactId>
+            <version>${cxf.tomcat.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf.systests</groupId>
+            <artifactId>cxf-systests-rs-sse-base</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty.websocket</groupId>
+            <artifactId>websocket-server</artifactId>
+            <version>${cxf.jetty.version}</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/rs-sse-tomcat/src/test/java/org/apache/cxf/systest/jaxrs/sse/tomcat/AbstractTomcatServer.java
----------------------------------------------------------------------
diff --git 
a/systests/rs-sse/rs-sse-tomcat/src/test/java/org/apache/cxf/systest/jaxrs/sse/tomcat/AbstractTomcatServer.java
 
b/systests/rs-sse/rs-sse-tomcat/src/test/java/org/apache/cxf/systest/jaxrs/sse/tomcat/AbstractTomcatServer.java
new file mode 100644
index 0000000..ded2a64
--- /dev/null
+++ 
b/systests/rs-sse/rs-sse-tomcat/src/test/java/org/apache/cxf/systest/jaxrs/sse/tomcat/AbstractTomcatServer.java
@@ -0,0 +1,111 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.systest.jaxrs.sse.tomcat;
+
+import java.io.File;
+import java.io.IOException;
+
+import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.Wrapper;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet;
+import org.apache.cxf.systest.jaxrs.sse.BookStore;
+import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
+import org.apache.cxf.transport.sse.SseHttpTransportFactory;
+
+public abstract class AbstractTomcatServer extends AbstractBusTestServerBase {
+
+    private Tomcat server;
+    private final String resourcePath;
+    private final String contextPath;
+    private final int port;
+
+    protected AbstractTomcatServer(final String contextPath, int portNumber) {
+        this(null, contextPath, portNumber);
+    }
+
+    protected AbstractTomcatServer(final String resourcePath, final String 
contextPath, int portNumber) {
+        this.resourcePath = resourcePath;
+        this.contextPath = contextPath;
+        this.port = portNumber;
+    }
+
+    protected void run() {
+        server = new Tomcat();
+        server.setPort(port);
+
+        try {
+            final File base = createTemporaryDirectory();
+            server.setBaseDir(base.getAbsolutePath());
+
+            if (resourcePath == null) {
+                final Context context = server.addContext("/", 
base.getAbsolutePath());
+                final Wrapper cxfServlet = Tomcat.addServlet(context, 
"cxfServlet", new CXFNonSpringJaxrsServlet());
+                
cxfServlet.addInitParameter(CXFNonSpringJaxrsServlet.TRANSPORT_ID,
+                    SseHttpTransportFactory.TRANSPORT_ID);
+                cxfServlet.addInitParameter("jaxrs.serviceClasses", 
BookStore.class.getName());
+                cxfServlet.addInitParameter("jaxrs.providers", 
JacksonJsonProvider.class.getName());
+                cxfServlet.setAsyncSupported(true);
+                context.addServletMapping("/rest/*", "cxfServlet");
+            } else {
+                server.getHost().setAppBase(base.getAbsolutePath());
+                server.getHost().setAutoDeploy(true);
+                server.getHost().setDeployOnStartup(true);
+                server.addWebapp(contextPath, 
getClass().getResource(resourcePath).toURI().getPath().toString());
+            }
+
+            server.start();
+        } catch (final Exception ex) {
+            ex.printStackTrace();
+            fail(ex.getMessage());
+        }
+    }
+
+    protected void configureServer(org.eclipse.jetty.server.Server theserver) 
throws Exception {
+
+    }
+
+    private static File createTemporaryDirectory() throws IOException {
+        final File base = File.createTempFile("tmp-", "");
+
+        if (!base.delete()) {
+            throw new IOException("Cannot (re)create base folder: " + 
base.getAbsolutePath());
+        }
+
+        if (!base.mkdir()) {
+            throw new IOException("Cannot create base folder: " + 
base.getAbsolutePath());
+        }
+
+        base.deleteOnExit();
+        return base;
+    }
+
+    public void tearDown() throws Exception {
+        super.tearDown();
+
+        if (server != null) {
+            server.stop();
+            server.destroy();
+            server = null;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/rs-sse-tomcat/src/test/java/org/apache/cxf/systest/jaxrs/sse/tomcat/TomcatEmbeddedTest.java
----------------------------------------------------------------------
diff --git 
a/systests/rs-sse/rs-sse-tomcat/src/test/java/org/apache/cxf/systest/jaxrs/sse/tomcat/TomcatEmbeddedTest.java
 
b/systests/rs-sse/rs-sse-tomcat/src/test/java/org/apache/cxf/systest/jaxrs/sse/tomcat/TomcatEmbeddedTest.java
new file mode 100644
index 0000000..b96cc28
--- /dev/null
+++ 
b/systests/rs-sse/rs-sse-tomcat/src/test/java/org/apache/cxf/systest/jaxrs/sse/tomcat/TomcatEmbeddedTest.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.systest.jaxrs.sse.tomcat;
+
+import org.apache.cxf.jaxrs.model.AbstractResourceInfo;
+import org.apache.cxf.systest.jaxrs.sse.AbstractSseTest;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+
+public class TomcatEmbeddedTest extends AbstractSseTest {
+    @Ignore
+    public static class EmbeddedTomcatServer extends AbstractTomcatServer {
+        public static final int PORT = 
allocatePortAsInt(EmbeddedTomcatServer.class);
+
+        public EmbeddedTomcatServer() {
+            super("/", PORT);
+        }
+    }
+
+    @BeforeClass
+    public static void startServers() throws Exception {
+        AbstractResourceInfo.clearAllMaps();
+        assertTrue("server did not launch correctly", 
launchServer(EmbeddedTomcatServer.class, true));
+        createStaticBus();
+    }
+
+    @Override
+    protected int getPort() {
+        return EmbeddedTomcatServer.PORT;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/rs-sse-tomcat/src/test/java/org/apache/cxf/systest/jaxrs/sse/tomcat/TomcatWarTest.java
----------------------------------------------------------------------
diff --git 
a/systests/rs-sse/rs-sse-tomcat/src/test/java/org/apache/cxf/systest/jaxrs/sse/tomcat/TomcatWarTest.java
 
b/systests/rs-sse/rs-sse-tomcat/src/test/java/org/apache/cxf/systest/jaxrs/sse/tomcat/TomcatWarTest.java
new file mode 100644
index 0000000..102c1d1
--- /dev/null
+++ 
b/systests/rs-sse/rs-sse-tomcat/src/test/java/org/apache/cxf/systest/jaxrs/sse/tomcat/TomcatWarTest.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.systest.jaxrs.sse.tomcat;
+
+import org.apache.cxf.jaxrs.model.AbstractResourceInfo;
+import org.apache.cxf.systest.jaxrs.sse.AbstractSseTest;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+
+public class TomcatWarTest extends AbstractSseTest {
+    @Ignore
+    public static class EmbeddedTomcatServer extends AbstractTomcatServer {
+        public static final int PORT = 
allocatePortAsInt(EmbeddedTomcatServer.class);
+
+        public EmbeddedTomcatServer() {
+            super("/jaxrs_sse", "/", PORT);
+        }
+    }
+
+    @BeforeClass
+    public static void startServers() throws Exception {
+        AbstractResourceInfo.clearAllMaps();
+        assertTrue("server did not launch correctly", 
launchServer(EmbeddedTomcatServer.class, true));
+        createStaticBus();
+    }
+
+    @Override
+    protected int getPort() {
+        return EmbeddedTomcatServer.PORT;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/AbstractBroadcasterSseTest.java
----------------------------------------------------------------------
diff --git 
a/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/AbstractBroadcasterSseTest.java
 
b/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/AbstractBroadcasterSseTest.java
deleted file mode 100644
index 12a7ec7..0000000
--- 
a/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/AbstractBroadcasterSseTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.cxf.systest.jaxrs.sse;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-
-import org.junit.Test;
-
-import static org.hamcrest.CoreMatchers.containsString;
-import static org.hamcrest.CoreMatchers.hasItems;
-
-public abstract class AbstractBroadcasterSseTest extends AbstractSseBaseTest {
-    @Test
-    public void testBooksStreamIsBroadcasted() throws Exception {
-        final Collection<Future<Response>> results = new ArrayList<>();
-
-        for (int i = 0; i < 2; ++i) {
-            results.add(
-                
createWebClient("/rest/api/bookstore/broadcast/sse").async().get()
-            );
-        }
-
-        createWebClient("/rest/api/bookstore/broadcast/close")
-            .async()
-            .post(null)
-            .get(10, TimeUnit.SECONDS)
-            .close();
-
-        for (final Future<Response> result: results) {
-            final Response r = result.get(3, TimeUnit.SECONDS);
-            assertEquals(Status.OK.getStatusCode(), r.getStatus());
-
-            final String response = r.readEntity(String.class);
-            assertThat(response, containsString("id: 1000"));
-            assertThat(response, containsString("data: " + toJson("New Book 
#1000", 1000)));
-
-            assertThat(response, containsString("id: 2000"));
-            assertThat(response, containsString("data: " + toJson("New Book 
#2000", 2000)));
-
-            r.close();
-        }
-    }
-
-    @Test
-    public void testBooksAreReturned() throws JsonProcessingException {
-        Response r = createWebClient("/rest/api/bookstore", 
MediaType.APPLICATION_JSON).get();
-        assertEquals(Status.OK.getStatusCode(), r.getStatus());
-
-        final Book[] books = r.readEntity(Book[].class);
-        assertThat(Arrays.asList(books), hasItems(new Book("New Book #1", 1), 
new Book("New Book #2", 2)));
-
-        r.close();
-    }
-}

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/AbstractSseBaseTest.java
----------------------------------------------------------------------
diff --git 
a/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/AbstractSseBaseTest.java
 
b/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/AbstractSseBaseTest.java
deleted file mode 100644
index 87425b5..0000000
--- 
a/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/AbstractSseBaseTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.cxf.systest.jaxrs.sse;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-import javax.ws.rs.client.ClientBuilder;
-import javax.ws.rs.client.WebTarget;
-import javax.ws.rs.core.MediaType;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
-
-import org.apache.cxf.jaxrs.client.WebClient;
-import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
-
-public abstract class AbstractSseBaseTest extends 
AbstractBusClientServerTestBase {
-    private final ObjectMapper mapper = new ObjectMapper();
-
-    protected String toJson(final String name, final Integer id) throws 
JsonProcessingException {
-        return mapper.writeValueAsString(new Book(name, id));
-    }
-
-    protected WebClient createWebClient(final String url, final String media) {
-        final List< ? > providers = Arrays.asList(new JacksonJsonProvider());
-
-        final WebClient wc = WebClient
-            .create("http://localhost:"; + getPort() + url, providers)
-            .accept(media);
-
-        
WebClient.getConfig(wc).getHttpConduit().getClient().setReceiveTimeout(8000L);
-        return wc;
-    }
-
-    protected WebClient createWebClient(final String url) {
-        return createWebClient(url, MediaType.SERVER_SENT_EVENTS);
-    }
-
-    protected WebTarget createWebTarget(final String url) {
-        return ClientBuilder
-            .newClient()
-            .property("http.receive.timeout", 8000)
-            .register(JacksonJsonProvider.class)
-            .target("http://localhost:"; + getPort() + url);
-    }
-    
-    protected void awaitEvents(long timeout, final Collection<?> events, int 
size) throws InterruptedException {
-        final long sleep = timeout / 10;
-        
-        for (int i = 0; i < timeout; i += sleep) {
-            if (events.size() == size) {
-                break;
-            } else {
-                Thread.sleep(sleep);
-            }
-        }
-    }
-
-    protected abstract int getPort();
-}

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/AbstractSseTest.java
----------------------------------------------------------------------
diff --git 
a/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/AbstractSseTest.java
 
b/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/AbstractSseTest.java
deleted file mode 100644
index 2f36914..0000000
--- 
a/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/AbstractSseTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.cxf.systest.jaxrs.sse;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.function.Consumer;
-
-import javax.ws.rs.client.WebTarget;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.sse.InboundSseEvent;
-import javax.ws.rs.sse.SseEventSource;
-
-import org.junit.Test;
-
-import static org.hamcrest.CoreMatchers.anyOf;
-import static org.hamcrest.CoreMatchers.hasItem;
-import static org.hamcrest.CoreMatchers.hasItems;
-
-public abstract class AbstractSseTest extends AbstractSseBaseTest {
-    @Test
-    public void testBooksStreamIsReturnedFromLastEventId() throws 
InterruptedException {
-        final WebTarget target = createWebTarget("/rest/api/bookstore/sse/1")
-            .property(HttpHeaders.LAST_EVENT_ID_HEADER, 150);
-        final Collection<Book> books = new ArrayList<>();
-        
-        try (final SseEventSource eventSource = 
SseEventSource.target(target).build()) {
-            eventSource.register(collect(books), System.out::println);
-            eventSource.open();
-            // Give the SSE stream some time to collect all events
-            awaitEvents(3000, books, 4);
-        }
-
-        // Easing the test verification here, it does not work well for Atm + 
Jetty
-        assertThat(books, 
-            anyOf(
-                hasItem(new Book("New Book #151", 151)), 
-                hasItem(new Book("New Book #152", 152)), 
-                hasItem(new Book("New Book #153", 153)), 
-                hasItem(new Book("New Book #154", 154))
-            )
-        );
-    }
-
-    @Test
-    public void testBooksStreamIsReturnedFromInboundSseEvents() throws 
InterruptedException {
-        final WebTarget target = createWebTarget("/rest/api/bookstore/sse/0");
-        final Collection<Book> books = new ArrayList<>();
-        
-        try (final SseEventSource eventSource = 
SseEventSource.target(target).build()) {
-            eventSource.register(collect(books), System.out::println);
-            eventSource.open();
-            // Give the SSE stream some time to collect all events
-            awaitEvents(3000, books, 4);
-        }
-
-        assertThat(books, 
-            hasItems(
-                new Book("New Book #1", 1), 
-                new Book("New Book #2", 2), 
-                new Book("New Book #3", 3), 
-                new Book("New Book #4", 4)
-            )
-        );
-    }
-
-    private static Consumer<InboundSseEvent> collect(final Collection< Book > 
books) {
-        return event -> books.add(event.readData(Book.class, 
MediaType.APPLICATION_JSON_TYPE));
-    }
-}

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/Book.java
----------------------------------------------------------------------
diff --git 
a/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/Book.java 
b/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/Book.java
deleted file mode 100644
index 7deb5c0..0000000
--- a/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/Book.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.cxf.systest.jaxrs.sse;
-
-import org.apache.commons.lang3.builder.EqualsBuilder;
-import org.apache.commons.lang3.builder.HashCodeBuilder;
-import org.apache.commons.lang3.builder.ToStringBuilder;
-
-public class Book {
-    private String name;
-    private Integer id;
-
-    public Book() {
-    }
-
-    public Book(Integer id) {
-        this.id = id;
-    }
-
-    public Book(String name, Integer id) {
-        this.name = name;
-        this.id = id;
-    }
-
-    public void setName(String n) {
-        name = n;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setId(Integer i) {
-        id = i;
-    }
-
-    public Integer getId() {
-        return id;
-    }
-
-    @Override
-    public int hashCode() {
-        return HashCodeBuilder.reflectionHashCode(this);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        return EqualsBuilder.reflectionEquals(this, obj);
-    }
-    
-    @Override
-    public String toString() {
-        return ToStringBuilder.reflectionToString(this);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/BookStore.java
----------------------------------------------------------------------
diff --git 
a/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/BookStore.java 
b/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/BookStore.java
deleted file mode 100644
index c096713..0000000
--- 
a/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/BookStore.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.cxf.systest.jaxrs.sse;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import javax.ws.rs.DefaultValue;
-import javax.ws.rs.GET;
-import javax.ws.rs.HeaderParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.sse.OutboundSseEvent;
-import javax.ws.rs.sse.OutboundSseEvent.Builder;
-import javax.ws.rs.sse.Sse;
-import javax.ws.rs.sse.SseBroadcaster;
-import javax.ws.rs.sse.SseEventSink;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Path("/api/bookstore")
-public class BookStore {
-    private static final Logger LOG = LoggerFactory.getLogger(BookStore.class);
-
-    private final CountDownLatch latch = new CountDownLatch(2);
-    private Sse sse;
-    private SseBroadcaster broadcaster;
-
-    @Context 
-    public void setSse(Sse sse) {
-        this.sse = sse;
-        this.broadcaster = sse.newBroadcaster();
-    }
-
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    public Collection<Book> books() {
-        return Arrays.asList(
-                new Book("New Book #1", 1),
-                new Book("New Book #2", 2)
-            );
-    }
-
-    @GET
-    @Path("sse/{id}")
-    @Produces(MediaType.SERVER_SENT_EVENTS)
-    public void forBook(@Context SseEventSink sink, @PathParam("id") final 
String id,
-            @HeaderParam(HttpHeaders.LAST_EVENT_ID_HEADER) @DefaultValue("0") 
final String lastEventId) {
-
-        new Thread() {
-            public void run() {
-                try {
-                    final Integer id = Integer.valueOf(lastEventId);
-                    final Builder builder = sse.newEventBuilder();
-
-                    sink.send(createStatsEvent(builder.name("book"), id + 1));
-                    Thread.sleep(200);
-                    sink.send(createStatsEvent(builder.name("book"), id + 2));
-                    Thread.sleep(200);
-                    sink.send(createStatsEvent(builder.name("book"), id + 3));
-                    Thread.sleep(200);
-                    sink.send(createStatsEvent(builder.name("book"), id + 4));
-                    Thread.sleep(200);
-                    sink.close();
-                } catch (final InterruptedException ex) {
-                    LOG.error("Communication error", ex);
-                }
-            }
-        }.start();
-    }
-
-    @GET
-    @Path("broadcast/sse")
-    @Produces(MediaType.SERVER_SENT_EVENTS)
-    public void broadcast(@Context SseEventSink sink) {
-        try {
-            broadcaster.register(sink);
-        } finally {
-            latch.countDown();
-        }
-    }
-
-    @POST
-    @Path("broadcast/close")
-    public void stop() {
-        try {
-            // Await a least 2 clients to be broadcasted over
-            if (!latch.await(10, TimeUnit.SECONDS)) {
-                LOG.warn("Not enough clients have been connected, closing 
broadcaster anyway");
-            }
-
-            final Builder builder = sse.newEventBuilder();
-            broadcaster.broadcast(createStatsEvent(builder.name("book"), 
1000));
-            broadcaster.broadcast(createStatsEvent(builder.name("book"), 
2000));
-
-        } catch (final InterruptedException ex) {
-            LOG.error("Wait has been interrupted", ex);
-        }
-
-        if (broadcaster != null) {
-            broadcaster.close();
-        }
-    }
-
-    private static OutboundSseEvent createStatsEvent(final 
OutboundSseEvent.Builder builder, final int eventId) {
-        return builder
-            .id(Integer.toString(eventId))
-            .data(Book.class, new Book("New Book #" + eventId, eventId))
-            .mediaType(MediaType.APPLICATION_JSON_TYPE)
-            .build();
-    }
-}

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/BookStore2.java
----------------------------------------------------------------------
diff --git 
a/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/BookStore2.java
 
b/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/BookStore2.java
deleted file mode 100644
index a5eeb8e..0000000
--- 
a/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/BookStore2.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.cxf.systest.jaxrs.sse;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import javax.ws.rs.DefaultValue;
-import javax.ws.rs.GET;
-import javax.ws.rs.HeaderParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.sse.OutboundSseEvent;
-import javax.ws.rs.sse.OutboundSseEvent.Builder;
-import javax.ws.rs.sse.Sse;
-import javax.ws.rs.sse.SseBroadcaster;
-import javax.ws.rs.sse.SseEventSink;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Path("/api/bookstore")
-public class BookStore2 {
-    private static final Logger LOG = 
LoggerFactory.getLogger(BookStore2.class);
-
-    private final CountDownLatch latch = new CountDownLatch(2);
-    private Sse sse;
-    private SseBroadcaster broadcaster;
-
-    public BookStore2(@Context Sse sse) {
-        this.sse = sse;
-        this.broadcaster = sse.newBroadcaster();
-    }
-
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    public Collection<Book> books() {
-        return Arrays.asList(
-                new Book("New Book #1", 1),
-                new Book("New Book #2", 2)
-            );
-    }
-
-    @GET
-    @Path("sse/{id}")
-    @Produces(MediaType.SERVER_SENT_EVENTS)
-    public void forBook(@Context SseEventSink sink, @PathParam("id") final 
String id,
-            @HeaderParam(HttpHeaders.LAST_EVENT_ID_HEADER) @DefaultValue("0") 
final String lastEventId) {
-
-        new Thread() {
-            public void run() {
-                try {
-                    final Integer id = Integer.valueOf(lastEventId);
-                    final Builder builder = sse.newEventBuilder();
-
-                    sink.send(createStatsEvent(builder.name("book"), id + 1));
-                    Thread.sleep(200);
-                    sink.send(createStatsEvent(builder.name("book"), id + 2));
-                    Thread.sleep(200);
-                    sink.send(createStatsEvent(builder.name("book"), id + 3));
-                    Thread.sleep(200);
-                    sink.send(createStatsEvent(builder.name("book"), id + 4));
-                    Thread.sleep(200);
-                    sink.close();
-                } catch (final InterruptedException ex) {
-                    LOG.error("Communication error", ex);
-                }
-            }
-        }.start();
-    }
-
-    @GET
-    @Path("broadcast/sse")
-    @Produces(MediaType.SERVER_SENT_EVENTS)
-    public void broadcast(@Context SseEventSink sink) {
-        try {
-            broadcaster.register(sink);
-        } finally {
-            latch.countDown();
-        }
-    }
-
-    @POST
-    @Path("broadcast/close")
-    public void stop() {
-        try {
-            // Await a least 2 clients to be broadcasted over
-            if (!latch.await(10, TimeUnit.SECONDS)) {
-                LOG.warn("Not enough clients have been connected, closing 
broadcaster anyway");
-            }
-
-            final Builder builder = sse.newEventBuilder();
-            broadcaster.broadcast(createStatsEvent(builder.name("book"), 
1000));
-            broadcaster.broadcast(createStatsEvent(builder.name("book"), 
2000));
-
-        } catch (final InterruptedException ex) {
-            LOG.error("Wait has been interrupted", ex);
-        }
-
-        if (broadcaster != null) {
-            broadcaster.close();
-        }
-    }
-
-    private static OutboundSseEvent createStatsEvent(final 
OutboundSseEvent.Builder builder, final int eventId) {
-        return builder
-            .id(Integer.toString(eventId))
-            .data(Book.class, new Book("New Book #" + eventId, eventId))
-            .mediaType(MediaType.APPLICATION_JSON_TYPE)
-            .build();
-    }
-}

http://git-wip-us.apache.org/repos/asf/cxf/blob/76877054/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/SseApplication.java
----------------------------------------------------------------------
diff --git 
a/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/SseApplication.java
 
b/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/SseApplication.java
deleted file mode 100644
index a4a4049..0000000
--- 
a/systests/rs-sse/src/test/java/org/apache/cxf/systest/jaxrs/sse/SseApplication.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.cxf.systest.jaxrs.sse;
-
-import java.util.Collections;
-import java.util.Set;
-
-import javax.ws.rs.core.Application;
-
-import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
-
-public class SseApplication extends Application {
-    @Override
-    public Set<Class<?>> getClasses() {
-        return Collections.singleton(BookStore2.class);
-    }
-
-    @Override
-    public Set<Object> getSingletons() {
-        return Collections.singleton(new JacksonJsonProvider());
-    }
-}

Reply via email to