Skip to content

Commit

Permalink
Shared Collection sample
Browse files Browse the repository at this point in the history
- adding "rest" version for comparison
  • Loading branch information
pavelbucek committed Feb 17, 2015
1 parent 058e23c commit 211ff59
Show file tree
Hide file tree
Showing 10 changed files with 662 additions and 60 deletions.
16 changes: 15 additions & 1 deletion samples/shared-collection/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
-->

<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">
<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>

<parent>
Expand Down Expand Up @@ -68,6 +69,19 @@
<scope>provided</scope>
</dependency>

<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-sse</artifactId>
<version>2.16</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-client</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* http://glassfish.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

package org.glassfish.tyrus.sample.shared.collection;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.json.JsonObject;

/**
* @author Pavel Bucek (pavel.bucek at oracle.com)
*/
class SharedCollection {

static final Map<String, String> map = new ConcurrentHashMap<String, String>();

static {
map.put("Red Leader", "Garven Dreis");
map.put("Red Two", "Wedge Antilles");
map.put("Red Three", "Biggs Darklighter");
map.put("Red Four", "John D. Branon");
map.put("Red Five", "Luke Skywalker");
}

static void broadcast(JsonObject object) {
SharedCollectionEndpoint.broadcast(object);
SharedCollectionResource.broadcast(object);
}

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014-2015 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
Expand Down Expand Up @@ -44,7 +44,6 @@
import java.io.Reader;
import java.util.Deque;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;

import javax.websocket.OnError;
Expand All @@ -60,27 +59,20 @@
/**
* @author Pavel Bucek (pavel.bucek at oracle.com)
*/
@ServerEndpoint("/tyrus-collection")
@ServerEndpoint("/ws/collection")
public class SharedCollectionEndpoint {

private static final Map<String, String> map = new ConcurrentHashMap<String, String>();
private static final Deque<Tuple<Session, JsonObject>> broadcastQueue = new ConcurrentLinkedDeque<Tuple<Session, JsonObject>>();

private volatile boolean broadcasting = false;

static {
map.put("Red Leader", "Garven Dreis");
map.put("Red Two", "Wedge Antilles");
map.put("Red Three", "Biggs Darklighter");
map.put("Red Four", "John D. Branon");
map.put("Red Five", "Luke Skywalker");
}
private static volatile Session session = null;
private static volatile boolean broadcasting = false;

@OnOpen
public void onOpen(Session s) {
SharedCollectionEndpoint.session = s;

final JsonObjectBuilder mapRepresentation = Json.createObjectBuilder();

for (Map.Entry<String, String> entry : map.entrySet()) {
for (Map.Entry<String, String> entry : SharedCollection.map.entrySet()) {
mapRepresentation.add(entry.getKey(), entry.getValue());
}

Expand All @@ -96,65 +88,66 @@ public void onOpen(Session s) {
}

@OnMessage
public void onMessage(Session s, Reader message) {
public void onMessage(Reader message) {
final JsonObject jsonObject = Json.createReader(message).readObject();
final String event = jsonObject.getString("event");

switch (event) {
case "put":
map.put(jsonObject.getString("key"), jsonObject.getString("value"));
broadcast(s, jsonObject);
SharedCollection.map.put(jsonObject.getString("key"), jsonObject.getString("value"));
SharedCollection.broadcast(jsonObject);
break;
case "remove":
map.remove(jsonObject.getString("key"));
broadcast(s, jsonObject);
SharedCollection.map.remove(jsonObject.getString("key"));
SharedCollection.broadcast(jsonObject);
break;
case "clear":
map.clear();
broadcast(s, jsonObject);
SharedCollection.map.clear();
SharedCollection.broadcast(jsonObject);
break;
}

}

private void broadcast(Session s, JsonObject object) {
broadcastQueue.add(new Tuple<Session, JsonObject>(s, object));
static void broadcast(JsonObject object) {
broadcastQueue.add(new Tuple<Session, JsonObject>(null, object));

processQueue();
}

private void processQueue() {
private static void processQueue() {

if (broadcasting) {
return;
}

synchronized (broadcastQueue) {
broadcasting = true;
try {
synchronized (broadcastQueue) {
broadcasting = true;

if (!broadcastQueue.isEmpty()) {
while (!broadcastQueue.isEmpty()) {
final Tuple<Session, JsonObject> t = broadcastQueue.remove();
if (!broadcastQueue.isEmpty()) {
while (!broadcastQueue.isEmpty()) {
final Tuple<Session, JsonObject> t = broadcastQueue.remove();

final Session s = t.first;
final String message = t.second.toString();
final Session s = SharedCollectionEndpoint.session;
final String message = t.second.toString();

for (Session session : s.getOpenSessions()) {
if (!session.getId().equals(s.getId())) {
for (Session session : s.getOpenSessions()) {
// if (!session.getId().equals(s.getId())) {
try {
session.getBasicRemote().sendText(message);
} catch (IOException e) {
// we don't care about that for now.
}
// }
}
}
}
}
}

broadcasting = false;
if (!broadcastQueue.isEmpty()) {
processQueue();
} finally {
broadcasting = false;
if (!broadcastQueue.isEmpty()) {
processQueue();
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* http://glassfish.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

package org.glassfish.tyrus.sample.shared.collection;

import java.io.IOException;
import java.io.StringReader;
import java.util.Map;

import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;

import org.glassfish.jersey.media.sse.EventOutput;
import org.glassfish.jersey.media.sse.OutboundEvent;
import org.glassfish.jersey.media.sse.SseBroadcaster;
import org.glassfish.jersey.media.sse.SseFeature;

/**
* @author Pavel Bucek (pavel.bucek at oracle.com)
*/
@Path("collection")
public class SharedCollectionResource {

private static final SseBroadcaster broadcaster = new SseBroadcaster();

@GET
@Produces(SseFeature.SERVER_SENT_EVENTS)
public EventOutput serverSentEventsSource() {

final EventOutput eventOutput = new EventOutput();

new Thread() {
@Override
public void run() {

try {
Thread.sleep(100);
} catch (InterruptedException ignored) {
}

final JsonObjectBuilder mapRepresentation = Json.createObjectBuilder();

for (Map.Entry<String, String> entry : SharedCollection.map.entrySet()) {
mapRepresentation.add(entry.getKey(), entry.getValue());
}

final JsonObjectBuilder event = Json.createObjectBuilder();
event.add("event", "init");
event.add("map", mapRepresentation.build());

try {
eventOutput.write(new OutboundEvent.Builder().name("update").data(String.class, event.build().toString()).build());
} catch (IOException e) {
// we don't care about that for now.
}

broadcaster.add(eventOutput);
}
}.start();

return eventOutput;
}

@POST
public void onMessage(String message) {

final JsonObject jsonObject = Json.createReader(new StringReader(message)).readObject();
final String event = jsonObject.getString("event");

switch (event) {
case "put":
SharedCollection.map.put(jsonObject.getString("key"), jsonObject.getString("value"));
SharedCollection.broadcast(jsonObject);
break;
case "remove":
SharedCollection.map.remove(jsonObject.getString("key"));
SharedCollection.broadcast(jsonObject);
break;
case "clear":
SharedCollection.map.clear();
SharedCollection.broadcast(jsonObject);
break;
}
}

static void broadcast(JsonObject object) {
broadcaster.broadcast(new OutboundEvent.Builder().name("update").data(String.class, object.toString()).build());
}
}
Loading

0 comments on commit 211ff59

Please sign in to comment.