2015-11-26 2 views
1

Я использую Swarm Wildfly для развертывания этого приложения. В основном я создаю приложение с поддержкой websocket.Inject EJB в классе @serverEndpoint приводит к ошибке NullPointerException

Я хотел бы ввести один синглтон, который будет запущен при запуске, который изменит результат переменной.

После доступа к ссылке «/ rafflethis» пользователь сможет увидеть результат, который будет отправлен через сеанс.

Результатом является то, что roll переменная нуль

Это класс

@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; 
    } 
} 

интерфейс

public interface RaffleManager { 
    String getResult(); 
} 

И "/ 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()); 
    } 
    } 
} 

Любое руководство, с чего я должен от головы? Благодаря!

ответ

0

Решение довольно Hacky, но очень простой в самом деле. Взгляните на предоставленную диаграмму.

Logic

А вот код

Логика Реализация:

@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 Реализация:

@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()); 
    } 
    } 
} 
1

Глядя на источник, я бы предположил, что проблема с именем. Ваш синглтон bean «runMe» является фактическим именем компонента, а не интерфейсом.

СТОРОНА ПРИМЕЧАНИЕ. Наилучшая практика для имен классов - это использование первой буквы. RunMe вместо runMe.

@Singleton - без параметров вы автоматически укажете свой компонент для поиска, используя соглашение о компоненте от имени вашего класса. Представьте, если вы реализуете несколько интерфейсов, как EJB выбирает имя? Поэтому логично использовать имя класса. Например. Если ваше имя класса - TestMe, имя ejb будет testMe.

В вашем случае, так как ваше имя класса runMe, я бы подумал, что имя bean будет запущено.

Чтобы гарантировать, что поиск не подведет, вы можете указать имя в @Singleton и @EJB.

@Singleton(name = "runMe") 
@Startup 
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER) 
public class runMe implements RaffleManager{ 

Затем в точке класса конец Услуги

@ServerEndpoint("/rafflethis") 
public class RaffleThis implements Serializable { 
    @EJB(beanName ="runMe") 
    RaffleManager roll; 
+0

Да, я знаю класс runMe, я просто слишком ленив, чтобы переименовать его. Спасибо за ответ.В будущем я увижу, что проблема может быть решена с помощью этого метода. Я нашел решение, на которое я отвечу ниже. Спасибо за вашу помощь и ответ! –