Skip to content
This repository was archived by the owner on May 28, 2018. It is now read-only.

Commit 9add7e3

Browse files
pavelbucekGerrit Code Review
authored andcommitted
Merge "Change OutboundEventWriter accepted type to comply with specs"
2 parents 1205156 + 912c190 commit 9add7e3

File tree

2 files changed

+213
-6
lines changed

2 files changed

+213
-6
lines changed

media/sse/src/main/java/org/glassfish/jersey/media/sse/OutboundEventWriter.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33
*
4-
* Copyright (c) 2012-2015 Oracle and/or its affiliates. All rights reserved.
4+
* Copyright (c) 2012-2017 Oracle and/or its affiliates. All rights reserved.
55
*
66
* The contents of this file are subject to the terms of either the GNU
77
* General Public License Version 2 only ("GPL") or the Common Development
@@ -49,6 +49,7 @@
4949
import javax.ws.rs.core.MediaType;
5050
import javax.ws.rs.core.MultivaluedMap;
5151
import javax.ws.rs.ext.MessageBodyWriter;
52+
import javax.ws.rs.sse.OutboundSseEvent;
5253

5354
import javax.inject.Inject;
5455
import javax.inject.Provider;
@@ -57,12 +58,12 @@
5758
import org.glassfish.jersey.message.MessageUtils;
5859

