Skip to content

Constructor Inject Sse failed  #25323

Description

@hantsy

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.

Replace the constructor injection with field injection, it worked.

// I have tried both ejb `@Singleton` and CDi `@applicationScoped`.
@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

  1. git clone https://github.com/hantsy/cargotracker
  2. switch to ee11 branch.
  3. Run test mvn clean verify -P"arq-glassfish-managed" -D"it.test=RealtimeCargoTrackingSseServiceTest"
  4. Or run the application in Glassfish container.
    • docker compose up postgres
    • mvn 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    8.0Issues that happen only on GlassFish 8 and not in version 7

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions