Skip to content

Commit 727c5df

Browse files
authored
Merge pull request #7 from DanielContrerasAladro/PAYARA-1939-ServerEventsSample
Payara 1939 server events sample
2 parents ec12da8 + bf8a6f6 commit 727c5df

File tree

9 files changed

+360
-0
lines changed

9 files changed

+360
-0
lines changed

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
<modules>
9494
<module>test-utils</module>
9595
<module>servlet</module>
96+
<module>sse</module>
9697
<module>security</module>
9798
<module>jsf</module>
9899
<module>cdi</module>

sse/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Java EE 8 Samples: Server Sent Events 1.0#
2+
3+
The [JSR 370](https://www.jcp.org/en/jsr/detail?id=370) specifies the JavaTM API for RESTful Web Services - Server-Sent Events (SSE).
4+
5+
## Samples ##
6+
7+
- producer

sse/pom.xml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
3+
4+
<parent>
5+
<groupId>org.javaee8</groupId>
6+
<artifactId>samples-parent</artifactId>
7+
<version>1.0-SNAPSHOT</version>
8+
</parent>
9+
10+
<artifactId>sse</artifactId>
11+
<packaging>pom</packaging>
12+
13+
<name>Java EE 8 Samples: Server Sent Events</name>
14+
15+
<modules>
16+
<module>producer</module>
17+
</modules>
18+
19+
<dependencies>
20+
<dependency>
21+
<groupId>org.javaee8</groupId>
22+
<artifactId>test-utils</artifactId>
23+
<version>${project.version}</version>
24+
</dependency>
25+
<dependency>
26+
<groupId>org.glassfish.jersey.media</groupId>
27+
<artifactId>jersey-media-sse</artifactId>
28+
<version>2.26</version>
29+
</dependency>
30+
<dependency>
31+
<groupId>javax.ws.rs</groupId>
32+
<artifactId>javax.ws.rs-api</artifactId>
33+
<version>2.1</version>
34+
</dependency>
35+
</dependencies>
36+
</project>

sse/producer/pom.xml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
3+
4+
<parent>
5+
<groupId>org.javaee8</groupId>
6+
<artifactId>sse</artifactId>
7+
<version>1.0-SNAPSHOT</version>
8+
</parent>
9+
10+
<artifactId>sse-producer</artifactId>
11+
<packaging>war</packaging>
12+
<name>Java EE 8 Samples: Server Sent Events [Producer]</name>
13+
<dependencies>
14+
<!-- JSON-B API -->
15+
<dependency>
16+
<groupId>javax.json.bind</groupId>
17+
<artifactId>javax.json.bind-api</artifactId>
18+
<version>1.0.0-RC2</version>
19+
</dependency>
20+
21+
<!-- Yasson (JSON-B RI) -->
22+
<dependency>
23+
<groupId>org.eclipse</groupId>
24+
<artifactId>yasson</artifactId>
25+
<version>1.0.0-RC1</version>
26+
<scope>runtime</scope>
27+
</dependency>
28+
</dependencies>
29+
</project>
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* To change this license header, choose License Headers in Project Properties.
3+
* To change this template file, choose Tools | Templates
4+
* and open the template in the editor.
5+
*/
6+
package org.javaee8.sse.data;
7+
8+
import java.util.Date;
9+
import java.util.UUID;
10+
import javax.json.bind.JsonbBuilder;
11+
12+
/**
13+
*
14+
* @author daniel
15+
*/
16+
public class EventData {
17+
18+
private Date time;
19+
private String id;
20+
private String comment;
21+
22+
public EventData() {
23+
super();
24+
}
25+
26+
public EventData(String comment) {
27+
super();
28+
this.setTime(new Date());
29+
this.setId(UUID.randomUUID().toString());
30+
this.setComment(comment);
31+
}
32+
33+
public Date getTime() {
34+
return time;
35+
}
36+
37+
public void setTime(Date time) {
38+
this.time = time;
39+
}
40+
41+
public String getId() {
42+
return id;
43+
}
44+
45+
public void setId(String id) {
46+
this.id = id;
47+
}
48+
49+
public String getComment() {
50+
return comment;
51+
}
52+
53+
public void setComment(String comment) {
54+
this.comment = comment;
55+
}
56+
57+
@Override
58+
public String toString() {
59+
return JsonbBuilder.create().toJson(this);
60+
}
61+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package org.javaee8.sse.producer;
2+
3+
import javax.annotation.PostConstruct;
4+
import javax.inject.Singleton;
5+
import javax.json.bind.Jsonb;
6+
import javax.json.bind.JsonbBuilder;
7+
import javax.ws.rs.GET;
8+
import javax.ws.rs.Path;
9+
import javax.ws.rs.Produces;
10+
import javax.ws.rs.core.Context;
11+
import javax.ws.rs.core.MediaType;
12+
import javax.ws.rs.sse.Sse;
13+
import javax.ws.rs.sse.SseBroadcaster;
14+
import javax.ws.rs.sse.SseEventSink;
15+
import org.javaee8.sse.data.EventData;
16+
17+
/**
18+
* @author Daniel Contreras
19+
*/
20+
@Path("sse")
21+
@Singleton
22+
public class SseResource {
23+
24+
@Context
25+
private Sse sse;
26+
27+
private volatile SseBroadcaster sseBroadcaster;
28+
29+
@PostConstruct
30+
public void init() {
31+
this.sseBroadcaster = sse.newBroadcaster();
32+
}
33+
34+
@GET
35+
@Path("register")
36+
@Produces(MediaType.SERVER_SENT_EVENTS)
37+
public void register(@Context SseEventSink eventSink) {
38+
39+
Jsonb jsonb = JsonbBuilder.create();
40+
41+
eventSink.send(sse.newEvent("INIT",new EventData("event:intialized").toString()));
42+
43+
sseBroadcaster.register(eventSink);
44+
45+
for (int i = 0; i < 5; i++) {
46+
47+
sseBroadcaster.broadcast(sse.newEvent("EVENT",new EventData("event:"+i).toString()));
48+
49+
try {
50+
Thread.sleep(100);
51+
} catch (InterruptedException e) {
52+
e.printStackTrace();
53+
}
54+
}
55+
56+
eventSink.send(sse.newEvent("FINISH",new EventData("event:finished").toString()));
57+
}
58+
59+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* To change this license header, choose License Headers in Project Properties.
3+
* To change this template file, choose Tools | Templates
4+
* and open the template in the editor.
5+
*/
6+
package org.javaee8.sse.rest;
7+
8+
import javax.ws.rs.ApplicationPath;
9+
import javax.ws.rs.core.Application;
10+
11+
/**
12+
*
13+
* @author daniel
14+
*/
15+
@ApplicationPath("rest")
16+
public class RestApplication extends Application {
17+
18+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<!DOCTYPE html>
2+
<!--
3+
To change this license header, choose License Headers in Project Properties.
4+
To change this template file, choose Tools | Templates
5+
and open the template in the editor.
6+
7+
@author Daniel Contreras
8+
-->
9+
<html>
10+
<head>
11+
<title>SSE</title>
12+
<meta charset="UTF-8">
13+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
14+
</head>
15+
<body>
16+
17+
<span id="foo"></span>
18+
19+
<br><br>
20+
<button onclick="start()">Start</button>
21+
22+
<script>
23+
24+
function start() {
25+
26+
var eventSource = new EventSource("rest/sse/register");
27+
console.log(eventSource);
28+
29+
eventSource.onmessage = function (event) {
30+
console.log(event)
31+
var el = document.getElementById("foo");
32+
el.innerHTML += event.data + "<br/>";
33+
el.scrollTop += 50;
34+
};
35+
36+
eventSource.addEventListener('broadcast', function (event) {
37+
38+
console.log(event)
39+
var el = document.getElementById("foo");
40+
el.innerHTML += event.data + "lt;br/&>";
41+
el.scrollTop += 50;
42+
43+
}, false);
44+
}
45+
</script>
46+
</body>
47+
</html>
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package org.javaee8.sse.producer;
2+
3+
import static org.jboss.shrinkwrap.api.ShrinkWrap.create;
4+
5+
import java.io.IOException;
6+
import java.net.URL;
7+
import java.util.Arrays;
8+
import java.util.Date;
9+
import javax.json.bind.Jsonb;
10+
import javax.json.bind.JsonbBuilder;
11+
12+
import org.jboss.arquillian.container.test.api.Deployment;
13+
import org.jboss.arquillian.container.test.api.RunAsClient;
14+
import org.jboss.arquillian.junit.Arquillian;
15+
import org.jboss.arquillian.test.api.ArquillianResource;
16+
import org.jboss.shrinkwrap.api.spec.WebArchive;
17+
import org.junit.After;
18+
import org.junit.Before;
19+
import org.junit.Test;
20+
import org.junit.runner.RunWith;
21+
22+
import javax.ws.rs.client.Client;
23+
import javax.ws.rs.client.ClientBuilder;
24+
import javax.ws.rs.client.WebTarget;
25+
import javax.ws.rs.sse.SseEventSource;
26+
import static org.hamcrest.CoreMatchers.instanceOf;
27+
import org.javaee8.sse.data.EventData;
28+
import org.javaee8.sse.rest.RestApplication;
29+
import static org.junit.Assert.assertNotNull;
30+
import static org.junit.Assert.assertThat;
31+
import static org.junit.Assert.assertTrue;
32+
33+
/**
34+
* @author Daniel Contreras
35+
*/
36+
@RunWith(Arquillian.class)
37+
public class SseResourceTest {
38+
39+
@ArquillianResource
40+
private URL base;
41+
42+
private Client sseClient;
43+
private WebTarget target;
44+
45+
SseEventSource eventSource;
46+
47+
@Deployment(testable = false)
48+
public static WebArchive createDeployment() {
49+
return create(WebArchive.class)
50+
.addClasses(RestApplication.class, SseResource.class, EventData.class, JsonbBuilder.class, Jsonb.class);
51+
}
52+
53+
@Before
54+
public void setup() {
55+
this.sseClient = ClientBuilder.newClient();
56+
this.target = this.sseClient.target(base + "rest/sse/register");
57+
eventSource = SseEventSource.target(target).build();
58+
System.out.println("SSE Event source created........");
59+
}
60+
61+
@After
62+
public void teardown() {
63+
eventSource.close();
64+
System.out.println("Closed SSE Event source..");
65+
sseClient.close();
66+
System.out.println("Closed JAX-RS client..");
67+
}
68+
69+
String[] types = {"INIT", "EVENT", "FINISH"};
70+
71+
@Test
72+
@RunAsClient
73+
public void testSSE() throws IOException {
74+
75+
Jsonb jsonb = JsonbBuilder.create();
76+
77+
System.out.println("SSE Client triggered in thread " + Thread.currentThread().getName());
78+
try {
79+
eventSource.register(
80+
(sseEvent)
81+
-> {
82+
assertTrue(Arrays.asList(types).contains(sseEvent.getName()));
83+
assertNotNull(sseEvent.readData());
84+
EventData event = jsonb.fromJson(sseEvent.readData(), EventData.class);
85+
assertThat(event.getTime(), instanceOf(Date.class));
86+
assertNotNull(event.getId());
87+
assertTrue(event.getComment().contains("event:"));
88+
System.out.println("\nSSE Event received :: " + event.toString() +"\n");
89+
90+
},
91+
(e) -> e.printStackTrace());
92+
93+
eventSource.open();
94+
Thread.sleep(1500);
95+
} catch (Exception e) {
96+
System.out.println("Error on SSE Test");
97+
System.out.println(e.getMessage());
98+
}
99+
100+
}
101+
102+
}

0 commit comments

Comments
 (0)