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 10:38:56 UTC
cxf git commit: add a blueprint version of websocket sample for karaf
Repository: cxf
Updated Branches:
refs/heads/master 0b9cb3da9 -> 64e7c75d2
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/64e7c75d
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/64e7c75d
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/64e7c75d
Branch: refs/heads/master
Commit: 64e7c75d2176a39abfd9de40196e7c6eb02cf127
Parents: 0b9cb3d
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 10:38:42 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/64e7c75d/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/64e7c75d/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/64e7c75d/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/64e7c75d/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/64e7c75d/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/64e7c75d/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/64e7c75d/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/64e7c75d/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);
+});