Search code examples
javaweld

Inject EJB in @serverEndpoint class results in NullPointerException


I'm using Swarm Wildfly to deploy this application. Basically I'm making a websocket enabled application.

I'd like to inject a singleton which will be started on the startup which modify the variable result.

Upon accessing the "/rafflethis" link, user will be able to see the result which will be sent via session.

The result is that the roll variable null

This is the class

@Singleton
@Startup
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class runMe implements RaffleManager{
  private static final Logger LOGGER = Logger.getLogger(runMe.class.getName());

  private static String result;

  @PostConstruct
  public void onStartup() {
    System.out.println("Initialization success.");
  }

  @Schedule(second = "*/10", minute = "*", hour = "*", persistent = false)
  public void run() throws Exception{
    int i = 0;
    while (true) {
      Thread.sleep(1000L);
      result = UUID.randomUUID().toString().toUpperCase();
      i++;
      LOGGER.log(Level.INFO, "i : " + i);
    }
  }

  public String getResult() {
    return result;
  }
}

interface

public interface RaffleManager {
  String getResult();
}

And the "/rafflethis"

@ServerEndpoint("/rafflethis")
public class RaffleThis implements Serializable {
  @EJB
  RaffleManager roll;

  private static final Set<Session> sessions = Collections.synchronizedSet(new HashSet<Session>());

  private static void sendMessageToAll(String message) {
    for (Session s : sessions) {
      try {
        s.getBasicRemote().sendText(message);
      } catch (IOException ex) {
        ex.printStackTrace();
      }
    }
  }

  @OnOpen
  public void monitorLuckyDip(Session session) throws Exception {
    sessions.add(session);
    while(true) {
      sendMessageToAll(roll.getResult());
    }
  }
}

Any lead where should I head from this? Thanks!


Solution

  • The solution is rather hacky but a very simple one indeed. Take a look at the provided diagram.

    Logic

    And here's the code

    Logic Implementation:

    @Startup
    @Singleton
    public class RunMe{
      private static final Logger LOGGER = Logger.getLogger(RunMe.class.getName());
    
    
      @Inject
      MessageDTO messageDTO;
    
    
      @PostConstruct
      public void onStartup() {
        System.out.println("Initialization success.");
      }
    
      @Schedule(second = "*/10", minute = "*", hour = "*", persistent = false)
      public void run() throws Exception{
        //You can also substitute this method with constructor of the class -- removing the @Schedule annotation.
        int i = 0;
        while (true) {
          Thread.sleep(1000L);
          messageDTO.setText(UUID.randomUUID().toString().toUpperCase());
          i++;
          LOGGER.log(Level.INFO, "i : " + i);
        }
      }
    }
    

    MessageDTO:

    @Singleton
    public class MessageDTO {
      private static String text;
    
      public static String getText() {
        return text;
      }
    
      public static void setText(String text) {
        MessageDTO.text = text;
      }
    }
    

    Websocket Implementation:

    @ServerEndpoint("/rafflethis")
    public class RaffleThis implements Serializable {
    
      private static final Logger LOGGER = Logger.getLogger(RaffleThis.class.getName());
      private static final Set<Session> sessions = Collections.synchronizedSet(new HashSet<Session>());
      @Inject
      MessageDTO messageDTO;
    
      private static void sendMessageToAll(String message) {
        for (Session s : sessions) {
          try {
            s.getBasicRemote().sendText(message);
          } catch (IOException ex) {
            ex.printStackTrace();
          }
        }
      }
    
      @OnOpen
      public void monitorLuckyDip(Session session) throws Exception {
        sessions.add(session);
        while (true) {
          Thread.sleep(200);
          sendMessageToAll(messageDTO.getText());
        }
      }
    }