5960
/**
60-
* Writer for {@link OutboundEvent}.
61+
* Writer for {@link OutboundSseEvent}.
6162
*
6263
* @author Pavel Bucek (pavel.bucek at oracle.com)
6364
* @author Marek Potociar (marek.potociar at oracle.com)
6465
*/
65-
class OutboundEventWriter implements MessageBodyWriter<OutboundEvent> {
66+
class OutboundEventWriter implements MessageBodyWriter<OutboundSseEvent> {
6667

6768
private static final Charset UTF8 = Charset.forName("UTF-8");
6869

@@ -80,11 +81,11 @@ class OutboundEventWriter implements MessageBodyWriter<OutboundEvent> {
8081
@Override
8182
public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
8283
final MediaType mediaType) {
83-
return type.equals(OutboundEvent.class) && SseFeature.SERVER_SENT_EVENTS_TYPE.isCompatible(mediaType);
84+
return OutboundSseEvent.class.isAssignableFrom(type) && SseFeature.SERVER_SENT_EVENTS_TYPE.isCompatible(mediaType);
8485
}
8586

8687
@Override
87-
public long getSize(final OutboundEvent incomingEvent,
88+
public long getSize(final OutboundSseEvent incomingEvent,
8889
final Class<?> type,
8990
final Type genericType,
9091
final Annotation[] annotations,
@@ -94,7 +95,7 @@ public long getSize(final OutboundEvent incomingEvent,
9495

9596
@Override
9697
@SuppressWarnings("unchecked")
97-
public void writeTo(final OutboundEvent outboundEvent,
98+
public void writeTo(final OutboundSseEvent outboundEvent,
9899
final Class<?> type,
99100
final Type genericType,
100101
final Annotation[] annotations,
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
/*
2+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3+
*
4+
* Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
5+
*
6+
* The contents of this file are subject to the terms of either the GNU
7+
* General Public License Version 2 only ("GPL") or the Common Development
8+
* and Distribution License("CDDL") (collectively, the "License"). You
9+
* may not use this file except in compliance with the License. You can
10+
* obtain a copy of the License at
11+
* http://glassfish.java.net/public/CDDL+GPL_1_1.html
12+
* or packager/legal/LICENSE.txt. See the License for the specific
13+
* language governing permissions and limitations under the License.
14+
*
15+
* When distributing the software, include this License Header Notice in each
16+
* file and include the License file at packager/legal/LICENSE.txt.
17+
*
18+
* GPL Classpath Exception:
19+
* Oracle designates this particular file as subject to the "Classpath"
20+
* exception as provided by Oracle in the GPL Version 2 section of the License
21+
* file that accompanied this code.
22+
*
23+
* Modifications:
24+
* If applicable, add the following below the License Header, with the fields
25+
* enclosed by brackets [] replaced by your own identifying information:
26+
* "Portions Copyright [year] [name of copyright owner]"
27+
*
28+
* Contributor(s):
29+
* If you wish your version of this file to be governed by only the CDDL or
30+
* only the GPL Version 2, indicate your decision by adding "[Contributor]
31+
* elects to include this software in this distribution under the [CDDL or GPL
32+
* Version 2] license." If you don't indicate a single choice of license, a
33+
* recipient has the option to distribute your version of this file under
34+
* either the CDDL, the GPL Version 2 or to extend the choice of license to
35+
* its licensees as provided above. However, if you add GPL Version 2 code
36+
* and therefore, elected the GPL Version 2 license, then the option applies
37+
* only if the new code is made subject to such option by the copyright
38+
* holder.
39+
*/
40+
41+
package org.glassfish.jersey.tests.e2e.sse;
42+
43+
import java.lang.reflect.Type;
44+
import java.util.ArrayList;
45+
import java.util.List;
46+
import java.util.concurrent.CountDownLatch;
47+
import java.util.concurrent.ExecutorService;
48+
import java.util.concurrent.Executors;
49+
import java.util.concurrent.TimeUnit;
50+
51+
import javax.ws.rs.GET;
52+
import javax.ws.rs.Path;
53+
import javax.ws.rs.ProcessingException;
54+
import javax.ws.rs.Produces;
55+
import javax.ws.rs.client.WebTarget;
56+
import javax.ws.rs.core.Application;
57+
import javax.ws.rs.core.Context;
58+
import javax.ws.rs.core.MediaType;
59+
import javax.ws.rs.sse.InboundSseEvent;
60+
import javax.ws.rs.sse.OutboundSseEvent;
61+
import javax.ws.rs.sse.SseEventSink;
62+
import javax.ws.rs.sse.SseEventSource;
63+
64+
import javax.inject.Singleton;
65+
66+
import org.glassfish.jersey.media.sse.EventListener;
67+
import org.glassfish.jersey.media.sse.EventSource;
68+
import org.glassfish.jersey.server.ResourceConfig;
69+
import org.glassfish.jersey.test.JerseyTest;
70+
71+
import org.junit.Assert;
72+
import org.junit.Test;
73+
74+
/**
75+
* Test that {@link org.glassfish.jersey.media.sse.OutboundEventWriter} works with custom
76+
* {@link javax.ws.rs.sse.OutboundSseEvent} implementation.
77+
*
78+
* @author Adam Lindenthal (adam.lindenthal at oracle.com)
79+
*/
80+
public class SseCustomEventImplTest extends JerseyTest {
81+
82+
private static final String SSE_EVENT_NAME = "custom-message";
83+
84+
@Override
85+
protected Application configure() {
86+
return new ResourceConfig(SseResource.class);
87+
}
88+
89+
@Path("events")
90+
@Singleton
91+
public static class SseResource {
92+
93+
@GET
94+
@Produces(MediaType.SERVER_SENT_EVENTS)
95+
public void getServerSentEvents(@Context final SseEventSink eventSink) {
96+
ExecutorService executor = Executors.newSingleThreadExecutor();
97+
executor.submit(() -> {
98+
eventSink.send(new MyOutboundEvent("foo"));
99+
eventSink.send(new MyOutboundEvent("bar"));
100+
eventSink.send(new MyOutboundEvent("baz"));
101+
});
102+
}
103+
}
104+
105+
@Test
106+
public void testWithJaxRsAPI() {
107+
final WebTarget endpoint = target().path("events");
108+
final List<InboundSseEvent> results = new ArrayList<>();
109+
try (final SseEventSource eventSource = SseEventSource.target(endpoint).build()) {
110+
final CountDownLatch receivedLatch = new CountDownLatch(3);
111+
eventSource.register((event) -> {
112+
results.add(event);
113+
receivedLatch.countDown();
114+
});
115+
116+
eventSource.open();
117+
final boolean allReceived = receivedLatch.await(5000, TimeUnit.MILLISECONDS);
118+
Assert.assertTrue(allReceived);
119+
Assert.assertEquals(3, results.size());
120+
Assert.assertEquals("foo", results.get(0).readData());
121+
Assert.assertEquals("bar", results.get(1).readData());
122+
Assert.assertEquals("baz", results.get(2).readData());
123+
} catch (final InterruptedException e) {
124+
e.printStackTrace();
125+
}
126+
}
127+
128+
@Test
129+
public void testWithJerseyAPI() throws InterruptedException {
130+
final WebTarget endpoint = target().path("events");
131+
final EventSource eventSource = EventSource.target(endpoint).build();
132+
final CountDownLatch receiveLatch = new CountDownLatch(3);
133+
134+
final List<String> results = new ArrayList<>();
135+
final EventListener listener = inboundEvent -> {
136+
try {
137+
results.add(inboundEvent.readData());
138+
receiveLatch.countDown();
139+
Assert.assertEquals(SSE_EVENT_NAME, inboundEvent.getName());
140+
} catch (ProcessingException ex) {
141+
throw new RuntimeException("Error when deserializing of data.", ex);
142+
}
143+
};
144+
eventSource.register(listener, SSE_EVENT_NAME);
145+
eventSource.open();
146+
Assert.assertTrue(receiveLatch.await(5000, TimeUnit.MILLISECONDS));
147+
Assert.assertEquals(3, results.size());
148+
Assert.assertEquals("foo", results.get(0));
149+
Assert.assertEquals("bar", results.get(1));
150+
Assert.assertEquals("baz", results.get(2));
151+
}
152+
153+
static class MyOutboundEvent implements OutboundSseEvent {
154+
155+
private String data;
156+
157+
public MyOutboundEvent(String data) {
158+
this.data = data;
159+
}
160+
161+
@Override
162+
public Class<?> getType() {
163+
return String.class;
164+
}
165+
166+
@Override
167+
public Type getGenericType() {
168+
return String.class;
169+
}
170+
171+
@Override
172+
public MediaType getMediaType() {
173+
return MediaType.TEXT_PLAIN_TYPE;
174+
}
175+
176+
@Override
177+
public String getData() {
178+
return data;
179+
}
180+
181+
@Override
182+
public String getId() {
183+
return null;
184+
}
185+
186+
@Override
187+
public String getName() {
188+
return SSE_EVENT_NAME;
189+
}
190+
191+
@Override
192+
public String getComment() {
193+
return "";
194+
}
195+
196+
@Override
197+
public long getReconnectDelay() {
198+
return 0;
199+
}
200+
201+
@Override
202+
public boolean isReconnectDelaySet() {
203+
return false;
204+
}
205+
}
206+
}

0 commit comments

Comments
 (0)