在@serverEndpoint class 中注入 EJB 导致 NullPointerException
Inject EJB in @serverEndpoint class results in NullPointerException
我正在使用 Swarm Wildfly 部署此应用程序。
基本上我正在制作一个支持 websocket 的应用程序。
我想注入一个单例,它将在修改变量结果的启动时启动。
访问“/rafflethis”后 link,用户将能够看到将通过会话发送的结果。
结果是roll
变量null
这是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;
}
}
界面
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());
}
}
}
我应该从哪里开始?谢谢!
查看源代码,我可能会认为是名称问题。
您的单例 bean "runMe" 是 bean 的实际名称而不是接口。
旁注:class 名称的最佳做法是将第一个字母大写。 RunMe 而不是 runMe。
@Singleton - 没有参数将自动命名您的 bean 以使用您的 class 名称中的 bean 约定进行查找。想象一下,如果你实现了多个接口,EJB 是如何取名的?所以使用 class 名称是合乎逻辑的。例如。如果您的 classname 是 TestMe,则 ejb 名称将是 testMe。
在你的情况下,因为你的 class 名称是 runMe,我认为 bean 名称将是 runMe。
为了保证查找不会失败,可以在@Singleton和@EJB中指定名称。
@Singleton(name = "runMe")
@Startup
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class runMe implements RaffleManager{
然后在你的服务端点class
@ServerEndpoint("/rafflethis")
public class RaffleThis implements Serializable {
@EJB(beanName ="runMe")
RaffleManager roll;
该解决方案相当棘手,但确实非常简单。看看提供的图表。
这是代码
逻辑实现:
@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());
}
}
}
我正在使用 Swarm Wildfly 部署此应用程序。 基本上我正在制作一个支持 websocket 的应用程序。
我想注入一个单例,它将在修改变量结果的启动时启动。
访问“/rafflethis”后 link,用户将能够看到将通过会话发送的结果。
结果是roll
变量null
这是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;
}
}
界面
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());
}
}
}
我应该从哪里开始?谢谢!
查看源代码,我可能会认为是名称问题。 您的单例 bean "runMe" 是 bean 的实际名称而不是接口。
旁注:class 名称的最佳做法是将第一个字母大写。 RunMe 而不是 runMe。
@Singleton - 没有参数将自动命名您的 bean 以使用您的 class 名称中的 bean 约定进行查找。想象一下,如果你实现了多个接口,EJB 是如何取名的?所以使用 class 名称是合乎逻辑的。例如。如果您的 classname 是 TestMe,则 ejb 名称将是 testMe。
在你的情况下,因为你的 class 名称是 runMe,我认为 bean 名称将是 runMe。
为了保证查找不会失败,可以在@Singleton和@EJB中指定名称。
@Singleton(name = "runMe")
@Startup
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class runMe implements RaffleManager{
然后在你的服务端点class
@ServerEndpoint("/rafflethis")
public class RaffleThis implements Serializable {
@EJB(beanName ="runMe")
RaffleManager roll;
该解决方案相当棘手,但确实非常简单。看看提供的图表。
这是代码
逻辑实现:
@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());
}
}
}