-
Notifications
You must be signed in to change notification settings - Fork 368
Description
I have filed an issue on Glassfish, eclipse-ee4j/glassfish#25323 but no one responded to it. I am not sure if it is an issue of the spec implementer.
Environment Details
- GlassFish Version (and build number): 8.0.0-M9
- JDK version: 21
- OS: Windows 10 Pro 64bit
- Database: Built-in derby and Docker/Postgres
Problem Description
In my cargo tracker fork, I tried to add an SSE broadcast endpoint to HTTP client to track the cargo event.
When using constructor inject, I have tried both EJB @Singleton and CDI @Singletone/@applicationScoped, but all do not work. But Replace the constructor injection with field injection, and it worked.
@Singleton
// @ApplicationScoped
@Path("tracking")
public class RealtimeCargoTrackingSseService {
private static final Logger LOGGER =
Logger.getLogger(RealtimeCargoTrackingSseService.class.getName());
private Sse sse;
private SseBroadcaster sseBroadcaster;
public RealtimeCargoTrackingSseService() {}
public RealtimeCargoTrackingSseService(@Context Sse sse) {
this.sse = sse;
this.sseBroadcaster = sse.newBroadcaster();
this.sseBroadcaster.onClose(
sseEventSink -> {
try {
sseEventSink.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
});
this.sseBroadcaster.onError(
(sseEventSink, throwable) -> {
sseEventSink.send(sse.newEvent("error", throwable.getMessage()));
try {
sseEventSink.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
});
}
@GET
@Produces(SERVER_SENT_EVENTS)
public void register(@Context SseEventSink sink) {
LOGGER.log(Level.INFO, "register sink: {0}", sink);
this.sseBroadcaster.register(sink);
}
public void onCargoInspected(@Observes @CargoInspected Cargo cargo) {
LOGGER.log(INFO, "observers cargo inspected event of cargo: {0}", cargo.getTrackingId());
Writer writer = new StringWriter();
try (JsonGenerator generator = Json.createGenerator(writer)) {
generator
.writeStartObject()
.write("trackingId", cargo.getTrackingId().id())
.write("origin", cargo.getOrigin().getName())
.write("destination", cargo.getRouteSpecification().destination().getName())
.write("lastKnownLocation", cargo.getDelivery().lastKnownLocation().getName())
.write("transportStatus", cargo.getDelivery().transportStatus().name())
.writeEnd();
}
String jsonValue = writer.toString();
LOGGER.log(INFO, "sending message to client: {0}", jsonValue);
OutboundSseEvent event =
sse.newEventBuilder()
.name("event")
.mediaType(APPLICATION_JSON_TYPE)
.data(jsonValue)
.build();
LOGGER.log(INFO, "broadcast event: {0}", event);
this.sseBroadcaster.broadcast(event);
}
}It failed due to the NullPionterException from this.sseBroadcaster and this.sse in the further methods(eg. register) being called when registering the SSE client connection.
Problem Reproducer
git clone https://github.com/hantsy/cargotracker- switch to
ee11branch. - Run test
mvn clean verify -P"arq-glassfish-managed" -D"it.test=RealtimeCargoTrackingSseServiceTest" - Or run the application in Glassfish container.
docker compose up postgresmvn clean package cargo:run -P"glassfish"curl http://localhost:8080/cargo-tracker/rest/tracking
My SSE class is similar to the broadcaster example in the Jersey docs, https://eclipse-ee4j.github.io/jersey.github.io/documentation/latest/sse.html and I remember this pattern worked in before projects.