You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by ay...@apache.org on 2016/04/05 14:35:10 UTC

[1/8] cxf git commit: add the stacktrace output in CustomerService for CXF-5855

Repository: cxf
Updated Branches:
  refs/heads/3.1.x-fixes 91197fdb2 -> 75edfe9d2


add the stacktrace output in CustomerService for CXF-5855


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

Branch: refs/heads/3.1.x-fixes
Commit: f12eb1a2a2eb2220550cb25dcc54d62127d55244
Parents: 35f01c9
Author: Akitoshi Yoshida <ay...@apache.org>
Authored: Thu Mar 17 10:08:25 2016 +0100
Committer: Akitoshi Yoshida <ay...@apache.org>
Committed: Tue Apr 5 13:36:57 2016 +0200

----------------------------------------------------------------------
 .../src/main/java/demo/jaxrs/server/CustomerService.java         | 4 ++++
 1 file changed, 4 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/f12eb1a2/distribution/src/main/release/samples/jax_rs/websocket/src/main/java/demo/jaxrs/server/CustomerService.java
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket/src/main/java/demo/jaxrs/server/CustomerService.java b/distribution/src/main/release/samples/jax_rs/websocket/src/main/java/demo/jaxrs/server/CustomerService.java
index cc039ff..f77f8aa 100644
--- a/distribution/src/main/release/samples/jax_rs/websocket/src/main/java/demo/jaxrs/server/CustomerService.java
+++ b/distribution/src/main/release/samples/jax_rs/websocket/src/main/java/demo/jaxrs/server/CustomerService.java
@@ -186,6 +186,8 @@ public class CustomerService {
                         } catch (IOException e) {
                             System.out.println("----error writing to " + wh.getValue() + " " + wh.get());
                             if (wh.increment()) {
+                                // the max error count reached; purging the output resource
+                                e.printStackTrace();
                                 try {
                                     wh.getValue().close();
                                 } catch (IOException e2) {
@@ -205,6 +207,8 @@ public class CustomerService {
                         } catch (IOException e) {
                             System.out.println("----error writing to " + wh.getValue() + " " + wh.get());
                             if (wh.increment()) {
+                                // the max error count reached; purging the output resource
+                                e.printStackTrace();
                                 try {
                                     wh.getValue().getOutputStream().close();
                                 } catch (IOException e2) {


[6/8] cxf git commit: use a non-empty context-path for samples/jax_rs/websocket sample

Posted by ay...@apache.org.
use a non-empty context-path for samples/jax_rs/websocket sample


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

Branch: refs/heads/3.1.x-fixes
Commit: b52157a330d9ef4daab8d2826579cb68ca171c69
Parents: f12eb1a
Author: Akitoshi Yoshida <ay...@apache.org>
Authored: Wed Mar 23 14:23:03 2016 +0100
Committer: Akitoshi Yoshida <ay...@apache.org>
Committed: Tue Apr 5 13:36:58 2016 +0200

----------------------------------------------------------------------
 .../release/samples/jax_rs/websocket/README.txt | 26 ++++++++---------
 .../src/main/java/demo/jaxrs/client/Client.java | 29 ++++++++-----------
 .../src/main/java/demo/jaxrs/server/Server.java |  4 ++-
 .../websocket/src/main/resources/index.html     |  4 +--
 .../websocket/src/test/resources/client.js      | 30 +++++++++++---------
 5 files changed, 46 insertions(+), 47 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/b52157a3/distribution/src/main/release/samples/jax_rs/websocket/README.txt
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket/README.txt b/distribution/src/main/release/samples/jax_rs/websocket/README.txt
index f1d3455..8df709e 100644
--- a/distribution/src/main/release/samples/jax_rs/websocket/README.txt
+++ b/distribution/src/main/release/samples/jax_rs/websocket/README.txt
@@ -3,7 +3,7 @@ JAX-RS WebSocket Demo
 
 This is a websocket transport version of JAX-RS Basic Demo.
 
-A RESTful customer service is provided on URL ws://localhost:9000/customers. 
+A RESTful customer service is provided on URL ws://localhost:9000/demo
 Users access this URI to operate on customer.
 
 This sample includes two convenient clients: a plain javascript browser client
@@ -13,12 +13,12 @@ and a node.js client based on atmosphere.
 Connecting to the server
 ---------------------------------------
 
-Open a websocket to ws://localhost:9000/ and send requests over the websocket.
+Open a websocket to ws://localhost:9000/demo and send requests over the websocket.
 
-A GET request to path /customerservice/customers/123
+A GET request to path /demo/customerservice/customers/123
 
 ------------------------------------------------------------------------
-GET /customerservice/customers/123
+GET /demo/customerservice/customers/123
 ------------------------------------------------------------------------
 
 returns a customer instance whose id is 123. The XML document returned:
@@ -30,10 +30,10 @@ returns a customer instance whose id is 123. The XML document returned:
 </Customer>
 ------------------------------------------------------------------------
 
-A GET request to path /customerservice/orders/223/products/323
+A GET request to path /demo/customerservice/orders/223/products/323
 
 ------------------------------------------------------------------------
-GET /customerservice/orders/223/products/323
+GET /demo/customerservice/orders/223/products/323
 ------------------------------------------------------------------------
 
 returns product 323 that belongs to order 223. The XML document returned:
@@ -48,7 +48,7 @@ returns product 323 that belongs to order 223. The XML document returned:
 A POST request to path /customerservice/customers
 
 ------------------------------------------------------------------------
-POST /customerservice/customers
+POST /demo/customerservice/customers
 Content-Type: text/xml; charset="utf-8"
 ------------------------------------------------------------------------
 
@@ -63,7 +63,7 @@ with the data:
 adds a customer whose name is Jack 
 
 
-A PUT request to path /customerservice/customers
+A PUT request to path /demo/customerservice/customers
 
 ------------------------------------------------------------------------
 PUT /customerservice/customers
@@ -82,20 +82,20 @@ with the data:
 updates the customer instance whose id is 123
 
 
-A GET request to path /monitor with id monitor-12345
+A GET request to path /demo/monitor with id monitor-12345
 
 ------------------------------------------------------------------------
-GET /customerservice/monitor
+GET /demo/customerservice/monitor
 requestId: monitor-12345
 ------------------------------------------------------------------------
 
 returns a continuous event stream on the customer
 activities. Try invoking some customer related operations.
 
-A GET request to path /unmonitor with id monitor-12345
+A GET request to path /demo/unmonitor with id monitor-12345
 
 ------------------------------------------------------------------------
-GET /customerservice/unmonitor/monitor-12345
+GET /demo/customerservice/unmonitor/monitor-12345
 ------------------------------------------------------------------------
 
 unregisters the event stream and returns its status.
@@ -141,7 +141,7 @@ the content. For example, the above POST example should use the Request
 value:
 
 ------------------------------------------------------------------------
-POST /customerservice/customers
+POST /demo/customerservice/customers
 Content-Type: text/xml; charset="utf-8"
 
 <Customer>

http://git-wip-us.apache.org/repos/asf/cxf/blob/b52157a3/distribution/src/main/release/samples/jax_rs/websocket/src/main/java/demo/jaxrs/client/Client.java
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket/src/main/java/demo/jaxrs/client/Client.java b/distribution/src/main/release/samples/jax_rs/websocket/src/main/java/demo/jaxrs/client/Client.java
index dbdc589..1b91019 100644
--- a/distribution/src/main/release/samples/jax_rs/websocket/src/main/java/demo/jaxrs/client/Client.java
+++ b/distribution/src/main/release/samples/jax_rs/websocket/src/main/java/demo/jaxrs/client/Client.java
@@ -19,6 +19,8 @@
 
 package demo.jaxrs.client;
 
+import demo.jaxrs.server.Server;
+
 import java.io.InputStream;
 import java.util.List;
 
@@ -31,21 +33,14 @@ public final class Client {
     }
 
     public static void main(String args[]) throws Exception {
-        // Sent HTTP GET request to query all customer info
-        /*
-         * URL url = new URL("http://localhost:9000/customers");
-         * System.out.println("Invoking server through HTTP GET to query all
-         * customer info"); InputStream in = url.openStream(); StreamSource
-         * source = new StreamSource(in); printSource(source);
-         */
 
         // Create a websocket client and connect to the target service
-        WebSocketTestClient client = new WebSocketTestClient("ws://localhost:9000/");
+        WebSocketTestClient client = new WebSocketTestClient(Server.HOST_URL + Server.CONTEXT_PATH);
         client.connect();
 
         // Sent GET request to query customer info
         System.out.println("Sent GET request to query customer info");
-        client.sendTextMessage("GET /customerservice/customers/123");
+        client.sendTextMessage("GET " + Server.CONTEXT_PATH + "/customerservice/customers/123");
         client.await(5);
         List<WebSocketTestClient.Response> responses = client.getReceivedResponses();
         System.out.println(responses.get(0));
@@ -53,7 +48,7 @@ public final class Client {
         // Sent GET request to query sub resource product info
         client.reset(1);
         System.out.println("Sent GET request to query sub resource product info");
-        client.sendTextMessage("GET /customerservice/orders/223/products/323");
+        client.sendTextMessage("GET " + Server.CONTEXT_PATH + "/customerservice/orders/223/products/323");
         client.await(5);
         responses = client.getReceivedResponses();
         System.out.println(responses.get(0));
@@ -62,8 +57,8 @@ public final class Client {
         client.reset(1);
         System.out.println("Sent PUT request to update customer info");
         String inputData = getStringFromInputStream(Client.class.getResourceAsStream("/update_customer.xml"));
-        client.sendTextMessage("PUT /customerservice/customers\r\nContent-Type: text/xml;"
-                               + " charset=ISO-8859-1\r\n\r\n"
+        client.sendTextMessage("PUT " + Server.CONTEXT_PATH + "/customerservice/customers\r\n"
+                               + "Content-Type: text/xml; charset=ISO-8859-1\r\n\r\n"
                                + inputData);
         client.await(5);
         responses = client.getReceivedResponses();
@@ -73,20 +68,20 @@ public final class Client {
         client.reset(1);
         System.out.println("Sent POST request to add customer");
         inputData = getStringFromInputStream(Client.class.getResourceAsStream("/add_customer.xml"));
-        client.sendTextMessage("POST /customerservice/customers\r\nContent-Type: text/xml; "
+        client.sendTextMessage("POST " + Server.CONTEXT_PATH + "/customerservice/customers\r\nContent-Type: text/xml; "
                                + "charset=ISO-8859-1\r\nAccept: text/xml\r\n\r\n" + inputData);
         client.await(5);
         responses = client.getReceivedResponses();
         System.out.println(responses.get(0));
 
         // Create another websocket client and connect to the target service
-        WebSocketTestClient client2 = new WebSocketTestClient("ws://localhost:9000/");
+        WebSocketTestClient client2 = new WebSocketTestClient(Server.HOST_URL + Server.CONTEXT_PATH);
         client2.connect();
 
         // Sent GET request to monitor the customer activities
         client2.reset(1);
         System.out.println("Sent GET request to monitor activities");
-        client2.sendTextMessage("GET /customerservice/monitor");
+        client2.sendTextMessage("GET " + Server.CONTEXT_PATH + "/customerservice/monitor");
         client2.await(5);
         responses = client2.getReceivedResponses();
         System.out.println(responses.get(0));
@@ -94,8 +89,8 @@ public final class Client {
         // one retrieval, one delete
         client2.reset(2);
         client.reset(2);
-        client.sendTextMessage("GET /customerservice/customers/123");
-        client.sendTextMessage("DELETE /customerservice/customers/235");
+        client.sendTextMessage("GET " + Server.CONTEXT_PATH + "/customerservice/customers/123");
+        client.sendTextMessage("DELETE " + Server.CONTEXT_PATH + "/customerservice/customers/235");
 
         client2.await(5);
         responses = client2.getReceivedResponses();

http://git-wip-us.apache.org/repos/asf/cxf/blob/b52157a3/distribution/src/main/release/samples/jax_rs/websocket/src/main/java/demo/jaxrs/server/Server.java
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket/src/main/java/demo/jaxrs/server/Server.java b/distribution/src/main/release/samples/jax_rs/websocket/src/main/java/demo/jaxrs/server/Server.java
index fe59dd0..851a512 100644
--- a/distribution/src/main/release/samples/jax_rs/websocket/src/main/java/demo/jaxrs/server/Server.java
+++ b/distribution/src/main/release/samples/jax_rs/websocket/src/main/java/demo/jaxrs/server/Server.java
@@ -23,13 +23,15 @@ import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
 import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
 
 public class Server {
+    public static final String HOST_URL = "ws://localhost:9000";
+    public static final String CONTEXT_PATH = "/demo";
 
     protected Server() throws Exception {
         JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
         sf.setResourceClasses(CustomerService.class);
         sf.setResourceProvider(CustomerService.class, 
             new SingletonResourceProvider(new CustomerService()));
-        sf.setAddress("ws://localhost:9000/");
+        sf.setAddress(HOST_URL + CONTEXT_PATH);
 
         sf.create();
     }

http://git-wip-us.apache.org/repos/asf/cxf/blob/b52157a3/distribution/src/main/release/samples/jax_rs/websocket/src/main/resources/index.html
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket/src/main/resources/index.html b/distribution/src/main/release/samples/jax_rs/websocket/src/main/resources/index.html
index 87c8eaf..e7d81f4 100644
--- a/distribution/src/main/release/samples/jax_rs/websocket/src/main/resources/index.html
+++ b/distribution/src/main/release/samples/jax_rs/websocket/src/main/resources/index.html
@@ -29,14 +29,14 @@
 <div id="output">
   <div id="config" style="float: left;">
     <strong>Service Endpoint URL:</strong><br />
-    <input id="wsUri" size="72" style="width: 100%" value="ws://localhost:9000/"/>
+    <input id="wsUri" size="72" style="width: 100%" value="ws://localhost:9000/demo"/>
     <br/>
     <button id="connect">Connect</button>
     <button id="disconnect">Disconnect</button>
     <br />
     <br />
     <strong>Request:</strong><br />
-    <textarea id="request" rows="10" cols="72" style="width: 100%;">GET /customerservice/customers/123</textarea>
+    <textarea id="request" rows="10" cols="72" style="width: 100%;">GET /demo/customerservice/customers/123</textarea>
     <br/>
     <button id="send">Send</button>
   </div>

http://git-wip-us.apache.org/repos/asf/cxf/blob/b52157a3/distribution/src/main/release/samples/jax_rs/websocket/src/test/resources/client.js
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket/src/test/resources/client.js b/distribution/src/main/release/samples/jax_rs/websocket/src/test/resources/client.js
index 8e8d653..2df8d30 100644
--- a/distribution/src/main/release/samples/jax_rs/websocket/src/test/resources/client.js
+++ b/distribution/src/main/release/samples/jax_rs/websocket/src/test/resources/client.js
@@ -8,14 +8,16 @@
 
 "use strict";
 
-var HOST_URL = 'http://localhost:9000/';
+// set the host url and path if the service runs at a different location
+var HOST_URL = 'http://localhost:9000';
+var CONTEXT_PATH = "/demo"
 
 var reader = require('readline');
 var prompt = reader.createInterface(process.stdin, process.stdout);
 
 var atmosphere = require('atmosphere.js');
 
-var request = { url: HOST_URL,
+var request = { url: HOST_URL + CONTEXT_PATH,
                 transport : 'websocket',
                 trackMessageLength: false,
                 dropHeaders: false,
@@ -75,10 +77,10 @@ function doHelp() {
 function doAdd(v) {
     var req;
     if (transport == 'websocket') {
-        req = "POST /customerservice/customers\r\nContent-Type: text/xml; charset='utf-8'\r\nAccept: text/xml\r\n\r\n" 
+        req = "POST " + CONTEXT_PATH + "/customerservice/customers\r\nContent-Type: text/xml; charset='utf-8'\r\nAccept: text/xml\r\n\r\n" 
             + createAddCustomerPayload(v[0]);
     } else if (transport == 'sse') {
-        req = {"method": "POST", "url": HOST_URL + "customerservice/customers", "headers": {"content-type": "text/xml; charset=utf-8", "accept": "text/xml"}, "data": createAddCustomerPayload(v[0])}
+        req = {"method": "POST", "url": HOST_URL + CONTEXT_PATH + "/customerservice/customers", "headers": {"content-type": "text/xml; charset=utf-8", "accept": "text/xml"}, "data": createAddCustomerPayload(v[0])}
     }
     console.log("TRACE: sending ", req);
     subSocket.push(req);
@@ -87,9 +89,9 @@ function doAdd(v) {
 function doDelete(v) {
     var req;
     if (transport == 'websocket') {
-        req = "DELETE /customerservice/customers/" + v[0];
+        req = "DELETE" + CONTEXT_PATH + "/customerservice/customers/" + v[0];
     } else if (transport == 'sse') {
-        req = {"method": "DELETE", "url": HOST_URL + "customerservice/customers/" + v[0]}
+        req = {"method": "DELETE", "url": HOST_URL + CONTEXT_PATH + "/customerservice/customers/" + v[0]}
     }
     console.log("TRACE: sending ", req);
     subSocket.push(req);
@@ -98,9 +100,9 @@ function doDelete(v) {
 function doGet(v) {
     var req;
     if (transport == 'websocket') {
-        req = "GET /customerservice/customers/" + v[0];
+        req = "GET " + CONTEXT_PATH + "/customerservice/customers/" + v[0];
     } else if (transport == 'sse') {
-        req = {"method": "GET", "url": HOST_URL + "customerservice/customers/" + v[0]}
+        req = {"method": "GET", "url": HOST_URL + CONTEXT_PATH + "/customerservice/customers/" + v[0]}
     }
     console.log("TRACE: sending ", req);
     subSocket.push(req);
@@ -109,9 +111,9 @@ function doGet(v) {
 function doSubscribe() {
     var req;
     if (transport == 'websocket') {
-        req = "GET /customerservice/monitor\r\nAccept: text/plain\r\n";
+        req = "GET " + CONTEXT_PATH + "/customerservice/monitor\r\nAccept: text/plain\r\n";
     } else if (transport == 'sse') {
-        req = {"method": "GET", "url": HOST_URL + "customerservice/monitor2", "headers": {"accept": "text/plain"}}
+        req = {"method": "GET", "url": HOST_URL + CONTEXT_PATH + "/customerservice/monitor", "headers": {"accept": "text/plain"}}
     }
     console.log("TRACE: sending ", req);
     subSocket.push(req);
@@ -120,9 +122,9 @@ function doSubscribe() {
 function doUnsubscribe() {
     var req;
     if (transport == 'websocket') {
-        req = "GET /customerservice/unmonitor/*\r\nAccept: text/plain\r\n";
+        req = "GET " + CONTEXT_PATH + "/customerservice/unmonitor/*\r\nAccept: text/plain\r\n";
     } else if (transport == 'sse') {
-        req = {"method": "GET", "url": HOST_URL + "customerservice/unmonitor2/*", "headers": {"accept": "text/plain"}}
+        req = {"method": "GET", "url": HOST_URL + CONTEXT_PATH + "/customerservice/unmonitor/*", "headers": {"accept": "text/plain"}}
     }
     console.log("TRACE: sending ", req);
     subSocket.push(req);
@@ -131,10 +133,10 @@ function doUnsubscribe() {
 function doUpdate(v) {
     var req;
     if (transport == 'websocket') {
-        req = "PUT /customerservice/customers\r\nContent-Type: text/xml; charset='utf-8'\r\nAccept: text/xml\r\n\r\n" 
+        req = "PUT " + CONTEXT_PATH + "/customerservice/customers\r\nContent-Type: text/xml; charset='utf-8'\r\nAccept: text/xml\r\n\r\n" 
             + createUpdateCustomerPayload(v[0], v[1]);
     } else if (transport == 'sse') {
-        req = {"method": "PUT", "url": HOST_URL + "customerservice/customers", "headers": {"content-type": "text/xml; charset=utf-8", "accept": "text/xml"}, "data": createUpdateCustomerPayload(v[0], v[1])}
+        req = {"method": "PUT", "url": HOST_URL + CONTEXT_PATH + "/customerservice/customers", "headers": {"content-type": "text/xml; charset=utf-8", "accept": "text/xml"}, "data": createUpdateCustomerPayload(v[0], v[1])}
     }
     console.log("TRACE: sending ", req);
     subSocket.push(req);


[4/8] cxf git commit: [CXF-5855] enable atmosphere's sse handling; update the sample

Posted by ay...@apache.org.
[CXF-5855] enable atmosphere's sse handling; update the sample


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

Branch: refs/heads/3.1.x-fixes
Commit: a529d270668dabd1cfa6b040769cb25af97973db
Parents: 91197fd
Author: Akitoshi Yoshida <ay...@apache.org>
Authored: Thu Mar 17 00:11:58 2016 +0100
Committer: Akitoshi Yoshida <ay...@apache.org>
Committed: Tue Apr 5 13:36:57 2016 +0200

----------------------------------------------------------------------
 .../release/samples/jax_rs/websocket/README.txt |  26 ++-
 .../release/samples/jax_rs/websocket/pom.xml    |  10 +-
 .../java/demo/jaxrs/server/CustomerService.java | 105 ++++++++-
 .../websocket/src/test/resources/client.js      | 232 +++++++++++++++++++
 .../websocket/atmosphere/AtmosphereUtils.java   |  18 ++
 .../AtmosphereWebSocketJettyDestination.java    |   3 +-
 .../AtmosphereWebSocketServletDestination.java  |   3 +-
 .../atmosphere/DefaultProtocolInterceptor.java  |  90 ++++++-
 8 files changed, 463 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/a529d270/distribution/src/main/release/samples/jax_rs/websocket/README.txt
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket/README.txt b/distribution/src/main/release/samples/jax_rs/websocket/README.txt
index 09c43e8..f1d3455 100644
--- a/distribution/src/main/release/samples/jax_rs/websocket/README.txt
+++ b/distribution/src/main/release/samples/jax_rs/websocket/README.txt
@@ -6,6 +6,13 @@ This is a websocket transport version of JAX-RS Basic Demo.
 A RESTful customer service is provided on URL ws://localhost:9000/customers. 
 Users access this URI to operate on customer.
 
+This sample includes two convenient clients: a plain javascript browser client
+and a node.js client based on atmosphere.
+
+
+Connecting to the server
+---------------------------------------
+
 Open a websocket to ws://localhost:9000/ and send requests over the websocket.
 
 A GET request to path /customerservice/customers/123
@@ -102,7 +109,6 @@ Please review the README in the samples directory before
 continuing.
 
 
-
 Building and running the demo using maven
 ---------------------------------------
 
@@ -118,6 +124,8 @@ Using either UNIX or Windows:
 
 To remove the target dir, run mvn clean".
 
+Using Javascript client in Browser
+--------
 Using a web browser that natively supports WebSocket (Safari, Chrome, Firefox):
 After starting the server (see above), open the index.html page located at
 
@@ -140,3 +148,19 @@ Content-Type: text/xml; charset="utf-8"
   <name>Jack</name>
 </Customer>
 ------------------------------------------------------------------------
+
+
+Using Node.js client 
+--------
+
+Go to samples/jax_rs/websocket/src/test/resources and at the console
+
+Assuming node (>=v4) and npm are installed, execute the following shell commands.
+
+% npm install atmosphere.js
+% node client.js
+
+This client program supports websocket and sse and allows
+you to choose your preferred protocol.
+
+

http://git-wip-us.apache.org/repos/asf/cxf/blob/a529d270/distribution/src/main/release/samples/jax_rs/websocket/pom.xml
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket/pom.xml b/distribution/src/main/release/samples/jax_rs/websocket/pom.xml
index abe9d3b..353e544 100644
--- a/distribution/src/main/release/samples/jax_rs/websocket/pom.xml
+++ b/distribution/src/main/release/samples/jax_rs/websocket/pom.xml
@@ -32,6 +32,7 @@
         <cxf.version>${project.version}</cxf.version>
         <!-- TODO remove these local entries after making the referenced dependency managed in parent/pom.xml -->
         <cxf.ahc.version>1.8.5</cxf.ahc.version>
+        <cxf.atmosphere.version>2.3.7</cxf.atmosphere.version>
         <cxf.jetty8.version>8.1.15.v20140411</cxf.jetty8.version>
         <cxf.jetty9.version>9.2.2.v20140723</cxf.jetty9.version>
         <cxf.jetty.version>${cxf.jetty8.version}</cxf.jetty.version>
@@ -207,6 +208,13 @@
             <groupId>org.springframework</groupId>
             <artifactId>spring-core</artifactId>
         </dependency>
-        
+
+        <!-- add atmosphere -->
+        <dependency>
+            <groupId>org.atmosphere</groupId>
+            <artifactId>atmosphere-runtime</artifactId>
+            <version>${cxf.atmosphere.version}</version>
+        </dependency>
+                
     </dependencies>
 </project>

http://git-wip-us.apache.org/repos/asf/cxf/blob/a529d270/distribution/src/main/release/samples/jax_rs/websocket/src/main/java/demo/jaxrs/server/CustomerService.java
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket/src/main/java/demo/jaxrs/server/CustomerService.java b/distribution/src/main/release/samples/jax_rs/websocket/src/main/java/demo/jaxrs/server/CustomerService.java
index 967e978..cc039ff 100644
--- a/distribution/src/main/release/samples/jax_rs/websocket/src/main/java/demo/jaxrs/server/CustomerService.java
+++ b/distribution/src/main/release/samples/jax_rs/websocket/src/main/java/demo/jaxrs/server/CustomerService.java
@@ -25,6 +25,9 @@ import java.util.Iterator;
 import java.util.Map;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.servlet.http.HttpServletResponse;
 
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
@@ -43,13 +46,15 @@ import org.apache.cxf.transport.websocket.WebSocketConstants;
 @Path("/customerservice/")
 @Produces("text/xml")
 public class CustomerService {
+    private static final int MAX_ERROR_COUNT = 5;
     private static ExecutorService executor = Executors.newSingleThreadExecutor();
 
     long currentId = 123;
     Map<Long, Customer> customers = new HashMap<Long, Customer>();
     Map<Long, Order> orders = new HashMap<Long, Order>();
-    Map<String, OutputStream> monitors = new HashMap<String, OutputStream>();
-    
+    Map<String, WriterHolder<OutputStream>> monitors = new HashMap<String, WriterHolder<OutputStream>>();
+    Map<String, WriterHolder<HttpServletResponse>> monitors2 = new HashMap<String, WriterHolder<HttpServletResponse>>();
+
     public CustomerService() {
         init();
     }
@@ -60,7 +65,9 @@ public class CustomerService {
         System.out.println("----invoking getCustomer, Customer id is: " + id);
         long idNumber = Long.parseLong(id);
         Customer customer = customers.get(idNumber);
-        sendCustomerEvent("retrieved", customer);
+        if (customer != null) {
+            sendCustomerEvent("retrieved", customer);
+        }
         return customer;
     }
 
@@ -129,35 +136,83 @@ public class CustomerService {
         final String key = reqid == null ? "*" : reqid; 
         return new StreamingOutput() {
             public void write(final OutputStream out) throws IOException, WebApplicationException {
-                monitors.put(key, out);
+                monitors.put(key, new WriterHolder(out, MAX_ERROR_COUNT));
                 out.write(("Subscribed at " + new java.util.Date()).getBytes());
             }
+            
         };
     }
 
     @GET
+    @Path("/monitor2")
+    @Produces("text/*")
+    public void monitorCustomers2(
+            final @javax.ws.rs.core.Context HttpServletResponse httpResponse,
+            @HeaderParam(WebSocketConstants.DEFAULT_REQUEST_ID_KEY) String reqid) {
+        final String key = reqid == null ? "*" : reqid; 
+        monitors2.put(key, new WriterHolder(httpResponse, MAX_ERROR_COUNT));
+        try {
+            httpResponse.getOutputStream().write(("Subscribed at " + new java.util.Date()).getBytes());
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @GET
     @Path("/unmonitor/{key}")
     @Produces("text/*")
     public String unmonitorCustomers(@PathParam("key") String key) {
         return (monitors.remove(key) != null ? "Removed: " : "Already removed: ") + key; 
     }
 
+    @GET
+    @Path("/unmonitor2/{key}")
+    @Produces("text/*")
+    public String unmonitorCustomers2(@PathParam("key") String key) {
+        return (monitors2.remove(key) != null ? "Removed: " : "Already removed: ") + key; 
+    }
+
     private void sendCustomerEvent(final String msg, final Customer customer) {
         executor.execute(new Runnable() {
             public void run() {
                 try {
                     String t = msg + ": " + customer.getId() + "/" + customer.getName();
-                    for (Iterator<OutputStream> it = monitors.values().iterator(); it.hasNext();) {
-                        OutputStream out = it.next();
+                    for (Iterator<WriterHolder<OutputStream>> it = monitors.values().iterator(); it.hasNext();) {
+                        WriterHolder<OutputStream> wh = it.next();
                         try {
-                            out.write(t.getBytes());
+                            wh.getValue().write(t.getBytes());
+                            wh.getValue().flush();
+                            wh.reset();
                         } catch (IOException e) {
-                            try {
-                                out.close();
-                            } catch (IOException e2) {
-                                // ignore;
+                            System.out.println("----error writing to " + wh.getValue() + " " + wh.get());
+                            if (wh.increment()) {
+                                try {
+                                    wh.getValue().close();
+                                } catch (IOException e2) {
+                                    // ignore;
+                                }
+                                it.remove();
+                                System.out.println("----purged " + wh.getValue());
+                            }
+                        }
+                    }
+                    for (Iterator<WriterHolder<HttpServletResponse>> it = monitors2.values().iterator(); it.hasNext();) {
+                        WriterHolder<HttpServletResponse> wh = it.next();
+                        try {
+                            wh.getValue().getOutputStream().write(t.getBytes());
+                            wh.getValue().getOutputStream().flush();
+                            wh.reset();
+                        } catch (IOException e) {
+                            System.out.println("----error writing to " + wh.getValue() + " " + wh.get());
+                            if (wh.increment()) {
+                                try {
+                                    wh.getValue().getOutputStream().close();
+                                } catch (IOException e2) {
+                                    // ignore;
+                                }
+                                it.remove();
+                                System.out.println("----purged " + wh.getValue());
                             }
-                            it.remove();
                         }
                     }
                 } catch (Exception e) {
@@ -183,4 +238,30 @@ public class CustomerService {
         orders.put(o.getId(), o);
     }
 
+    private static class WriterHolder<T> {
+        final private T value;
+        final private int max; 
+        final private AtomicInteger errorCount;
+
+        public WriterHolder(T object, int max) {
+            this.value = object;
+            this.max = max;
+            this.errorCount = new AtomicInteger();
+        }
+
+        public T getValue() {
+            return value;
+        }
+
+        public int get() {
+            return errorCount.get();
+        }
+        public boolean increment() {
+            return max < errorCount.getAndIncrement();
+        }
+
+        public void reset() {
+            errorCount.getAndSet(0);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/a529d270/distribution/src/main/release/samples/jax_rs/websocket/src/test/resources/client.js
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket/src/test/resources/client.js b/distribution/src/main/release/samples/jax_rs/websocket/src/test/resources/client.js
new file mode 100644
index 0000000..7eb55f3
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/websocket/src/test/resources/client.js
@@ -0,0 +1,232 @@
+/**
+ * client.js
+ * 
+ * A client program to interact with samples/jax_rs/websocket's server.
+ * 
+ * 
+ */
+
+"use strict";
+
+var HOST_URL = 'http://localhost:9100/';
+
+var reader = require('readline');
+var prompt = reader.createInterface(process.stdin, process.stdout);
+
+var atmosphere = require('atmosphere.js');
+
+var request = { url: HOST_URL,
+                transport : 'websocket',
+                trackMessageLength: false,
+                dropHeaders: false,
+                reconnectInterval : 5000};
+var isopen = false;
+
+const TRANSPORT_NAMES = ["websocket", "sse"];
+
+const COMMAND_LIST = 
+    [["add name",       "Add a new consumer and return the customer instance."],
+     ["delete id",      "Delete the customer."],
+     ["get id",         "Return the customere."],
+     ["quit",           "Quit the application."],
+     ["subscribe",      "Subscribe to the customer updatese."],
+     ["unsubscribe",    "Unsubscribe from the customer updatese."],
+     ["update id name", "Update the customer."]];
+
+function selectOption(c, opts) {
+    var i = parseInt(c);
+    if (!(i >= 0 && i < opts.length)) {
+        console.log('Invalid selection: ' + c + '; Using ' + opts[0]);
+        i = 0;
+    }
+    return opts[i];
+}
+
+function getArgs(name, msg) {
+    var sp = name.length;
+    if (msg.length > name.length && msg.charAt(name.length) != ' ') {
+        // remove the command suffix
+        sp = msg.indexOf(' ', name.length);
+        if (sp < 0) {
+            sp = msg.length;
+        }
+    }
+    return msg.substring(sp).trim().split(' ');
+}
+
+function createAddCustomerPayload(name) {
+    return "<?xml version=\"1.0\"?>\n<Customer>\n    <name>" + name + "</name>\n</Customer>\n";
+}
+
+function createUpdateCustomerPayload(id, name) {
+    return "<?xml version=\"1.0\"?>\n<Customer>\n    <name>" + name + "</name>\n    <id>" + id + "</id>\n</Customer>\n";
+}
+
+///
+
+function doHelp() {
+    console.log('Available commands');
+    for (var i = 0; i < COMMAND_LIST.length; i++) { 
+        var c = COMMAND_LIST[i][0];
+        console.log(c + "                    ".substring(0, 20 - c.length) + COMMAND_LIST[i][1]);
+    }
+}
+
+function doAdd(v) {
+    var req;
+    if (transport == 'websocket') {
+        req = "POST /customerservice/customers\r\nContent-Type: text/xml; charset='utf-8'\r\nAccept: text/xml\r\n\r\n" 
+            + createAddCustomerPayload(v[0]);
+    } else if (transport == 'sse') {
+        req = {"method": "POST", "url": HOST_URL + "customerservice/customers", "headers": {"content-type": "text/xml; charset=utf-8", "accept": "text/xml"}, "data": createAddCustomerPayload(v[0])}
+    }
+    console.log("TRACE: sending ", req);
+    subSocket.push(req);
+}
+
+function doDelete(v) {
+    var req;
+    if (transport == 'websocket') {
+        req = "DELETE /customerservice/customers/" + v[0];
+    } else if (transport == 'sse') {
+        req = {"method": "DELETE", "url": HOST_URL + "customerservice/customers/" + v[0]}
+    }
+    console.log("TRACE: sending ", req);
+    subSocket.push(req);
+}
+
+function doGet(v) {
+    var req;
+    if (transport == 'websocket') {
+        req = "GET /customerservice/customers/" + v[0];
+    } else if (transport == 'sse') {
+        req = {"method": "GET", "url": HOST_URL + "customerservice/customers/" + v[0]}
+    }
+    console.log("TRACE: sending ", req);
+    subSocket.push(req);
+}
+
+function doSubscribe() {
+    var req;
+    if (transport == 'websocket') {
+        req = "GET /customerservice/monitor\r\nAccept: text/plain\r\n";
+    } else if (transport == 'sse') {
+        req = {"method": "GET", "url": HOST_URL + "customerservice/monitor2", "headers": {"accept": "text/plain"}}
+    }
+    console.log("TRACE: sending ", req);
+    subSocket.push(req);
+}
+
+function doUnsubscribe() {
+    var req;
+    if (transport == 'websocket') {
+        req = "GET /customerservice/unmonitor/*\r\nAccept: text/plain\r\n";
+    } else if (transport == 'sse') {
+        req = {"method": "GET", "url": HOST_URL + "customerservice/unmonitor2/*", "headers": {"accept": "text/plain"}}
+    }
+    console.log("TRACE: sending ", req);
+    subSocket.push(req);
+}
+
+function doUpdate(v) {
+    var req;
+    if (transport == 'websocket') {
+        req = "PUT /customerservice/customers\r\nContent-Type: text/xml; charset='utf-8'\r\nAccept: text/xml\r\n\r\n" 
+            + createUpdateCustomerPayload(v[0], v[1]);
+    } else if (transport == 'sse') {
+        req = {"method": "PUT", "url": HOST_URL + "customerservice/customers", "headers": {"content-type": "text/xml; charset=utf-8", "accept": "text/xml"}, "data": createUpdateCustomerPayload(v[0], v[1])}
+    }
+    console.log("TRACE: sending ", req);
+    subSocket.push(req);
+}
+
+function doQuit() {
+    subSocket.close();
+    process.exit(0);
+}
+
+///
+
+request.onOpen = function(response) {
+    isopen = true;
+    console.log('Connected using ' + response.transport);
+    prompt.setPrompt("> ", 2);
+    prompt.prompt();
+};
+
+request.onMessage = function (response) {
+    var message = response.responseBody;
+    console.log('Received: ', message);
+    console.log('------------------------------------------------------------------------');
+    prompt.setPrompt("> ", 2);
+    prompt.prompt();
+};
+
+request.onReconnect = function(response) {
+    console.log('Reconnecting ...');
+}
+
+request.onReopen = function(response) {
+    isopen = true;
+    console.log('Reconnected using ' + response.transport);
+    prompt.setPrompt("> ", 2);
+    prompt.prompt();
+}
+
+request.onClose = function(response) {
+    isopen = false;
+}
+
+request.onError = function(response) {
+    console.log("Sorry, something went wrong: " + response.responseBody);
+};
+
+var transport = null;
+var subSocket = null;
+var author = null;
+
+console.log("Select transport ...");
+for (var i = 0; i < TRANSPORT_NAMES.length; i++) { 
+    console.log(i + ": " + TRANSPORT_NAMES[i]);
+}
+prompt.setPrompt("select: ", 6);
+prompt.prompt();
+
+prompt.
+on('line', function(line) {
+    var msg = line.trim();
+    if (transport == null) {
+        transport = selectOption(msg, TRANSPORT_NAMES);
+        request.transport = transport;
+        subSocket = atmosphere.subscribe(request);
+        console.log("Connecting using " + transport);
+        setTimeout(function() {
+            if (!isopen) {
+                console.log("Unable to open a connection. Terminated.");
+                process.exit(0);
+            }
+        }, 3000);
+    } else if (msg.length == 0) {
+        doHelp();
+    } else if (msg.indexOf("add") == 0) {
+        doAdd(getArgs("add", msg));
+    } else if (msg.indexOf("del") == 0) {
+        doDelete(getArgs("del", msg));
+    } else if (msg.indexOf("get") == 0) {
+        doGet(getArgs("get", msg));
+    } else if (msg.indexOf("quit") == 0) {
+        doQuit();
+    } else if (msg.indexOf("sub") == 0) {
+        doSubscribe(getArgs("sub", msg));
+    } else if (msg.indexOf("unsub") == 0) {
+        doUnsubscribe(getArgs("unsub", msg));
+    } else if (msg.indexOf("update") == 0) {
+        doUpdate(getArgs("update", msg));
+    }
+    prompt.setPrompt("> ", 2);
+    prompt.prompt();
+}).
+on('close', function() {
+    console.log("close");
+    process.exit(0);
+});

http://git-wip-us.apache.org/repos/asf/cxf/blob/a529d270/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/atmosphere/AtmosphereUtils.java
----------------------------------------------------------------------
diff --git a/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/atmosphere/AtmosphereUtils.java b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/atmosphere/AtmosphereUtils.java
index 1a4a9b5..079792c 100644
--- a/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/atmosphere/AtmosphereUtils.java
+++ b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/atmosphere/AtmosphereUtils.java
@@ -21,10 +21,18 @@ package org.apache.cxf.transport.websocket.atmosphere;
 
 import java.util.List;
 
+import javax.servlet.http.HttpServletRequest;
+
 import org.apache.cxf.Bus;
 import org.apache.cxf.helpers.CastUtils;
 import org.atmosphere.cpr.AtmosphereFramework;
 import org.atmosphere.cpr.AtmosphereInterceptor;
+import org.atmosphere.cpr.HeaderConfig;
+import org.atmosphere.interceptor.CacheHeadersInterceptor;
+import org.atmosphere.interceptor.HeartbeatInterceptor;
+import org.atmosphere.interceptor.JavaScriptProtocol;
+import org.atmosphere.interceptor.SSEAtmosphereInterceptor;
+import org.atmosphere.util.Utils;
 
 /**
  * 
@@ -36,6 +44,10 @@ public final class AtmosphereUtils {
 
     public static void addInterceptors(AtmosphereFramework framework, Bus bus) {
         Object ais = bus.getProperty("atmosphere.interceptors");
+        // pre-install those atmosphere default interceptors before the custom interceptors.
+        framework.interceptor(new CacheHeadersInterceptor()).interceptor(new HeartbeatInterceptor())
+        .interceptor(new SSEAtmosphereInterceptor()).interceptor(new JavaScriptProtocol());
+
         if (ais == null || ais instanceof AtmosphereInterceptor) {
             framework.interceptor(ais == null 
                 ? new DefaultProtocolInterceptor() : (AtmosphereInterceptor)ais);
@@ -43,9 +55,15 @@ public final class AtmosphereUtils {
         }
         if (ais instanceof List<?>) {
             List<AtmosphereInterceptor> icps = CastUtils.cast((List<?>)ais);
+            // add the custom interceptors
             for (AtmosphereInterceptor icp : icps) {
                 framework.interceptor(icp);
             }
         }
     }
+    
+    public static boolean useAtmosphere(HttpServletRequest req) {
+        return Utils.webSocketEnabled(req) 
+            || req.getParameter(HeaderConfig.X_ATMOSPHERE_TRANSPORT) != null; 
+    }
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/a529d270/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/atmosphere/AtmosphereWebSocketJettyDestination.java
----------------------------------------------------------------------
diff --git a/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/atmosphere/AtmosphereWebSocketJettyDestination.java b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/atmosphere/AtmosphereWebSocketJettyDestination.java
index 0e02923..d0cc806 100644
--- a/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/atmosphere/AtmosphereWebSocketJettyDestination.java
+++ b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/atmosphere/AtmosphereWebSocketJettyDestination.java
@@ -45,7 +45,6 @@ import org.atmosphere.cpr.AtmosphereRequest;
 import org.atmosphere.cpr.AtmosphereResource;
 import org.atmosphere.cpr.AtmosphereResponse;
 import org.atmosphere.handler.AbstractReflectorAtmosphereHandler;
-import org.atmosphere.util.Utils;
 import org.eclipse.jetty.server.Request;
 
 
@@ -119,7 +118,7 @@ public class AtmosphereWebSocketJettyDestination extends JettyHTTPDestination im
         @Override
         public void handle(String target, Request baseRequest, HttpServletRequest request,
                            HttpServletResponse response) throws IOException, ServletException {
-            if (Utils.webSocketEnabled(request)) {
+            if (AtmosphereUtils.useAtmosphere(request)) {
                 try {
                     framework.doCometSupport(AtmosphereRequest.wrap(request), 
                                              AtmosphereResponse.wrap(response));

http://git-wip-us.apache.org/repos/asf/cxf/blob/a529d270/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/atmosphere/AtmosphereWebSocketServletDestination.java
----------------------------------------------------------------------
diff --git a/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/atmosphere/AtmosphereWebSocketServletDestination.java b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/atmosphere/AtmosphereWebSocketServletDestination.java
index 6459150..a4e702c 100644
--- a/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/atmosphere/AtmosphereWebSocketServletDestination.java
+++ b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/atmosphere/AtmosphereWebSocketServletDestination.java
@@ -41,7 +41,6 @@ import org.atmosphere.cpr.AtmosphereRequest;
 import org.atmosphere.cpr.AtmosphereResource;
 import org.atmosphere.cpr.AtmosphereResponse;
 import org.atmosphere.handler.AbstractReflectorAtmosphereHandler;
-import org.atmosphere.util.Utils;
 
 /**
  * 
@@ -69,7 +68,7 @@ public class AtmosphereWebSocketServletDestination extends ServletDestination im
     @Override
     public void invoke(ServletConfig config, ServletContext context, HttpServletRequest req,
                        HttpServletResponse resp) throws IOException {
-        if (Utils.webSocketEnabled(req)) {
+        if (AtmosphereUtils.useAtmosphere(req)) {
             try {
                 framework.doCometSupport(AtmosphereRequest.wrap(req), 
                                          AtmosphereResponse.wrap(resp));

http://git-wip-us.apache.org/repos/asf/cxf/blob/a529d270/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/atmosphere/DefaultProtocolInterceptor.java
----------------------------------------------------------------------
diff --git a/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/atmosphere/DefaultProtocolInterceptor.java b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/atmosphere/DefaultProtocolInterceptor.java
index 1a2cd9a..2631d51 100644
--- a/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/atmosphere/DefaultProtocolInterceptor.java
+++ b/rt/transports/websocket/src/main/java/org/apache/cxf/transport/websocket/atmosphere/DefaultProtocolInterceptor.java
@@ -37,8 +37,8 @@ import org.apache.cxf.io.CachedOutputStream;
 import org.apache.cxf.transport.websocket.InvalidPathException;
 import org.apache.cxf.transport.websocket.WebSocketConstants;
 import org.apache.cxf.transport.websocket.WebSocketUtils;
-import org.atmosphere.config.service.AtmosphereInterceptorService;
 import org.atmosphere.cpr.Action;
+import org.atmosphere.cpr.ApplicationConfig;
 import org.atmosphere.cpr.AsyncIOInterceptor;
 import org.atmosphere.cpr.AsyncIOInterceptorAdapter;
 import org.atmosphere.cpr.AsyncIOWriter;
@@ -48,20 +48,24 @@ import org.atmosphere.cpr.AtmosphereInterceptorAdapter;
 import org.atmosphere.cpr.AtmosphereInterceptorWriter;
 import org.atmosphere.cpr.AtmosphereRequest;
 import org.atmosphere.cpr.AtmosphereResource;
+import org.atmosphere.cpr.AtmosphereResourceEvent;
+import org.atmosphere.cpr.AtmosphereResourceEventListenerAdapter;
 import org.atmosphere.cpr.AtmosphereResponse;
 import org.atmosphere.cpr.FrameworkConfig;
 
 /**
  * DefaultProtocolInterceptor provides the default CXF's WebSocket protocol that uses.
  * 
+ * This interceptor is automatically engaged when no atmosphere interceptor is configured.  
  */
-@AtmosphereInterceptorService
 public class DefaultProtocolInterceptor extends AtmosphereInterceptorAdapter {
     private static final Logger LOG = LogUtils.getL7dLogger(DefaultProtocolInterceptor.class);
 
     private static final String REQUEST_DISPATCHED = "request.dispatched";
     private static final String RESPONSE_PARENT = "response.parent";
 
+    private Map<String, AtmosphereResponse> suspendedResponses = new HashMap<String, AtmosphereResponse>();
+
     private final AsyncIOInterceptor interceptor = new Interceptor();
 
     private Pattern includedheaders;
@@ -102,10 +106,77 @@ public class DefaultProtocolInterceptor extends AtmosphereInterceptorAdapter {
         this.excludedheaders = excludedheaders;
     }
 
-    @SuppressWarnings("deprecation")
     @Override
     public Action inspect(final AtmosphereResource r) {
         LOG.log(Level.FINE, "inspect");
+        if (AtmosphereResource.TRANSPORT.WEBSOCKET != r.transport() 
+            && AtmosphereResource.TRANSPORT.SSE != r.transport()
+            && AtmosphereResource.TRANSPORT.POLLING != r.transport()) {
+            LOG.fine("Skipping ignorable request");
+            return Action.CONTINUE;
+        }
+        if (AtmosphereResource.TRANSPORT.POLLING == r.transport()) {
+            final String saruuid = (String)r.getRequest()
+                .getAttribute(ApplicationConfig.SUSPENDED_ATMOSPHERE_RESOURCE_UUID);
+            final AtmosphereResponse suspendedResponse = suspendedResponses.get(saruuid);
+            LOG.fine("Attaching a proxy writer to suspended response");
+            r.getResponse().asyncIOWriter(new AtmosphereInterceptorWriter() {
+                @Override
+                public AsyncIOWriter write(AtmosphereResponse r, String data) throws IOException {
+                    suspendedResponse.write(data);
+                    suspendedResponse.flushBuffer();
+                    return this;
+                }
+
+                @Override
+                public AsyncIOWriter write(AtmosphereResponse r, byte[] data) throws IOException {
+                    suspendedResponse.write(data);
+                    suspendedResponse.flushBuffer();
+                    return this;
+                }
+
+                @Override
+                public AsyncIOWriter write(AtmosphereResponse r, byte[] data, int offset, int length) 
+                    throws IOException {
+                    suspendedResponse.write(data, offset, length);
+                    suspendedResponse.flushBuffer();
+                    return this;
+                }
+            });
+            // REVISIT we need to keep this response's asyncwriter alive so that data can be written to the 
+            //   suspended response, but investigate if there is a better alternative. 
+            r.getResponse().destroyable(false);
+            return Action.CONTINUE;
+        }
+
+        r.addEventListener(new AtmosphereResourceEventListenerAdapter() {
+            @Override
+            public void onSuspend(AtmosphereResourceEvent event) {
+                final String srid = (String)event.getResource().getRequest()
+                    .getAttribute(ApplicationConfig.SUSPENDED_ATMOSPHERE_RESOURCE_UUID);
+                LOG.log(Level.FINE, "Registrering suspended resource: {}", srid);
+                suspendedResponses.put(srid, event.getResource().getResponse());
+
+                AsyncIOWriter writer = event.getResource().getResponse().getAsyncIOWriter();
+                if (writer == null) {
+                    writer = new AtmosphereInterceptorWriter();
+                    r.getResponse().asyncIOWriter(writer);
+                }
+                if (writer instanceof AtmosphereInterceptorWriter) {
+                    ((AtmosphereInterceptorWriter)writer).interceptor(interceptor);
+                }
+            }
+
+            @Override
+            public void onDisconnect(AtmosphereResourceEvent event) {
+                super.onDisconnect(event);
+                final String srid = (String)event.getResource().getRequest()
+                    .getAttribute(ApplicationConfig.SUSPENDED_ATMOSPHERE_RESOURCE_UUID);
+                LOG.log(Level.FINE, "Unregistrering suspended resource: {}", srid);
+                suspendedResponses.remove(srid);
+            }
+
+        });
         AtmosphereRequest request = r.getRequest();
 
         if (request.getAttribute(REQUEST_DISPATCHED) == null) {
@@ -115,6 +186,11 @@ public class DefaultProtocolInterceptor extends AtmosphereInterceptorAdapter {
             try {
                 byte[] data = WebSocketUtils.readBody(request.getInputStream());
                 if (data.length == 0) {
+                    if (AtmosphereResource.TRANSPORT.WEBSOCKET == r.transport() 
+                        || AtmosphereResource.TRANSPORT.SSE == r.transport()) {
+                        r.suspend();
+                        return Action.SUSPEND;
+                    }
                     return Action.CANCELLED;
                 }
                 
@@ -124,10 +200,10 @@ public class DefaultProtocolInterceptor extends AtmosphereInterceptorAdapter {
                 try {
                     AtmosphereRequest ar = createAtmosphereRequest(request, data);
                     response = new WrappedAtmosphereResponse(r.getResponse(), ar);
-                    ar.attributes().put(REQUEST_DISPATCHED, "true");
+                    ar.localAttributes().put(REQUEST_DISPATCHED, "true");
                     String refid = ar.getHeader(WebSocketConstants.DEFAULT_REQUEST_ID_KEY);
                     if (refid != null) {
-                        ar.attributes().put(WebSocketConstants.DEFAULT_REQUEST_ID_KEY, refid);
+                        ar.localAttributes().put(WebSocketConstants.DEFAULT_REQUEST_ID_KEY, refid);
                     }
                     // This is a new request, we must clean the Websocket AtmosphereResource.
                     request.removeAttribute(FrameworkConfig.INJECTED_ATMOSPHERE_RESOURCE);
@@ -156,7 +232,6 @@ public class DefaultProtocolInterceptor extends AtmosphereInterceptorAdapter {
                 return Action.CANCELLED;
             } catch (IOException e) {
                 LOG.log(Level.WARNING, "Error during protocol processing", e);
-                return Action.CONTINUE;
             }           
         } else {
             request.destroyable(false);
@@ -229,6 +304,9 @@ public class DefaultProtocolInterceptor extends AtmosphereInterceptorAdapter {
         AtmosphereRequest request = response.request();
         String refid = (String)request.getAttribute(WebSocketConstants.DEFAULT_REQUEST_ID_KEY);
 
+        if (AtmosphereResource.TRANSPORT.WEBSOCKET != response.resource().transport()) {
+            return payload; 
+        }
         Map<String, String> headers = new HashMap<String, String>();
         if (refid != null) {
             response.addHeader(WebSocketConstants.DEFAULT_RESPONSE_ID_KEY, refid);


[7/8] cxf git commit: add a blueprint version of websocket sample for karaf

Posted by ay...@apache.org.
add a blueprint version of websocket sample for karaf


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

Branch: refs/heads/3.1.x-fixes
Commit: 5ce682771ae91eab61e25eaa90ef416168eb4402
Parents: de9b793
Author: Akitoshi Yoshida <ay...@apache.org>
Authored: Tue Apr 5 10:38:42 2016 +0200
Committer: Akitoshi Yoshida <ay...@apache.org>
Committed: Tue Apr 5 13:36:58 2016 +0200

----------------------------------------------------------------------
 .../samples/jax_rs/websocket_osgi/README.txt    |  94 +++++++
 .../samples/jax_rs/websocket_osgi/pom.xml       |  94 +++++++
 .../main/java/demo/jaxrs/server/Customer.java   |  43 +++
 .../java/demo/jaxrs/server/CustomerService.java | 271 +++++++++++++++++++
 .../src/main/java/demo/jaxrs/server/Order.java  |  69 +++++
 .../main/java/demo/jaxrs/server/Product.java    |  43 +++
 .../resources/OSGI-INF/blueprint/context.xml    |  47 ++++
 .../websocket_osgi/src/test/resources/client.js | 234 ++++++++++++++++
 8 files changed, 895 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/5ce68277/distribution/src/main/release/samples/jax_rs/websocket_osgi/README.txt
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket_osgi/README.txt b/distribution/src/main/release/samples/jax_rs/websocket_osgi/README.txt
new file mode 100644
index 0000000..60d7705
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/websocket_osgi/README.txt
@@ -0,0 +1,94 @@
+JAX-RS WebSocket OSGi Blueprint Demo 
+=================
+
+This is an OSGi Blueprint version of JAX-RS WebSocket Demo.
+
+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
+
+This will produce a war file in the target folder.
+
+
+Starting Karaf (refer to http://karaf.apache.org/manual/latest-3.0.x/quick-start.html)
+
+  bin/karaf
+
+
+          __ __                  ____      
+         / //_/____ __________ _/ __/      
+        / ,<  / __ `/ ___/ __ `/ /_        
+       / /| |/ /_/ / /  / /_/ / __/        
+      /_/ |_|\__,_/_/   \__,_/_/         
+  
+    Apache Karaf (3.0.4)
+  
+  Hit '<tab>' for a list of available commands
+  and '[cmd] --help' for help on a specific command.
+  Hit '<ctrl-d>' or type 'system:shutdown' or 'logout' to shutdown Karaf.
+
+
+In order to install CXF's features, you need to add the CXF's features repo using
+
+  feature:repo-add cxf 3.n.m
+
+ where 3.n.m corresponds to a valid CXF version number
+
+Install CXF's cxf-jaxrs and cxf-transports-websocket-server features that installs all the required bundles
+for this demo bundle.
+
+  feature:install cxf-jaxrs cxf-transports-websocket-server
+
+Install this demo bundle (using the appropriate bundle version number)
+
+  install -s mvn:org.apache.cxf.samples/jax_rs_websocket_osgi/3.n.m
+
+And verify the bundles are installed.
+
+karaf@root()> feature:repo-add cxf 3.2.0-SNAPSHOT
+Adding feature url mvn:org.apache.cxf.karaf/apache-cxf/3.2.0-SNAPSHOT/xml/features
+karaf@root()> feature:install cxf-jaxrs cxf-transports-websocket-server
+karaf@root()> list -t 0 | grep CXF
+ 80 | Active   |  40 | 3.2.0.SNAPSHOT   | Apache CXF Core                                                    
+ 81 | Active   |  40 | 3.2.0.SNAPSHOT   | Apache CXF Runtime Management                                      
+100 | Active   |  40 | 3.2.0.SNAPSHOT   | Apache CXF Runtime HTTP Transport                                  
+102 | Active   |  40 | 3.2.0.SNAPSHOT   | Apache CXF JAX-RS Extensions: Providers                            
+103 | Active   |  40 | 3.2.0.SNAPSHOT   | Apache CXF JAX-RS Extensions: Search                               
+104 | Active   |  40 | 3.2.0.SNAPSHOT   | Apache CXF JAX-RS Service Description                              
+105 | Active   |  40 | 3.2.0.SNAPSHOT   | Apache CXF Runtime JAX-RS Frontend                                 
+106 | Active   |  40 | 3.2.0.SNAPSHOT   | Apache CXF JAX-RS Client                                           
+108 | Active   |  40 | 3.2.0.SNAPSHOT   | Apache CXF Runtime WebSocket Transport                             
+karaf@root()> install -s mvn:org.apache.cxf.samples/jax_rs_websocket_osgi
+Bundle ID: 109
+karaf@root()> list
+START LEVEL 100 , List Threshold: 50
+ ID | State  | Lvl | Version        | Name                           
+---------------------------------------------------------------------
+107 | Active |  80 | 2.4.3          | atmosphere-runtime             
+109 | Active |  80 | 3.2.0.SNAPSHOT | JAX-RS WebSocket Blueprint Demo
+karaf@root()>
+
+
+Visit http://localhost:8181/cxf/ to see if this RESTful service is registered.
+
+Using Node.js client to test the service
+--------
+
+Go to samples/jax_rs/websocket_osgi/src/test/resources and at the console
+
+Assuming node (>=v4) and npm are installed, execute the following shell commands.
+
+% npm install atmosphere.js
+% node client.js
+
+This client program supports websocket and sse and allows
+you to choose your preferred protocol.
+
+

http://git-wip-us.apache.org/repos/asf/cxf/blob/5ce68277/distribution/src/main/release/samples/jax_rs/websocket_osgi/pom.xml
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket_osgi/pom.xml b/distribution/src/main/release/samples/jax_rs/websocket_osgi/pom.xml
new file mode 100644
index 0000000..e0d1234
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/websocket_osgi/pom.xml
@@ -0,0 +1,94 @@
+<?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_websocket_osgi</artifactId>
+    <packaging>bundle</packaging>
+    <name>JAX-RS WebSocket Blueprint Demo</name>
+    <description>JAX-RS WebSocket Demo</description>
+
+    <parent>
+        <groupId>org.apache.cxf.samples</groupId>
+        <artifactId>cxf-samples</artifactId>
+        <version>3.2.0-SNAPSHOT</version>
+        <relativePath>../..</relativePath>
+    </parent>
+    <properties>
+        <cxf.version>${project.version}</cxf.version>
+        <!-- TODO remove these local entries after making the referenced dependency managed in parent/pom.xml -->
+        <cxf.atmosphere.version>2.4.3</cxf.atmosphere.version>
+        <cxf.jetty92.version>9.2.15.v20160210</cxf.jetty92.version>
+        <cxf.jetty93.version>9.3.5.v20151012</cxf.jetty93.version>
+        <cxf.jetty.version>${cxf.jetty93.version}</cxf.jetty.version>
+    </properties>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-SymbolicName>${project.groupId}.${project.artifactId};blueprint.aries.xml-validation:=false</Bundle-SymbolicName>
+                        <Import-Package>
+                            javax.ws.rs,
+                            javax.ws.rs.core,
+                            org.apache.cxf.jaxrs.provider,
+                            org.osgi.service.blueprint,
+                            *
+                        </Import-Package>
+                        <Export-Package>
+                        </Export-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <dependencies>
+        <!-- cxt et al -->
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-transports-http</artifactId>
+            <version>3.2.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-transports-websocket</artifactId>
+            <version>3.2.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+            <version>3.2.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>javax.ws.rs</groupId>
+            <artifactId>javax.ws.rs-api</artifactId>
+        </dependency>
+
+        <!-- add atmosphere -->
+        <dependency>
+            <groupId>org.atmosphere</groupId>
+            <artifactId>atmosphere-runtime</artifactId>
+            <version>${cxf.atmosphere.version}</version>
+        </dependency>
+                
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/cxf/blob/5ce68277/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/main/java/demo/jaxrs/server/Customer.java
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/main/java/demo/jaxrs/server/Customer.java b/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/main/java/demo/jaxrs/server/Customer.java
new file mode 100644
index 0000000..44025f0
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/main/java/demo/jaxrs/server/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 demo.jaxrs.server;
+
+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;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5ce68277/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/main/java/demo/jaxrs/server/CustomerService.java
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/main/java/demo/jaxrs/server/CustomerService.java b/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/main/java/demo/jaxrs/server/CustomerService.java
new file mode 100644
index 0000000..f77f8aa
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/main/java/demo/jaxrs/server/CustomerService.java
@@ -0,0 +1,271 @@
+/**
+ * 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 demo.jaxrs.server;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.servlet.http.HttpServletResponse;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.StreamingOutput;
+
+import org.apache.cxf.transport.websocket.WebSocketConstants;
+
+@Path("/customerservice/")
+@Produces("text/xml")
+public class CustomerService {
+    private static final int MAX_ERROR_COUNT = 5;
+    private static ExecutorService executor = Executors.newSingleThreadExecutor();
+
+    long currentId = 123;
+    Map<Long, Customer> customers = new HashMap<Long, Customer>();
+    Map<Long, Order> orders = new HashMap<Long, Order>();
+    Map<String, WriterHolder<OutputStream>> monitors = new HashMap<String, WriterHolder<OutputStream>>();
+    Map<String, WriterHolder<HttpServletResponse>> monitors2 = new HashMap<String, WriterHolder<HttpServletResponse>>();
+
+    public CustomerService() {
+        init();
+    }
+
+    @GET
+    @Path("/customers/{id}/")
+    public Customer getCustomer(@PathParam("id") String id) {
+        System.out.println("----invoking getCustomer, Customer id is: " + id);
+        long idNumber = Long.parseLong(id);
+        Customer customer = customers.get(idNumber);
+        if (customer != null) {
+            sendCustomerEvent("retrieved", customer);
+        }
+        return customer;
+    }
+
+    @PUT
+    @Path("/customers/")
+    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();
+            sendCustomerEvent("updated", customer);
+        } else {
+            r = Response.notModified().build();
+        }
+
+        return r;
+    }
+
+    @POST
+    @Path("/customers/")
+    public Response addCustomer(Customer customer) {
+        System.out.println("----invoking addCustomer, Customer name is: " + customer.getName());
+        customer.setId(++currentId);
+
+        customers.put(customer.getId(), customer);
+        sendCustomerEvent("added", customer);
+        return Response.ok(customer).build();
+    }
+
+    @DELETE
+    @Path("/customers/{id}/")
+    public Response deleteCustomer(@PathParam("id") 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();
+            Customer customer = customers.remove(idNumber);
+            if (customer != null) {
+                sendCustomerEvent("deleted", customer);
+            }
+        } else {
+            r = Response.notModified().build();
+        }
+
+        return r;
+    }
+
+    @Path("/orders/{orderId}/")
+    public Order getOrder(@PathParam("orderId") String orderId) {
+        System.out.println("----invoking getOrder, Order id is: " + orderId);
+        long idNumber = Long.parseLong(orderId);
+        Order c = orders.get(idNumber);
+        return c;
+    }
+
+    @GET
+    @Path("/monitor")
+    @Produces("text/*")
+    public StreamingOutput monitorCustomers(
+            @HeaderParam(WebSocketConstants.DEFAULT_REQUEST_ID_KEY) String reqid) {
+        final String key = reqid == null ? "*" : reqid; 
+        return new StreamingOutput() {
+            public void write(final OutputStream out) throws IOException, WebApplicationException {
+                monitors.put(key, new WriterHolder(out, MAX_ERROR_COUNT));
+                out.write(("Subscribed at " + new java.util.Date()).getBytes());
+            }
+            
+        };
+    }
+
+    @GET
+    @Path("/monitor2")
+    @Produces("text/*")
+    public void monitorCustomers2(
+            final @javax.ws.rs.core.Context HttpServletResponse httpResponse,
+            @HeaderParam(WebSocketConstants.DEFAULT_REQUEST_ID_KEY) String reqid) {
+        final String key = reqid == null ? "*" : reqid; 
+        monitors2.put(key, new WriterHolder(httpResponse, MAX_ERROR_COUNT));
+        try {
+            httpResponse.getOutputStream().write(("Subscribed at " + new java.util.Date()).getBytes());
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @GET
+    @Path("/unmonitor/{key}")
+    @Produces("text/*")
+    public String unmonitorCustomers(@PathParam("key") String key) {
+        return (monitors.remove(key) != null ? "Removed: " : "Already removed: ") + key; 
+    }
+
+    @GET
+    @Path("/unmonitor2/{key}")
+    @Produces("text/*")
+    public String unmonitorCustomers2(@PathParam("key") String key) {
+        return (monitors2.remove(key) != null ? "Removed: " : "Already removed: ") + key; 
+    }
+
+    private void sendCustomerEvent(final String msg, final Customer customer) {
+        executor.execute(new Runnable() {
+            public void run() {
+                try {
+                    String t = msg + ": " + customer.getId() + "/" + customer.getName();
+                    for (Iterator<WriterHolder<OutputStream>> it = monitors.values().iterator(); it.hasNext();) {
+                        WriterHolder<OutputStream> wh = it.next();
+                        try {
+                            wh.getValue().write(t.getBytes());
+                            wh.getValue().flush();
+                            wh.reset();
+                        } catch (IOException e) {
+                            System.out.println("----error writing to " + wh.getValue() + " " + wh.get());
+                            if (wh.increment()) {
+                                // the max error count reached; purging the output resource
+                                e.printStackTrace();
+                                try {
+                                    wh.getValue().close();
+                                } catch (IOException e2) {
+                                    // ignore;
+                                }
+                                it.remove();
+                                System.out.println("----purged " + wh.getValue());
+                            }
+                        }
+                    }
+                    for (Iterator<WriterHolder<HttpServletResponse>> it = monitors2.values().iterator(); it.hasNext();) {
+                        WriterHolder<HttpServletResponse> wh = it.next();
+                        try {
+                            wh.getValue().getOutputStream().write(t.getBytes());
+                            wh.getValue().getOutputStream().flush();
+                            wh.reset();
+                        } catch (IOException e) {
+                            System.out.println("----error writing to " + wh.getValue() + " " + wh.get());
+                            if (wh.increment()) {
+                                // the max error count reached; purging the output resource
+                                e.printStackTrace();
+                                try {
+                                    wh.getValue().getOutputStream().close();
+                                } catch (IOException e2) {
+                                    // ignore;
+                                }
+                                it.remove();
+                                System.out.println("----purged " + wh.getValue());
+                            }
+                        }
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        });
+
+    }
+    final void init() {
+        Customer c = new Customer();
+        c.setName("John");
+        c.setId(123);
+        customers.put(c.getId(), c);
+        c = new Customer();
+        c.setName("Homer");
+        c.setId(235);
+        customers.put(c.getId(), c);
+        
+        Order o = new Order();
+        o.setDescription("order 223");
+        o.setId(223);
+        orders.put(o.getId(), o);
+    }
+
+    private static class WriterHolder<T> {
+        final private T value;
+        final private int max; 
+        final private AtomicInteger errorCount;
+
+        public WriterHolder(T object, int max) {
+            this.value = object;
+            this.max = max;
+            this.errorCount = new AtomicInteger();
+        }
+
+        public T getValue() {
+            return value;
+        }
+
+        public int get() {
+            return errorCount.get();
+        }
+        public boolean increment() {
+            return max < errorCount.getAndIncrement();
+        }
+
+        public void reset() {
+            errorCount.getAndSet(0);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5ce68277/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/main/java/demo/jaxrs/server/Order.java
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/main/java/demo/jaxrs/server/Order.java b/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/main/java/demo/jaxrs/server/Order.java
new file mode 100644
index 0000000..a06b68b
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/main/java/demo/jaxrs/server/Order.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 demo.jaxrs.server;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "Order")
+public class Order {
+    private long id;
+    private String description;
+    private Map<Long, Product> products = new HashMap<Long, Product>();
+
+    public Order() {
+        init();
+    }
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String d) {
+        this.description = d;
+    }
+
+    @GET
+    @Path("products/{productId}/")
+    public Product getProduct(@PathParam("productId")int productId) {
+        System.out.println("----invoking getProduct with id: " + productId);
+        Product p = products.get(new Long(productId));
+        return p;
+    }
+
+    final void init() {
+        Product p = new Product();
+        p.setId(323);
+        p.setDescription("product 323");
+        products.put(p.getId(), p);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5ce68277/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/main/java/demo/jaxrs/server/Product.java
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/main/java/demo/jaxrs/server/Product.java b/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/main/java/demo/jaxrs/server/Product.java
new file mode 100644
index 0000000..4452ec5
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/main/java/demo/jaxrs/server/Product.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 demo.jaxrs.server;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "Product")
+public class Product {
+    private long id;
+    private String description;
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String d) {
+        this.description = d;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5ce68277/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/main/resources/OSGI-INF/blueprint/context.xml
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/main/resources/OSGI-INF/blueprint/context.xml b/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/main/resources/OSGI-INF/blueprint/context.xml
new file mode 100644
index 0000000..9bd1cdf
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/main/resources/OSGI-INF/blueprint/context.xml
@@ -0,0 +1,47 @@
+<?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.
+-->
+<!-- START SNIPPET: blueprint -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:cxf="http://cxf.apache.org/blueprint/core"
+       xmlns:jaxrs="http://cxf.apache.org/blueprint/jaxrs"
+
+       xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
+                           http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd
+                           http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/blueprint/jaxrs.xsd">
+
+
+    <!-- Application resources -->
+    <bean id="sampleResource" class="demo.jaxrs.server.CustomerService" />
+
+    <cxf:bus>
+        <cxf:features>
+            <cxf:logging />
+        </cxf:features>
+    </cxf:bus>
+
+    <jaxrs:server id="websocketSampleService" address="/websocketSample" transportId="http://cxf.apache.org/transports/websocket">
+        <jaxrs:serviceBeans>
+            <ref component-id="sampleResource" />
+        </jaxrs:serviceBeans>
+    </jaxrs:server>
+
+</blueprint>
+<!-- END SNIPPET: blueprint -->

http://git-wip-us.apache.org/repos/asf/cxf/blob/5ce68277/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/test/resources/client.js
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/test/resources/client.js b/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/test/resources/client.js
new file mode 100644
index 0000000..492d520
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/websocket_osgi/src/test/resources/client.js
@@ -0,0 +1,234 @@
+/**
+ * client.js
+ * 
+ * A client program to interact with samples/jax_rs/websocket_osgi service
+ * 
+ * 
+ */
+
+"use strict";
+
+// set the host url and path if the service runs at a different location
+var HOST_URL = 'http://localhost:8181';
+var CONTEXT_PATH = "/cxf/websocketSample"
+
+var reader = require('readline');
+var prompt = reader.createInterface(process.stdin, process.stdout);
+
+var atmosphere = require('atmosphere.js');
+
+var request = { url: HOST_URL + CONTEXT_PATH,
+                transport : 'websocket',
+                trackMessageLength: false,
+                dropHeaders: false,
+                reconnectInterval : 5000};
+var isopen = false;
+
+const TRANSPORT_NAMES = ["websocket", "sse"];
+
+const COMMAND_LIST = 
+    [["add name",       "Add a new consumer and return the customer instance. (e.g., add green)"],
+     ["delete id",      "Delete the customer. (e.g., delete 124)"],
+     ["get id",         "Return the customere. (e.g., get 123)"],
+     ["quit",           "Quit the application."],
+     ["subscribe",      "Subscribe to the customer queries."],
+     ["unsubscribe",    "Unsubscribe from the customer queries."],
+     ["update id name", "Update the customer. (e.g., update 125 red)"]];
+
+function selectOption(c, opts) {
+    var i = parseInt(c);
+    if (!(i >= 0 && i < opts.length)) {
+        console.log('Invalid selection: ' + c + '; Using ' + opts[0]);
+        i = 0;
+    }
+    return opts[i];
+}
+
+function getArgs(name, msg) {
+    var sp = name.length;
+    if (msg.length > name.length && msg.charAt(name.length) != ' ') {
+        // remove the command suffix
+        sp = msg.indexOf(' ', name.length);
+        if (sp < 0) {
+            sp = msg.length;
+        }
+    }
+    return msg.substring(sp).trim().split(' ');
+}
+
+function createAddCustomerPayload(name) {
+    return "<?xml version=\"1.0\"?>\n<Customer>\n    <name>" + name + "</name>\n</Customer>\n";
+}
+
+function createUpdateCustomerPayload(id, name) {
+    return "<?xml version=\"1.0\"?>\n<Customer>\n    <name>" + name + "</name>\n    <id>" + id + "</id>\n</Customer>\n";
+}
+
+///
+
+function doHelp() {
+    console.log('Available commands');
+    for (var i = 0; i < COMMAND_LIST.length; i++) { 
+        var c = COMMAND_LIST[i][0];
+        console.log(c + "                    ".substring(0, 20 - c.length) + COMMAND_LIST[i][1]);
+    }
+}
+
+function doAdd(v) {
+    var req;
+    if (transport == 'websocket') {
+        req = "POST " + CONTEXT_PATH + "/customerservice/customers\r\nContent-Type: text/xml; charset='utf-8'\r\nAccept: text/xml\r\n\r\n" 
+            + createAddCustomerPayload(v[0]);
+    } else if (transport == 'sse') {
+        req = {"method": "POST", "url": HOST_URL + CONTEXT_PATH + "/customerservice/customers", "headers": {"content-type": "text/xml; charset=utf-8", "accept": "text/xml"}, "data": createAddCustomerPayload(v[0])}
+    }
+    console.log("TRACE: sending ", req);
+    subSocket.push(req);
+}
+
+function doDelete(v) {
+    var req;
+    if (transport == 'websocket') {
+        req = "DELETE" + CONTEXT_PATH + "/customerservice/customers/" + v[0];
+    } else if (transport == 'sse') {
+        req = {"method": "DELETE", "url": HOST_URL + CONTEXT_PATH + "/customerservice/customers/" + v[0]}
+    }
+    console.log("TRACE: sending ", req);
+    subSocket.push(req);
+}
+
+function doGet(v) {
+    var req;
+    if (transport == 'websocket') {
+        req = "GET " + CONTEXT_PATH + "/customerservice/customers/" + v[0];
+    } else if (transport == 'sse') {
+        req = {"method": "GET", "url": HOST_URL + CONTEXT_PATH + "/customerservice/customers/" + v[0]}
+    }
+    console.log("TRACE: sending ", req);
+    subSocket.push(req);
+}
+
+function doSubscribe() {
+    var req;
+    if (transport == 'websocket') {
+        req = "GET " + CONTEXT_PATH + "/customerservice/monitor\r\nAccept: text/plain\r\n";
+    } else if (transport == 'sse') {
+        req = {"method": "GET", "url": HOST_URL + CONTEXT_PATH + "/customerservice/monitor", "headers": {"accept": "text/plain"}}
+    }
+    console.log("TRACE: sending ", req);
+    subSocket.push(req);
+}
+
+function doUnsubscribe() {
+    var req;
+    if (transport == 'websocket') {
+        req = "GET " + CONTEXT_PATH + "/customerservice/unmonitor/*\r\nAccept: text/plain\r\n";
+    } else if (transport == 'sse') {
+        req = {"method": "GET", "url": HOST_URL + CONTEXT_PATH + "/customerservice/unmonitor/*", "headers": {"accept": "text/plain"}}
+    }
+    console.log("TRACE: sending ", req);
+    subSocket.push(req);
+}
+
+function doUpdate(v) {
+    var req;
+    if (transport == 'websocket') {
+        req = "PUT " + CONTEXT_PATH + "/customerservice/customers\r\nContent-Type: text/xml; charset='utf-8'\r\nAccept: text/xml\r\n\r\n" 
+            + createUpdateCustomerPayload(v[0], v[1]);
+    } else if (transport == 'sse') {
+        req = {"method": "PUT", "url": HOST_URL + CONTEXT_PATH + "/customerservice/customers", "headers": {"content-type": "text/xml; charset=utf-8", "accept": "text/xml"}, "data": createUpdateCustomerPayload(v[0], v[1])}
+    }
+    console.log("TRACE: sending ", req);
+    subSocket.push(req);
+}
+
+function doQuit() {
+    subSocket.close();
+    process.exit(0);
+}
+
+///
+
+request.onOpen = function(response) {
+    isopen = true;
+    console.log('Connected using ' + response.transport);
+    prompt.setPrompt("> ", 2);
+    prompt.prompt();
+};
+
+request.onMessage = function (response) {
+    var message = response.responseBody;
+    console.log('Received: ', message);
+    console.log('------------------------------------------------------------------------');
+    prompt.setPrompt("> ", 2);
+    prompt.prompt();
+};
+
+request.onReconnect = function(response) {
+    console.log('Reconnecting ...');
+}
+
+request.onReopen = function(response) {
+    isopen = true;
+    console.log('Reconnected using ' + response.transport);
+    prompt.setPrompt("> ", 2);
+    prompt.prompt();
+}
+
+request.onClose = function(response) {
+    isopen = false;
+}
+
+request.onError = function(response) {
+    console.log("Sorry, something went wrong: " + response.responseBody);
+};
+
+var transport = null;
+var subSocket = null;
+var author = null;
+
+console.log("Select transport ...");
+for (var i = 0; i < TRANSPORT_NAMES.length; i++) { 
+    console.log(i + ": " + TRANSPORT_NAMES[i]);
+}
+prompt.setPrompt("select: ", 6);
+prompt.prompt();
+
+prompt.
+on('line', function(line) {
+    var msg = line.trim();
+    if (transport == null) {
+        transport = selectOption(msg, TRANSPORT_NAMES);
+        request.transport = transport;
+        subSocket = atmosphere.subscribe(request);
+        console.log("Connecting using " + transport);
+        setTimeout(function() {
+            if (!isopen) {
+                console.log("Unable to open a connection. Terminated.");
+                process.exit(0);
+            }
+        }, 3000);
+    } else if (msg.length == 0) {
+        doHelp();
+    } else if (msg.indexOf("add") == 0) {
+        doAdd(getArgs("add", msg));
+    } else if (msg.indexOf("del") == 0) {
+        doDelete(getArgs("del", msg));
+    } else if (msg.indexOf("get") == 0) {
+        doGet(getArgs("get", msg));
+    } else if (msg.indexOf("quit") == 0) {
+        doQuit();
+    } else if (msg.indexOf("sub") == 0) {
+        doSubscribe(getArgs("sub", msg));
+    } else if (msg.indexOf("unsub") == 0) {
+        doUnsubscribe(getArgs("unsub", msg));
+    } else if (msg.indexOf("update") == 0) {
+        doUpdate(getArgs("update", msg));
+    }
+    prompt.setPrompt("> ", 2);
+    prompt.prompt();
+}).
+on('close', function() {
+    console.log("close");
+    process.exit(0);
+});


[8/8] cxf git commit: make websocket_osgi sample also work for both karaf 4.0.x (for cxf-3.1.x)

Posted by ay...@apache.org.
make websocket_osgi sample also work for both karaf 4.0.x (for cxf-3.1.x)


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

Branch: refs/heads/3.1.x-fixes
Commit: 75edfe9d21fd654d844e24038a72206b4e15457d
Parents: 5ce6827
Author: Akitoshi Yoshida <ay...@apache.org>
Authored: Tue Apr 5 10:38:42 2016 +0200
Committer: Akitoshi Yoshida <ay...@apache.org>
Committed: Tue Apr 5 14:33:29 2016 +0200

----------------------------------------------------------------------
 .../samples/jax_rs/websocket_osgi/README.txt    | 58 ++++++++++----------
 .../samples/jax_rs/websocket_osgi/pom.xml       | 10 ++--
 2 files changed, 35 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/75edfe9d/distribution/src/main/release/samples/jax_rs/websocket_osgi/README.txt
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket_osgi/README.txt b/distribution/src/main/release/samples/jax_rs/websocket_osgi/README.txt
index 60d7705..09cf100 100644
--- a/distribution/src/main/release/samples/jax_rs/websocket_osgi/README.txt
+++ b/distribution/src/main/release/samples/jax_rs/websocket_osgi/README.txt
@@ -16,23 +16,22 @@ Using either UNIX or Windows:
 
 This will produce a war file in the target folder.
 
+Starting Karaf (refer to http://karaf.apache.org/manual/latest-3.0.x/quick-start.html.
+You can also use Karaf 4.0.x for this demo.)
 
-Starting Karaf (refer to http://karaf.apache.org/manual/latest-3.0.x/quick-start.html)
+$ bin/karaf 
+        __ __                  ____      
+       / //_/____ __________ _/ __/      
+      / ,<  / __ `/ ___/ __ `/ /_        
+     / /| |/ /_/ / /  / /_/ / __/        
+    /_/ |_|\__,_/_/   \__,_/_/         
 
-  bin/karaf
+  Apache Karaf (3.0.4)
 
+Hit '<tab>' for a list of available commands
+and '[cmd] --help' for help on a specific command.
+Hit '<ctrl-d>' or type 'system:shutdown' or 'logout' to shutdown Karaf.
 
-          __ __                  ____      
-         / //_/____ __________ _/ __/      
-        / ,<  / __ `/ ___/ __ `/ /_        
-       / /| |/ /_/ / /  / /_/ / __/        
-      /_/ |_|\__,_/_/   \__,_/_/         
-  
-    Apache Karaf (3.0.4)
-  
-  Hit '<tab>' for a list of available commands
-  and '[cmd] --help' for help on a specific command.
-  Hit '<ctrl-d>' or type 'system:shutdown' or 'logout' to shutdown Karaf.
 
 
 In order to install CXF's features, you need to add the CXF's features repo using
@@ -52,28 +51,29 @@ Install this demo bundle (using the appropriate bundle version number)
 
 And verify the bundles are installed.
 
-karaf@root()> feature:repo-add cxf 3.2.0-SNAPSHOT
-Adding feature url mvn:org.apache.cxf.karaf/apache-cxf/3.2.0-SNAPSHOT/xml/features
+
+karaf@root()> feature:repo-add cxf 3.1.7-SNAPSHOT
+Adding feature url mvn:org.apache.cxf.karaf/apache-cxf/3.1.7-SNAPSHOT/xml/features
 karaf@root()> feature:install cxf-jaxrs cxf-transports-websocket-server
-karaf@root()> list -t 0 | grep CXF
- 80 | Active   |  40 | 3.2.0.SNAPSHOT   | Apache CXF Core                                                    
- 81 | Active   |  40 | 3.2.0.SNAPSHOT   | Apache CXF Runtime Management                                      
-100 | Active   |  40 | 3.2.0.SNAPSHOT   | Apache CXF Runtime HTTP Transport                                  
-102 | Active   |  40 | 3.2.0.SNAPSHOT   | Apache CXF JAX-RS Extensions: Providers                            
-103 | Active   |  40 | 3.2.0.SNAPSHOT   | Apache CXF JAX-RS Extensions: Search                               
-104 | Active   |  40 | 3.2.0.SNAPSHOT   | Apache CXF JAX-RS Service Description                              
-105 | Active   |  40 | 3.2.0.SNAPSHOT   | Apache CXF Runtime JAX-RS Frontend                                 
-106 | Active   |  40 | 3.2.0.SNAPSHOT   | Apache CXF JAX-RS Client                                           
-108 | Active   |  40 | 3.2.0.SNAPSHOT   | Apache CXF Runtime WebSocket Transport                             
-karaf@root()> install -s mvn:org.apache.cxf.samples/jax_rs_websocket_osgi
+karaf@root()> install -s mvn:org.apache.cxf.samples/jax_rs_websocket_osgi/3.1.7-SNAPSHOT
 Bundle ID: 109
+karaf@root()> list -t 0 | grep CXF
+ 80 | Active   |  40 | 3.1.7.SNAPSHOT   | Apache CXF Core                                                    
+ 81 | Active   |  40 | 3.1.7.SNAPSHOT   | Apache CXF Runtime Management                                      
+100 | Active   |  40 | 3.1.7.SNAPSHOT   | Apache CXF Runtime HTTP Transport                                  
+102 | Active   |  40 | 3.1.7.SNAPSHOT   | Apache CXF JAX-RS Extensions: Providers                            
+103 | Active   |  40 | 3.1.7.SNAPSHOT   | Apache CXF JAX-RS Extensions: Search                               
+104 | Active   |  40 | 3.1.7.SNAPSHOT   | Apache CXF JAX-RS Service Description                              
+105 | Active   |  40 | 3.1.7.SNAPSHOT   | Apache CXF Runtime JAX-RS Frontend                                 
+106 | Active   |  40 | 3.1.7.SNAPSHOT   | Apache CXF JAX-RS Client                                           
+108 | Active   |  40 | 3.1.7.SNAPSHOT   | Apache CXF Runtime WebSocket Transport                             
 karaf@root()> list
 START LEVEL 100 , List Threshold: 50
  ID | State  | Lvl | Version        | Name                           
 ---------------------------------------------------------------------
-107 | Active |  80 | 2.4.3          | atmosphere-runtime             
-109 | Active |  80 | 3.2.0.SNAPSHOT | JAX-RS WebSocket Blueprint Demo
-karaf@root()>
+107 | Active |  80 | 2.3.7          | atmosphere-runtime             
+109 | Active |  80 | 3.1.7.SNAPSHOT | JAX-RS WebSocket Blueprint Demo
+karaf@root()> 
 
 
 Visit http://localhost:8181/cxf/ to see if this RESTful service is registered.

http://git-wip-us.apache.org/repos/asf/cxf/blob/75edfe9d/distribution/src/main/release/samples/jax_rs/websocket_osgi/pom.xml
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket_osgi/pom.xml b/distribution/src/main/release/samples/jax_rs/websocket_osgi/pom.xml
index e0d1234..16e1988 100644
--- a/distribution/src/main/release/samples/jax_rs/websocket_osgi/pom.xml
+++ b/distribution/src/main/release/samples/jax_rs/websocket_osgi/pom.xml
@@ -27,7 +27,7 @@
     <parent>
         <groupId>org.apache.cxf.samples</groupId>
         <artifactId>cxf-samples</artifactId>
-        <version>3.2.0-SNAPSHOT</version>
+        <version>3.1.7-SNAPSHOT</version>
         <relativePath>../..</relativePath>
     </parent>
     <properties>
@@ -48,6 +48,8 @@
                     <instructions>
                         <Bundle-SymbolicName>${project.groupId}.${project.artifactId};blueprint.aries.xml-validation:=false</Bundle-SymbolicName>
                         <Import-Package>
+                            javax.servlet;version="[2.6,4)",
+                            javax.servlet.http;version="[2.6,4)",
                             javax.ws.rs,
                             javax.ws.rs.core,
                             org.apache.cxf.jaxrs.provider,
@@ -66,17 +68,17 @@
         <dependency>
             <groupId>org.apache.cxf</groupId>
             <artifactId>cxf-rt-transports-http</artifactId>
-            <version>3.2.0-SNAPSHOT</version>
+            <version>3.1.7-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.cxf</groupId>
             <artifactId>cxf-rt-transports-websocket</artifactId>
-            <version>3.2.0-SNAPSHOT</version>
+            <version>3.1.7-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.cxf</groupId>
             <artifactId>cxf-rt-frontend-jaxrs</artifactId>
-            <version>3.2.0-SNAPSHOT</version>
+            <version>3.1.7-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>javax.ws.rs</groupId>


[2/8] cxf git commit: [CXF-5855] enable atmosphere's sse handling; update the sample

Posted by ay...@apache.org.
[CXF-5855] enable atmosphere's sse handling; update the sample


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

Branch: refs/heads/3.1.x-fixes
Commit: 35f01c94841870afa8331e0591aec8a3bc4ca94d
Parents: 897d81d
Author: Akitoshi Yoshida <ay...@apache.org>
Authored: Thu Mar 17 00:11:58 2016 +0100
Committer: Akitoshi Yoshida <ay...@apache.org>
Committed: Tue Apr 5 13:36:57 2016 +0200

----------------------------------------------------------------------
 .../jax_rs/websocket/src/test/resources/client.js     | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/35f01c94/distribution/src/main/release/samples/jax_rs/websocket/src/test/resources/client.js
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket/src/test/resources/client.js b/distribution/src/main/release/samples/jax_rs/websocket/src/test/resources/client.js
index 7eb55f3..8e8d653 100644
--- a/distribution/src/main/release/samples/jax_rs/websocket/src/test/resources/client.js
+++ b/distribution/src/main/release/samples/jax_rs/websocket/src/test/resources/client.js
@@ -8,7 +8,7 @@
 
 "use strict";
 
-var HOST_URL = 'http://localhost:9100/';
+var HOST_URL = 'http://localhost:9000/';
 
 var reader = require('readline');
 var prompt = reader.createInterface(process.stdin, process.stdout);
@@ -25,13 +25,13 @@ var isopen = false;
 const TRANSPORT_NAMES = ["websocket", "sse"];
 
 const COMMAND_LIST = 
-    [["add name",       "Add a new consumer and return the customer instance."],
-     ["delete id",      "Delete the customer."],
-     ["get id",         "Return the customere."],
+    [["add name",       "Add a new consumer and return the customer instance. (e.g., add green)"],
+     ["delete id",      "Delete the customer. (e.g., delete 124)"],
+     ["get id",         "Return the customere. (e.g., get 123)"],
      ["quit",           "Quit the application."],
-     ["subscribe",      "Subscribe to the customer updatese."],
-     ["unsubscribe",    "Unsubscribe from the customer updatese."],
-     ["update id name", "Update the customer."]];
+     ["subscribe",      "Subscribe to the customer queries."],
+     ["unsubscribe",    "Unsubscribe from the customer queries."],
+     ["update id name", "Update the customer. (e.g., update 125 red)"]];
 
 function selectOption(c, opts) {
     var i = parseInt(c);


[5/8] cxf git commit: add a webapp version of samples/jax_rs/websocket (for cxf-3.1.x)

Posted by ay...@apache.org.
add a webapp version of samples/jax_rs/websocket (for cxf-3.1.x)


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

Branch: refs/heads/3.1.x-fixes
Commit: de9b7936156d622c284df7f055acac80b920b7d0
Parents: b52157a
Author: Akitoshi Yoshida <ay...@apache.org>
Authored: Wed Mar 23 14:40:00 2016 +0100
Committer: Akitoshi Yoshida <ay...@apache.org>
Committed: Tue Apr 5 13:36:58 2016 +0200

----------------------------------------------------------------------
 .../samples/jax_rs/websocket_web/README.txt     |  32 +++
 .../samples/jax_rs/websocket_web/pom.xml        | 123 +++++++++
 .../main/java/demo/jaxrs/server/Customer.java   |  43 +++
 .../java/demo/jaxrs/server/CustomerService.java | 271 +++++++++++++++++++
 .../src/main/java/demo/jaxrs/server/Order.java  |  69 +++++
 .../main/java/demo/jaxrs/server/Product.java    |  43 +++
 .../src/main/webapp/WEB-INF/beans.xml           |  46 ++++
 .../src/main/webapp/WEB-INF/web.xml             |  42 +++
 8 files changed, 669 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/de9b7936/distribution/src/main/release/samples/jax_rs/websocket_web/README.txt
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket_web/README.txt b/distribution/src/main/release/samples/jax_rs/websocket_web/README.txt
new file mode 100644
index 0000000..36008ed
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/websocket_web/README.txt
@@ -0,0 +1,32 @@
+JAX-RS WebSocket WebApp Demo 
+=================
+
+This is an WebApp version of JAX-RS WebSocket Demo.
+
+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
+
+This will produce a war file in the target folder.
+
+To run the war file using jetty9
+
+  mvn jetty:run-war  (from one command line window)
+
+To run the war file using tomcat7
+
+  mvn tomcat7:run-war  (from one command line window)
+
+To remove the target dir, run mvn clean".
+
+
+You can use the same clients included in JAX-RS WebSockt Demo.
+Refer to samples/jax_rs/websocket/README.txt for more information.
+

http://git-wip-us.apache.org/repos/asf/cxf/blob/de9b7936/distribution/src/main/release/samples/jax_rs/websocket_web/pom.xml
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket_web/pom.xml b/distribution/src/main/release/samples/jax_rs/websocket_web/pom.xml
new file mode 100644
index 0000000..7b76bbc
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/websocket_web/pom.xml
@@ -0,0 +1,123 @@
+<?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_websocket_web</artifactId>
+    <name>JAX-RS WebSocket Demo</name>
+    <description>JAX-RS WebSocket WebApp Demo</description>
+    <packaging>war</packaging>
+    <parent>
+        <groupId>org.apache.cxf.samples</groupId>
+        <artifactId>cxf-samples</artifactId>
+        <version>3.1.7-SNAPSHOT</version>
+        <relativePath>../..</relativePath>
+    </parent>
+    <properties>
+        <cxf.version>${project.version}</cxf.version>
+        <!-- TODO remove these local entries after making the referenced dependency managed in parent/pom.xml -->
+        <cxf.atmosphere.version>2.3.7</cxf.atmosphere.version>
+        <cxf.jetty92.version>9.2.15.v20160210</cxf.jetty92.version>
+        <cxf.jetty93.version>9.3.5.v20151012</cxf.jetty93.version>
+        <cxf.jetty.version>${cxf.jetty92.version}</cxf.jetty.version>
+    </properties>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.eclipse.jetty</groupId>
+                <artifactId>jetty-maven-plugin</artifactId>
+                <version>${cxf.jetty.version}</version>
+                <configuration>
+                    <webAppSourceDirectory>${project.build.directory}/${project.name}</webAppSourceDirectory>
+                    <scanIntervalSeconds>1</scanIntervalSeconds>
+                    <httpConnector>
+                        <port>9000</port>
+                    </httpConnector>
+                    <webAppConfig>
+                        <contextPath>/</contextPath>
+                    </webAppConfig>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.tomcat.maven</groupId>
+                <artifactId>tomcat7-maven-plugin</artifactId>
+                <version>2.2</version>
+                <configuration>
+                    <warSourceDirectory>${project.build.directory}/${project.artifactId}</warSourceDirectory>
+                    <port>9000</port>
+                    <path>/</path>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>run-tomcat</id>
+                        <configuration>
+                            <fork>true</fork>
+                        </configuration>
+                        <goals>
+                            <goal>run</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+    <dependencies>
+        <!-- cxt et al -->
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-transports-http</artifactId>
+            <version>3.1.7-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-transports-websocket</artifactId>
+            <version>3.1.7-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+            <version>3.1.7-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>javax.ws.rs</groupId>
+            <artifactId>javax.ws.rs-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+        </dependency>
+
+        <!-- add atmosphere -->
+        <dependency>
+            <groupId>org.atmosphere</groupId>
+            <artifactId>atmosphere-runtime</artifactId>
+            <version>${cxf.atmosphere.version}</version>
+        </dependency>
+                
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/cxf/blob/de9b7936/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/java/demo/jaxrs/server/Customer.java
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/java/demo/jaxrs/server/Customer.java b/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/java/demo/jaxrs/server/Customer.java
new file mode 100644
index 0000000..44025f0
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/java/demo/jaxrs/server/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 demo.jaxrs.server;
+
+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;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/de9b7936/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/java/demo/jaxrs/server/CustomerService.java
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/java/demo/jaxrs/server/CustomerService.java b/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/java/demo/jaxrs/server/CustomerService.java
new file mode 100644
index 0000000..f77f8aa
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/java/demo/jaxrs/server/CustomerService.java
@@ -0,0 +1,271 @@
+/**
+ * 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 demo.jaxrs.server;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.servlet.http.HttpServletResponse;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.StreamingOutput;
+
+import org.apache.cxf.transport.websocket.WebSocketConstants;
+
+@Path("/customerservice/")
+@Produces("text/xml")
+public class CustomerService {
+    private static final int MAX_ERROR_COUNT = 5;
+    private static ExecutorService executor = Executors.newSingleThreadExecutor();
+
+    long currentId = 123;
+    Map<Long, Customer> customers = new HashMap<Long, Customer>();
+    Map<Long, Order> orders = new HashMap<Long, Order>();
+    Map<String, WriterHolder<OutputStream>> monitors = new HashMap<String, WriterHolder<OutputStream>>();
+    Map<String, WriterHolder<HttpServletResponse>> monitors2 = new HashMap<String, WriterHolder<HttpServletResponse>>();
+
+    public CustomerService() {
+        init();
+    }
+
+    @GET
+    @Path("/customers/{id}/")
+    public Customer getCustomer(@PathParam("id") String id) {
+        System.out.println("----invoking getCustomer, Customer id is: " + id);
+        long idNumber = Long.parseLong(id);
+        Customer customer = customers.get(idNumber);
+        if (customer != null) {
+            sendCustomerEvent("retrieved", customer);
+        }
+        return customer;
+    }
+
+    @PUT
+    @Path("/customers/")
+    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();
+            sendCustomerEvent("updated", customer);
+        } else {
+            r = Response.notModified().build();
+        }
+
+        return r;
+    }
+
+    @POST
+    @Path("/customers/")
+    public Response addCustomer(Customer customer) {
+        System.out.println("----invoking addCustomer, Customer name is: " + customer.getName());
+        customer.setId(++currentId);
+
+        customers.put(customer.getId(), customer);
+        sendCustomerEvent("added", customer);
+        return Response.ok(customer).build();
+    }
+
+    @DELETE
+    @Path("/customers/{id}/")
+    public Response deleteCustomer(@PathParam("id") 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();
+            Customer customer = customers.remove(idNumber);
+            if (customer != null) {
+                sendCustomerEvent("deleted", customer);
+            }
+        } else {
+            r = Response.notModified().build();
+        }
+
+        return r;
+    }
+
+    @Path("/orders/{orderId}/")
+    public Order getOrder(@PathParam("orderId") String orderId) {
+        System.out.println("----invoking getOrder, Order id is: " + orderId);
+        long idNumber = Long.parseLong(orderId);
+        Order c = orders.get(idNumber);
+        return c;
+    }
+
+    @GET
+    @Path("/monitor")
+    @Produces("text/*")
+    public StreamingOutput monitorCustomers(
+            @HeaderParam(WebSocketConstants.DEFAULT_REQUEST_ID_KEY) String reqid) {
+        final String key = reqid == null ? "*" : reqid; 
+        return new StreamingOutput() {
+            public void write(final OutputStream out) throws IOException, WebApplicationException {
+                monitors.put(key, new WriterHolder(out, MAX_ERROR_COUNT));
+                out.write(("Subscribed at " + new java.util.Date()).getBytes());
+            }
+            
+        };
+    }
+
+    @GET
+    @Path("/monitor2")
+    @Produces("text/*")
+    public void monitorCustomers2(
+            final @javax.ws.rs.core.Context HttpServletResponse httpResponse,
+            @HeaderParam(WebSocketConstants.DEFAULT_REQUEST_ID_KEY) String reqid) {
+        final String key = reqid == null ? "*" : reqid; 
+        monitors2.put(key, new WriterHolder(httpResponse, MAX_ERROR_COUNT));
+        try {
+            httpResponse.getOutputStream().write(("Subscribed at " + new java.util.Date()).getBytes());
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @GET
+    @Path("/unmonitor/{key}")
+    @Produces("text/*")
+    public String unmonitorCustomers(@PathParam("key") String key) {
+        return (monitors.remove(key) != null ? "Removed: " : "Already removed: ") + key; 
+    }
+
+    @GET
+    @Path("/unmonitor2/{key}")
+    @Produces("text/*")
+    public String unmonitorCustomers2(@PathParam("key") String key) {
+        return (monitors2.remove(key) != null ? "Removed: " : "Already removed: ") + key; 
+    }
+
+    private void sendCustomerEvent(final String msg, final Customer customer) {
+        executor.execute(new Runnable() {
+            public void run() {
+                try {
+                    String t = msg + ": " + customer.getId() + "/" + customer.getName();
+                    for (Iterator<WriterHolder<OutputStream>> it = monitors.values().iterator(); it.hasNext();) {
+                        WriterHolder<OutputStream> wh = it.next();
+                        try {
+                            wh.getValue().write(t.getBytes());
+                            wh.getValue().flush();
+                            wh.reset();
+                        } catch (IOException e) {
+                            System.out.println("----error writing to " + wh.getValue() + " " + wh.get());
+                            if (wh.increment()) {
+                                // the max error count reached; purging the output resource
+                                e.printStackTrace();
+                                try {
+                                    wh.getValue().close();
+                                } catch (IOException e2) {
+                                    // ignore;
+                                }
+                                it.remove();
+                                System.out.println("----purged " + wh.getValue());
+                            }
+                        }
+                    }
+                    for (Iterator<WriterHolder<HttpServletResponse>> it = monitors2.values().iterator(); it.hasNext();) {
+                        WriterHolder<HttpServletResponse> wh = it.next();
+                        try {
+                            wh.getValue().getOutputStream().write(t.getBytes());
+                            wh.getValue().getOutputStream().flush();
+                            wh.reset();
+                        } catch (IOException e) {
+                            System.out.println("----error writing to " + wh.getValue() + " " + wh.get());
+                            if (wh.increment()) {
+                                // the max error count reached; purging the output resource
+                                e.printStackTrace();
+                                try {
+                                    wh.getValue().getOutputStream().close();
+                                } catch (IOException e2) {
+                                    // ignore;
+                                }
+                                it.remove();
+                                System.out.println("----purged " + wh.getValue());
+                            }
+                        }
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        });
+
+    }
+    final void init() {
+        Customer c = new Customer();
+        c.setName("John");
+        c.setId(123);
+        customers.put(c.getId(), c);
+        c = new Customer();
+        c.setName("Homer");
+        c.setId(235);
+        customers.put(c.getId(), c);
+        
+        Order o = new Order();
+        o.setDescription("order 223");
+        o.setId(223);
+        orders.put(o.getId(), o);
+    }
+
+    private static class WriterHolder<T> {
+        final private T value;
+        final private int max; 
+        final private AtomicInteger errorCount;
+
+        public WriterHolder(T object, int max) {
+            this.value = object;
+            this.max = max;
+            this.errorCount = new AtomicInteger();
+        }
+
+        public T getValue() {
+            return value;
+        }
+
+        public int get() {
+            return errorCount.get();
+        }
+        public boolean increment() {
+            return max < errorCount.getAndIncrement();
+        }
+
+        public void reset() {
+            errorCount.getAndSet(0);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/de9b7936/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/java/demo/jaxrs/server/Order.java
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/java/demo/jaxrs/server/Order.java b/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/java/demo/jaxrs/server/Order.java
new file mode 100644
index 0000000..a06b68b
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/java/demo/jaxrs/server/Order.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 demo.jaxrs.server;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "Order")
+public class Order {
+    private long id;
+    private String description;
+    private Map<Long, Product> products = new HashMap<Long, Product>();
+
+    public Order() {
+        init();
+    }
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String d) {
+        this.description = d;
+    }
+
+    @GET
+    @Path("products/{productId}/")
+    public Product getProduct(@PathParam("productId")int productId) {
+        System.out.println("----invoking getProduct with id: " + productId);
+        Product p = products.get(new Long(productId));
+        return p;
+    }
+
+    final void init() {
+        Product p = new Product();
+        p.setId(323);
+        p.setDescription("product 323");
+        products.put(p.getId(), p);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/de9b7936/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/java/demo/jaxrs/server/Product.java
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/java/demo/jaxrs/server/Product.java b/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/java/demo/jaxrs/server/Product.java
new file mode 100644
index 0000000..4452ec5
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/java/demo/jaxrs/server/Product.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 demo.jaxrs.server;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "Product")
+public class Product {
+    private long id;
+    private String description;
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String d) {
+        this.description = d;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/de9b7936/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/webapp/WEB-INF/beans.xml
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/webapp/WEB-INF/beans.xml b/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000..b6ffaa1
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/webapp/WEB-INF/beans.xml
@@ -0,0 +1,46 @@
+<?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.
+-->
+<!-- START SNIPPET: beans -->
+<beans xmlns="http://www.springframework.org/schema/beans" 
+   xmlns:http="http://cxf.apache.org/transports/http/configuration"
+   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" 
+   xmlns:jaxrs="http://cxf.apache.org/jaxrs" 
+   xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration"
+   xmlns:cxf="http://cxf.apache.org/core" 
+   xsi:schemaLocation="
+   http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
+   http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
+   http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.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://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
+    <import resource="classpath:META-INF/cxf/cxf.xml"/>
+    <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
+
+    <bean class="demo.jaxrs.server.CustomerService" id="serviceBean"/>
+
+    <jaxrs:server id="websocketService" address="/demo" transportId="http://cxf.apache.org/transports/websocket">
+        <jaxrs:serviceBeans>
+            <ref bean="serviceBean"/>
+        </jaxrs:serviceBeans>
+    </jaxrs:server>
+    
+</beans>
+<!-- END SNIPPET: beans -->

http://git-wip-us.apache.org/repos/asf/cxf/blob/de9b7936/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/webapp/WEB-INF/web.xml b/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..b9f5299
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/websocket_web/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<!--
+        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.
+-->
+<!-- START SNIPPET: webxml -->
+<web-app>
+    <context-param>
+        <param-name>contextConfigLocation</param-name>
+        <param-value>WEB-INF/beans.xml</param-value>
+    </context-param>
+    <listener>
+        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+    </listener>
+    <servlet>
+        <servlet-name>CXFServlet</servlet-name>
+        <display-name>CXF Servlet</display-name>
+        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
+        <load-on-startup>1</load-on-startup>
+        <async-supported>true</async-supported>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>CXFServlet</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+</web-app>
+<!-- END SNIPPET: webxml -->


[3/8] cxf git commit: fix the test error by adjusting its setup for CXF-5855

Posted by ay...@apache.org.
fix the test error by adjusting its setup for CXF-5855


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

Branch: refs/heads/3.1.x-fixes
Commit: 897d81dc292eb6159aab96390cb3fbfed1c34a6b
Parents: a529d27
Author: Akitoshi Yoshida <ay...@apache.org>
Authored: Thu Mar 17 11:17:57 2016 +0100
Committer: Akitoshi Yoshida <ay...@apache.org>
Committed: Tue Apr 5 13:36:57 2016 +0200

----------------------------------------------------------------------
 .../websocket/atmosphere/DefaultProtocolInterceptorTest.java   | 6 ++++++
 1 file changed, 6 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/897d81dc/rt/transports/websocket/src/test/java/org/apache/cxf/transport/websocket/atmosphere/DefaultProtocolInterceptorTest.java
----------------------------------------------------------------------
diff --git a/rt/transports/websocket/src/test/java/org/apache/cxf/transport/websocket/atmosphere/DefaultProtocolInterceptorTest.java b/rt/transports/websocket/src/test/java/org/apache/cxf/transport/websocket/atmosphere/DefaultProtocolInterceptorTest.java
index e6b70af..1dee1de 100644
--- a/rt/transports/websocket/src/test/java/org/apache/cxf/transport/websocket/atmosphere/DefaultProtocolInterceptorTest.java
+++ b/rt/transports/websocket/src/test/java/org/apache/cxf/transport/websocket/atmosphere/DefaultProtocolInterceptorTest.java
@@ -25,7 +25,10 @@ import java.util.Map;
 
 import org.apache.cxf.transport.websocket.WebSocketUtils;
 import org.atmosphere.cpr.AtmosphereRequest;
+import org.atmosphere.cpr.AtmosphereResource;
+import org.atmosphere.cpr.AtmosphereResourceImpl;
 import org.atmosphere.cpr.AtmosphereResponse;
+import org.atmosphere.cpr.FrameworkConfig;
 
 import org.junit.Assert;
 import org.junit.Test;
@@ -40,6 +43,9 @@ public class DefaultProtocolInterceptorTest extends Assert {
         DefaultProtocolInterceptor dpi = new DefaultProtocolInterceptor();
         AtmosphereRequest request = AtmosphereRequest.newInstance();
         AtmosphereResponse response = AtmosphereResponse.newInstance();
+        AtmosphereResourceImpl resource = new AtmosphereResourceImpl();
+        resource.transport(AtmosphereResource.TRANSPORT.WEBSOCKET);
+        request.localAttributes().put(FrameworkConfig.ATMOSPHERE_RESOURCE, resource);
         response.request(request);
         String payload = "hello cxf";
         String contentType = "text/plain";