Looking for a correct way to inject a jersey resource to a POJO class

33 Views Asked by At

I have implemented Jersey SSE, My requirement is to send notificaion to connected clients when there is a data chnage on the server.

Well My SSE is working, now I am trying to tie it up with the code in POJO class which detects data chnage.

My resource looks like this

package org.example;

import javax.annotation.PostConstruct;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.sse.OutboundSseEvent;
import javax.ws.rs.sse.Sse;
import javax.ws.rs.sse.SseEventSink;
import org.jvnet.hk2.annotations.Service;

@Service
@Path("events")
public class SSEResource {

    @Context
    Sse sse;

    private SSEConnectionManager connectionManager;

    @PostConstruct
    public void initialize() {
        connectionManager = SSEConnectionManager.getInstance();
        connectionManager.initialize(sse);
    }

    @GET
    @Produces(MediaType.SERVER_SENT_EVENTS)
    public void getServerSentEvents(@Context SseEventSink eventSink, @Context UriInfo uri) {

        MultivaluedMap<String, String> queryParams = uri.getQueryParameters();

        String closeParam = queryParams.getFirst("close");
        String clientIdParam = queryParams.getFirst("clientId");

        System.out.println("Client ID Parameter: " + clientIdParam);

        // Check if clientIdParam is missing or empty
        if (clientIdParam == null || clientIdParam.isEmpty()) {
            // Send a message to enter the clientId
            sendEventToClient(eventSink, "Please enter a valid clientId!");
            // Close the SSE connection since clientId is not provided
            eventSink.close();
            return; // Return early
        }

        if (closeParam != null && clientIdParam != null && !clientIdParam.isEmpty()) {
            // Close the SSE connection immediately
            eventSink.close();
            return; // Return early without sending the welcome message
        }

        // Check if the client has an existing connection
        if (connectionManager.isConnected(clientIdParam)) {
            connectionManager.closeConnection(clientIdParam);
        }

        // Add the connection to the SSEConnectionManager
        connectionManager.addConnection(clientIdParam, eventSink);

        // Send a welcome message to the client
        sendEventToClient(eventSink, "Welcome to SSE, Client " + clientIdParam + "!");
    }

    // Method to send an SSE event to a specific client
    private void sendEventToClient(SseEventSink eventSink, String data) {
        final OutboundSseEvent event = sse.newEventBuilder().name("message-to-client").data(String.class, data).build();
        eventSink.send(event);
    }


    public void sendEventToSpecificClient(String clientId, String message) {
        try {
            System.out.println("Client ID Parameter: " + clientId);
            if (clientId != null && !clientId.isEmpty()) {
                // Check if the client is connected
                if (connectionManager.isConnected(clientId)) {
                    try {
                        sendEventToClient(connectionManager.getConnection(clientId), message);
                    } catch (Exception e) {
                        // Handle any exceptions that occur during sending the event
                        System.out.println("Error sending event to Client " + clientId + ": " + e.getMessage());
                    }
                } else {
                    System.out.println("Client " + clientId + " not connected!");
                }
            }
        } finally {
            // eventSink.close(); // Close the SseEventSink in the finally block
        }
    }

    @GET
    @Path("close/{clientId}")
    @Produces(MediaType.TEXT_PLAIN)
    public String closeConnection(@PathParam("clientId") String clientId) {
        if (clientId != null && !clientId.isEmpty()) {
            if (connectionManager.isConnected(clientId)) {
                connectionManager.closeConnection(clientId);
                return "SSE connection closed for client " + clientId;
            } else {
                return "Client " + clientId + " not connected!";
            }
        } else {
            return "Invalid client ID!";
        }
    }


    public void broadcastEvent(String message) {
        final OutboundSseEvent event = sse.newEventBuilder().name("broadcast").mediaType(MediaType.TEXT_PLAIN_TYPE).data(String.class, message).build();

        // Broadcast the event to all connected clients
        connectionManager.getBroadcaster().broadcast(event);
    }
}

What I want to be able to is to call sendEventToSpecificClient() or broadcastEvent() from my POJO class

For testing sake I created this, but sseResource is always null

import javax.inject.Inject;


public class MainApp {

    @Inject
    SSEResource sseResource;


    public static void main(String[] args) {
        // Simulate the client ID and message
        String clientId = "123";
        String message = "This is a test message.";

        new MainApp().call(clientId, message);


    }

    void call(String clientId, String message) {

        // Call the sendEventToSpecificClient method to send the event
        sseResource.sendEventToSpecificClient(clientId, message);
    }
}

Here's is MyApplication.java


import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.server.ResourceConfig;

public class MyApplication extends ResourceConfig {

    public MyApplication() {
        // Register your resource classes or packages here using packages(), register(), etc.
        packages("org.example");

        // Register the AppLifecycleListener
        register(AppLifecycleListener.class);

        // Register the AbstractBinder with the bindings for dependency injection
        register(new AbstractBinder() {
            @Override
            protected void configure() {
                // Bind the SSEResource class to itself (no need to specify the same class again)
                bind(SSEResource.class).to(SSEResource.class);
            }
        });
    }
}

How Can properly inject the SSEresource in normal POJO class? I am using HK2 which comes with jersey.

0

There are 0 best solutions below