我正在使用EJB和WAR模块在glassfish中运行。 EJB模块包含一个管理与远程计算机的连接的单例,并且在特定事件的情况下,使用JMS发送消息。 WAR模块包含一个websocket服务器,它拦截JMS消息并将它们发送到连接的浏览器。它完美地运作。 现在我介绍一种“启动”方法:当一个新的客户端连接时,我想发送它的机器列表,所以javascript可以准备正确的div数。为此,我在单例bean中创建了一个返回列表的方法,我希望在新会话打开时调用它。
这是EJB模块中的单例:
@Singleton
public class TServer implements ServerListener, TServerLocal {
private HashMap<String, Servers> servers = new HashMap<>();
@EJB
private JMSQueueProducer jms;
@Override
public void connect(String hostname, String username, String password) {
Server server = new Server(hostname, username, password);
server.addListener(this);
}
private void onServerEvent(String host, String data) {
this.jms.textMessage(host + " " + data);
}
[...]
}
@Local
public interface TServerLocal {
public void connect(String hostname, String username, String password);
public void disconnect(String hostname);
public LinkedList<String> list();
}
JMSQueueProducer是一个无状态EJB,仅用于将消息发送到JMS队列:
@Stateless
@LocalBean
public class JMSAsteriskQueueProducer {
@Inject
private JMSContext jmsContext;
@Resource(mappedName = "jms/serverQueue")
private Queue sQueue;
public void textMessage(String message) {
jmsContext.createProducer().send(sQueue, message);
}
}
这是WAR模块中的websocket服务器:
@ApplicationScoped
@ServerEndpoint("/websocket")
public class WebSocketServer {
private static final Set<Session> sessions = Collections.synchronizedSet(new HashSet<Session>());
@EJB
private TServerLocal tServer;
@OnOpen
public void open(Session session) {
sessions.add(session);
LinkedList<String> servers = tServer.list();
}
[...]
}
如果我尝试启动会话,我会在tServer.list()处获得NullPointerException,这意味着tServer为null。 我尝试用@Inject更改@EJB,结果相同。我认为在CDI中调用EJB是完全合法的,我做错了什么?
答案 0 :(得分:0)
你的@Singleton需要@LocalBean注释,因为除了无界面视图之外它还暴露了其他界面:
@LocalBean
@Singleton
public class TServer implements ServerListener, TServerLocal {
...
}