Skip to content

Commit

Permalink
Add @Inject Sse support
Browse files Browse the repository at this point in the history
Signed-off-by: jansupol <jan.supol@oracle.com>
  • Loading branch information
jansupol committed Mar 24, 2021
1 parent 754a8b0 commit 9ffd014
Show file tree
Hide file tree
Showing 6 changed files with 255 additions and 15 deletions.
7 changes: 6 additions & 1 deletion bom/pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
Expand Down Expand Up @@ -243,6 +243,11 @@
<artifactId>jersey-cdi1x-ban-custom-hk2-binding</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext.cdi</groupId>
<artifactId>jersey-cdi-inject</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext.rx</groupId>
<artifactId>jersey-rx-client-guava</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.ParamConverterProvider;
import java.lang.reflect.Type;
import javax.ws.rs.ext.Providers;
import javax.ws.rs.sse.Sse;
import java.security.AccessController;
import java.util.HashSet;
import java.util.Set;
Expand All @@ -57,10 +58,9 @@
@SuppressWarnings("unused")
class InjectExtension implements Extension {
private void processAnnotatedType(@Observes ProcessAnnotatedType<?> processAnnotatedType, BeanManager beanManager) {
final Type baseType = processAnnotatedType.getAnnotatedType().getBaseType();
if (Application.class.isAssignableFrom((Class<?>) baseType)
&& Configuration.class.isAssignableFrom((Class<?>) baseType)) {
if (!((Class<?>) baseType).isAnnotationPresent(Alternative.class)) {
final Class<?> baseClass = (Class<?>) processAnnotatedType.getAnnotatedType().getBaseType();
if (Application.class.isAssignableFrom(baseClass) && Configuration.class.isAssignableFrom(baseClass)) {
if (!baseClass.isAnnotationPresent(Alternative.class)) {
processAnnotatedType.veto(); // Filter bean annotated ResourceConfig
}
}
Expand All @@ -87,11 +87,12 @@ private static Set<Class<?>> sumNonJerseyBoundInjectables() {
injectables.add(ContainerRequestContext.class);
injectables.add(HttpHeaders.class);
injectables.add(ParamConverterProvider.class);
injectables.add(javax.ws.rs.ext.Providers.class);
injectables.add(Providers.class);
injectables.add(Request.class);
injectables.add(ResourceContext.class);
injectables.add(ResourceInfo.class);
injectables.add(SecurityContext.class);
injectables.add(Sse.class);
injectables.add(UriInfo.class);

//Servlet if available
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
Expand All @@ -66,18 +65,21 @@
<dependency>
<groupId>org.jboss.weld.se</groupId>
<artifactId>weld-se-core</artifactId>
<version>3.0.3.Final</version>
<!-- latest 3.x -->
<version>3.1.7.Final</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext.cdi</groupId>
<artifactId>jersey-cdi1x</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext.cdi</groupId>
<artifactId>jersey-cdi-inject</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-sse</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,11 @@
import org.glassfish.jersey.internal.PropertiesDelegate;
import org.glassfish.jersey.servlet.WebConfig;

import javax.enterprise.inject.spi.BeanManager;
import javax.inject.Inject;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ResourceContext;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.Application;
Expand Down Expand Up @@ -58,10 +56,10 @@ public class ParentInject implements ParentChecker {
protected HttpHeaders injectHttpHeaders;

@Context
ParamConverterProvider contextParamConverterProvider;
protected ParamConverterProvider contextParamConverterProvider;

@Inject
ParamConverterProvider injectParamConverterProvider;
protected ParamConverterProvider injectParamConverterProvider;

@Context
protected PropertiesDelegate contextPropertiesDelegate;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/

package org.glassfish.jersey.tests.cdi.inject;

import org.glassfish.jersey.server.ServerProperties;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.sse.Sse;
import javax.ws.rs.sse.SseBroadcaster;
import javax.ws.rs.sse.SseEventSink;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class SseAplication extends Application {

@Path(InjectionChecker.ROOT)
@ApplicationScoped
public static class ApplicationScopedResource {
@Context
Sse contextSse;

@Inject
Sse injectSse;

private static SseBroadcaster contextSseBroadcaster;
private static SseBroadcaster injectSseBroadcaster;

@GET
@Path("register/{x}")
@Produces(MediaType.SERVER_SENT_EVENTS)
public void register(@PathParam("x") String inject, @Context SseEventSink eventSink) {
if (inject.contains("context")) {
contextSseBroadcaster = contextSse.newBroadcaster();
contextSseBroadcaster.register(eventSink);
eventSink.send(contextSse.newEvent(inject));
} else {
injectSseBroadcaster = injectSse.newBroadcaster();
injectSseBroadcaster.register(eventSink);
eventSink.send(injectSse.newEvent(inject));
}
}

@POST
@Path("broadcast/{x}")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public void broadcast(@PathParam("x") String inject, String event) {
if (inject.contains("context")) {
if (contextSseBroadcaster == null) {
throw new IllegalStateException("contextSseBroadcaster is null");
} else if (contextSse == null) {
throw new IllegalStateException("contextSse is null");
}
contextSseBroadcaster.broadcast(contextSse.newEvent(event));
contextSseBroadcaster.close();
} else {
if (injectSseBroadcaster == null) {
throw new IllegalStateException("injectSseBroadcaster is null");
} else if (injectSse == null) {
throw new IllegalStateException("injectSse is null");
}
injectSseBroadcaster.broadcast(injectSse.newEvent(event));
injectSseBroadcaster.close();
}
}
}

@Override
public Set<Class<?>> getClasses() {
return Collections.singleton(ApplicationScopedResource.class);
}

@Override
public Map<String, Object> getProperties() {
Map<String, Object> props = new HashMap<>(1);
props.put(ServerProperties.WADL_FEATURE_DISABLE, true);
return props;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/

package org.glassfish.jersey.tests.cdi.inject;

import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory;
import org.glassfish.jersey.servlet.ServletProperties;
import org.glassfish.jersey.test.DeploymentContext;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.ServletDeploymentContext;
import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
import org.glassfish.jersey.test.spi.TestContainerException;
import org.glassfish.jersey.test.spi.TestContainerFactory;
import org.jboss.weld.environment.se.Weld;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;

import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.sse.SseEventSource;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class SseTest extends JerseyTest {
private Weld weld;

@Before
public void setup() {
Assume.assumeTrue(Hk2InjectionManagerFactory.isImmediateStrategy());
}

@Override
public void setUp() throws Exception {
if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
weld = new Weld();
weld.initialize();
super.setUp();
}
}

@Override
public void tearDown() throws Exception {
if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
weld.shutdown();
super.tearDown();
}
}

@Override
protected Application configure() {
return new SseAplication();
}

@Override
protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
return new GrizzlyWebTestContainerFactory();
}

@Override
protected DeploymentContext configureDeployment() {
return ServletDeploymentContext.builder(configure())
.initParam(ServletProperties.JAXRS_APPLICATION_CLASS, SseAplication.class.getName())
.build();
}

@Test
public void testContextSse() throws InterruptedException {
testSse("contexted");
}

@Test
public void testInjectSse() throws InterruptedException {
testSse("injected");
}

private void testSse(String injectType) throws InterruptedException {
final String entity = "Everyone !!!";
final CountDownLatch broadcastLatch = new CountDownLatch(2);
final CountDownLatch registerLatch = new CountDownLatch(1);
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

final WebTarget target = target(InjectionChecker.ROOT).path("register").path(injectType);
try (SseEventSource source = SseEventSource.target(target).build()) {
source.register(inboundSseEvent -> {
try {
byteArrayOutputStream.write(inboundSseEvent.readData(String.class).getBytes());
registerLatch.countDown();
broadcastLatch.countDown();
} catch (IOException e) {
throw new RuntimeException(e);
}
});
source.open();
registerLatch.await(5000, TimeUnit.MILLISECONDS);
Assert.assertEquals(0, registerLatch.getCount());

try (Response response = target(InjectionChecker.ROOT).path("broadcast").path(injectType)
.request()
.post(Entity.entity(entity, MediaType.MULTIPART_FORM_DATA_TYPE))) {
String readEntity = response.readEntity(String.class);
// System.out.println(readEntity);
Assert.assertEquals(readEntity, response.getStatus(), Response.Status.NO_CONTENT.getStatusCode());

}
broadcastLatch.await(5000, TimeUnit.MILLISECONDS);
}
Assert.assertTrue(byteArrayOutputStream.toString().contains(entity));
Assert.assertEquals(0, broadcastLatch.getCount());
}
}

0 comments on commit 9ffd014

Please sign in to comment.