Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit ffc9394

Browse files
Merge pull request #24 from dmatej/issue-23-SseResourceTest
Fixed #23 ClientConfig differs between appservers
2 parents b71d7c2 + e47b395 commit ffc9394

File tree

4 files changed

+92
-73
lines changed

4 files changed

+92
-73
lines changed

‎jaxrs/sse-producer/src/main/java/org/javaee8/jaxrs/sseproducer/data/EventData.java

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import java.util.Date;
44
import java.util.UUID;
5-
import javax.json.bind.JsonbBuilder;
65

76
/**
87
*
@@ -16,7 +15,7 @@ public class EventData {
1615

1716
public EventData() {
1817
}
19-
18+
2019
public EventData(String comment) {
2120
this.setTime(new Date());
2221
this.setId(UUID.randomUUID().toString());
@@ -46,9 +45,4 @@ public String getComment() {
4645
public void setComment(String comment) {
4746
this.comment = comment;
4847
}
49-
50-
@Override
51-
public String toString() {
52-
return JsonbBuilder.create().toJson(this);
53-
}
5448
}

‎jaxrs/sse-producer/src/main/java/org/javaee8/jaxrs/sseproducer/producer/SseResource.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@
1515
import org.javaee8.jaxrs.sseproducer.data.EventData;
1616

1717
/**
18+
* Produces server side events.
19+
*
1820
* @author Daniel Contreras
1921
*/
2022
@Path("sse")
2123
public class SseResource {
22-
24+
2325
@Context
2426
private Sse sse;
2527

@@ -34,25 +36,23 @@ public void init() {
3436
@Path("register")
3537
@Produces(MediaType.SERVER_SENT_EVENTS)
3638
public void register(@Context SseEventSink eventSink) {
37-
38-
Jsonb jsonb = JsonbBuilder.create();
3939

40-
eventSink.send(sse.newEvent("INIT",new EventData("event:intialized").toString()));
40+
final Jsonb json = JsonbBuilder.create();
41+
eventSink.send(sse.newEvent("INIT", json.toJson(new EventData("event:intialized"))));
4142

4243
sseBroadcaster.register(eventSink);
4344

4445
for (int i = 0; i < 5; i++) {
4546

46-
sseBroadcaster.broadcast(sse.newEvent("EVENT",new EventData("event:"+i).toString()));
47+
sseBroadcaster.broadcast(sse.newEvent("EVENT",json.toJson(new EventData("event:" + i))));
4748

4849
try {
49-
Thread.sleep(100);
50+
Thread.sleep(10);
5051
} catch (InterruptedException e) {
5152
e.printStackTrace();
5253
}
5354
}
54-
55-
eventSink.send(sse.newEvent("FINISH",new EventData("event:finished").toString()));
55+
56+
eventSink.send(sse.newEvent("FINISH",json.toJson(new EventData("event:finished"))));
5657
}
57-
5858
}

‎jaxrs/sse-producer/src/main/webapp/index.html

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
<!DOCTYPE html>
22
<!--
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-
73
@author Daniel Contreras
84
-->
95
<html>
@@ -20,23 +16,23 @@
2016
<button onclick="start()">Start</button>
2117

2218
<script>
23-
19+
2420
function start() {
2521

2622
var eventSource = new EventSource("rest/sse/register");
2723
console.log(eventSource);
2824

2925
eventSource.onmessage = function (event) {
3026
console.log(event)
31-
var el = document.getElementById("foo");
27+
var el = document.getElementById("foo");
3228
el.innerHTML += event.data + "<br/>";
3329
el.scrollTop += 50;
3430
};
3531

3632
eventSource.addEventListener('broadcast', function (event) {
3733

3834
console.log(event)
39-
var el = document.getElementById("foo");
35+
var el = document.getElementById("foo");
4036
el.innerHTML += event.data + "lt;br/&>";
4137
el.scrollTop += 50;
4238

Lines changed: 79 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,29 @@
11
package org.javaee8.jaxrs.sseproducer;
22

3+
import static org.hamcrest.CoreMatchers.instanceOf;
34
import static org.jboss.shrinkwrap.api.ShrinkWrap.create;
5+
import static org.junit.Assert.assertNotNull;
6+
import static org.junit.Assert.assertThat;
47

5-
import java.io.IOException;
68
import java.net.URL;
7-
import java.util.Arrays;
89
import java.util.Date;
10+
import java.util.Queue;
11+
import java.util.concurrent.ConcurrentLinkedQueue;
12+
import java.util.function.Consumer;
13+
914
import javax.json.bind.Jsonb;
1015
import javax.json.bind.JsonbBuilder;
16+
import javax.ws.rs.client.Client;
17+
import javax.ws.rs.client.ClientBuilder;
18+
import javax.ws.rs.client.WebTarget;
19+
import javax.ws.rs.core.Response;
20+
import javax.ws.rs.sse.InboundSseEvent;
21+
import javax.ws.rs.sse.SseEventSource;
1122

23+
import org.glassfish.jersey.client.ClientConfig;
24+
import org.glassfish.jersey.client.ClientProperties;
25+
import org.glassfish.jersey.client.HttpUrlConnectorProvider;
26+
import org.hamcrest.Matchers;
1227
import org.javaee8.jaxrs.sseproducer.data.EventData;
1328
import org.javaee8.jaxrs.sseproducer.producer.SseResource;
1429
import org.javaee8.jaxrs.sseproducer.rest.RestApplication;
@@ -22,82 +37,96 @@
2237
import org.junit.Test;
2338
import org.junit.runner.RunWith;
2439

25-
import javax.ws.rs.client.Client;
26-
import javax.ws.rs.client.ClientBuilder;
27-
import javax.ws.rs.client.WebTarget;
28-
import javax.ws.rs.sse.SseEventSource;
29-
import static org.hamcrest.CoreMatchers.instanceOf;
30-
import static org.junit.Assert.assertNotNull;
31-
import static org.junit.Assert.assertThat;
32-
import static org.junit.Assert.assertTrue;
33-
3440
/**
41+
* Test example for the Server-Sent Events with the Jersey JAX-RS implementation.
42+
*
3543
* @author Daniel Contreras
44+
* @author David Matějček
3645
*/
3746
@RunWith(Arquillian.class)
3847
public class SseResourceTest {
3948

49+
private static final String[] EVENT_TYPES = {"INIT", "EVENT", "FINISH"};
50+
4051
@ArquillianResource
4152
private URL base;
4253

4354
private Client sseClient;
4455
private WebTarget target;
56+
private SseEventSource eventSource;
4557

46-
SseEventSource eventSource;
47-
48-
@Deployment(testable = false)
58+
@Deployment(testable = true)
4959
public static WebArchive createDeployment() {
50-
return create(WebArchive.class)
51-
.addClasses(RestApplication.class, SseResource.class, EventData.class, JsonbBuilder.class, Jsonb.class);
60+
return create(WebArchive.class).addClasses(RestApplication.class, SseResource.class, EventData.class);
5261
}
5362

63+
64+
/**
65+
* Initializes the client, target and the eventSource used to create event consumers
66+
*/
5467
@Before
5568
public void setup() {
56-
this.sseClient = ClientBuilder.newClient();
57-
this.target = this.sseClient.target(base + "rest/sse/register");
58-
eventSource = SseEventSource.target(target).build();
69+
// this is needed to avoid a conflict with embedded server, that can have
70+
// customized configuration and connector providers.
71+
final ClientConfig configuration = new ClientConfig();
72+
configuration.property(ClientProperties.CONNECT_TIMEOUT, 100);
73+
configuration.property(ClientProperties.READ_TIMEOUT, 5000);
74+
configuration.connectorProvider(new HttpUrlConnectorProvider());
75+
this.sseClient = ClientBuilder.newClient(configuration);
76+
this.target = this.sseClient.target(this.base + "rest/sse/register");
77+
this.eventSource = SseEventSource.target(this.target).build();
5978
System.out.println("SSE Event source created........");
79+
final Response response = this.target.request().get();
80+
assertThat("GET response status - server is not ready", response.getStatus(),
81+
Matchers.equalTo(Response.Status.OK.getStatusCode()));
6082
}
6183

84+
85+
/**
86+
* Closes all client resources.
87+
*/
6288
@After
6389
public void teardown() {
64-
eventSource.close();
90+
this.eventSource.close();
6591
System.out.println("Closed SSE Event source..");
66-
sseClient.close();
92+
this.sseClient.close();
6793
System.out.println("Closed JAX-RS client..");
6894
}
6995

70-
String[] types = {"INIT", "EVENT", "FINISH"};
7196

72-
@Test
97+
/**
98+
* Registers reaction on events, waits for events and checks their content.
99+
*
100+
* @throws Exception
101+
*/
102+
@Test(timeout = 5000)
73103
@RunAsClient
74-
public void testSSE() throws IOException {
75-
76-
Jsonbjsonb = JsonbBuilder.create();
77-
78-
System.out.println("SSE Client triggered in thread " + Thread.currentThread().getName());
79-
try {
80-
eventSource.register(
81-
(sseEvent)
82-
-> {
83-
assertTrue(Arrays.asList(types).contains(sseEvent.getName()));
84-
assertNotNull(sseEvent.readData());
85-
EventDataevent = jsonb.fromJson(sseEvent.readData(), EventData.class);
86-
assertThat(event.getTime(), instanceOf(Date.class));
87-
assertNotNull(event.getId());
88-
assertTrue(event.getComment().contains("event:"));
89-
System.out.println("\nSSE Event received :: " + event.toString() +"\n");
90-
91-
},
92-
(e) -> e.printStackTrace());
93-
94-
eventSource.open();
95-
Thread.sleep(1500);
96-
} catch (Exceptione) {
97-
System.out.println("Error on SSE Test");
98-
System.out.println(e.getMessage());
104+
public void testSSE() throws Exception {
105+
finalQueue<Throwable> asyncExceptions = newConcurrentLinkedQueue<>();
106+
finalQueue<EventData> receivedEvents = newConcurrentLinkedQueue<>();
107+
// jsonb is thread safe!
108+
finalJsonbjsonb = JsonbBuilder.create();
109+
finalConsumer<InboundSseEvent> onEvent = (sseEvent) -> {
110+
assertThat("event type", sseEvent.getName(), Matchers.isOneOf(EVENT_TYPES));
111+
finalStringdata = sseEvent.readData();
112+
System.out.println("Data received as string:\n" + data);
113+
assertNotNull("data received as string", data);
114+
finalEventDataevent = jsonb.fromJson(data, EventData.class);
115+
receivedEvents.add(event);
116+
assertThat("event.time", event.getTime(), instanceOf(Date.class));
117+
assertNotNull("event.id", event.getId());
118+
assertThat("event.comment", event.getComment(), Matchers.containsString("event:"));
119+
};
120+
this.eventSource.register(onEvent, asyncExceptions::add);
121+
System.out.println("Server Side Events Client registered in the test thread.");
122+
// following line starts acceptation of events.
123+
this.eventSource.open();
124+
// don't end the test until we have all events or timeout or error comes.
125+
// this is not an obvious implementation, we only need to hold the test until all events
126+
// are asynchronously processed.
127+
while (receivedEvents.size() <= 5 && asyncExceptions.isEmpty()) {
128+
Thread.sleep(10L);
99129
}
100-
130+
assertThat("receiver exceptions", asyncExceptions, Matchers.emptyIterable());
101131
}
102-
103132
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /