谁能告诉我为什么此代码无法打开简单的网络套接字?
(如果有兴趣,我正在尝试实现websocket和JMS的集成,如下所述:https://blogs.oracle.com/theaquarium/integrating-websockets-and-jms-with-cdi-events-in-java-ee-7-v2。但这不是问题的一部分)
我在本地的Wildfly 10服务器上部署了HTML页面,Endpoint和几个Java bean。这是耳朵的结构。
WebSocketsOne.ear
META-INF
application.xml
MANIFEST.MF
WebSocketsOne-server.jar
META-INF
persistence.xml
org
america3
websockets
endpoints
WebSocketsOneEndPt.java
javabeans
WebSocketsOneJMSMsg.java
WebSocketsOneMDB.java
WebSocketsOneSenderBean.java
WebSocketsOne-war.war
META-INF
MANIFEST.MF
WEB-INF
web.xml
index.html
“ / WebSocketsOne”是项目的上下文。
<module id="WebSocketsOneWar">
<web>
<web-uri>WebSocketsOne-war.war</web-uri>
<context-root>/WebSocketsOne</context-root>
</web>
</module>
它的部署仅带有一个与Java Bean相关的警告(我将在打开websocket后处理);
09:17:20,201 INFO Starting subdeployment (runtime-name: "WebSocketsOne-war.war")
09:17:24,977 WARN Deployment deployment "WebSocketsOne-ear.ear" contains CDI annotations but no bean archive was not found. (No beans.xml nor class with bean defining annotations)
09:17:27,430 INFO Deployed "WebSocketsOne-ear.ear" (runtime-name : "WebSocketsOne-ear.ear")
此URL将打开HTML页面: http://localhost:8080/WebSocketsOne/index.html
这是HTML页面通过以下链接调用的javascript代码: 公开会议
我构造了ear文件,以复制与java“ package”层次结构匹配的子目录。并在下面的URL中使用它。是吗?
function openUp() {
URL = "ws://localhost:8080/WebSocketsOne/org/america3/websockets/endpoints/WebSocketsOneEntPt";
alert("Opening: websocket " + URL);
if (!websocketSession) {
websocketSession = new WebSocket(URL);
websocketSession.onopen = function (event) {
alert ("I am open");
};
}
}
websocketSession.onopen永远不会被调用。
这是我的终结点课程
package org.america3.websockets.endpoints;
// imports
@Named
@ServerEndpoint("/WebSocketsOne/org/america3/websockets/endpoints")
public class WebSocketsOneEndPt implements Serializable {
private WebSocketsOneSenderBean senderBean;
private static final Set<Session> sessions = Collections.synchronizedSet(new HashSet<Session>());
/* sessions holds all WebSocket sessions connected to this
* WebSocket server endpoint (per JVM).
* Notice that on onOpen and onClose, we manage
* all user sessions connected to this endpoint.
* We will see later how sessions will be used
* inside onMessage.
*/
final Logger logger = Logger.getLogger("org.america3.websockets.endpoints");
private static final long serialVersionUID = 1L;
// Constructor
@Inject
public WebSocketsOneEndPt(WebSocketsOneSenderBean sb) {
this.senderBean = sb;
logger.info("Constructor");
}
/* Injecting the MsgSenderBean into the Websocket, allows
* it to call the MsgSenderBean's send message from within
* the websocket's onMessage() method below.
*/
@OnOpen
public void onOpen(final Session session) {
sessions.add(session);
logger.info("Endpoint opened session");
}
@OnMessage
public void onMessage(final String message, final Session client) {
senderBean.sendMessage(message);
/* this allows the endpoint to broadcast messages through
* MsgSenderBean's sendMessage() method.
*/
}
@OnClose
public void onClose(final Session session) {
sessions.remove(session);
}
public void onJMSMessage(@Observes @WebSocketsOneJMSMsg Message msg) {
try {
for (Session s : sessions) {
s.getBasicRemote().sendText("message from JMS: " + msg.getBody(String.class));
}
} catch (IOException | JMSException ex) {
Logger.getLogger(WebSocketsOneEndPt.class.getName()).log(Level.SEVERE, null, ex);
} }
}
如果有兴趣的话,以下是我在上面引用的文章中呼吁的Java bean的草稿。但不是我的第一个问题的一部分。打开网络套接字后,我将对其进行调试。
package org.america3.websockets.javabeans;
// imports
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
public @interface WebSocketsOneJMSMsg {
}
package org.america3.websockets.javabeans;
// imports
@Named
@MessageDriven(mappedName = "/jms/queue/sendToServerQueue")
public class WebsocketsOneMDB implements MessageListener {
@Inject
@WebSocketsOneJMSMsg Event<Message> jmsEvent;
@Override
public void onMessage(Message msg) {
jmsEvent.fire(msg);
}
}
package org.america3.websockets.javabeans;
// imports
@Named
@LocalBean
@Stateless
public class WebSocketsOneSenderBean {
/* This SessionBean is @Stateless,
* as well as being part of the CDI context (@Named),
* and as it does not have an interface, it is a @LocalBean.
*/
/* Inject the JMSContext
* JMSContext is a new classes added to JMS API.
* It encapsulates a Connection and a Session, and makes
* use of a default ConnectionFactory, now a required resource to be
* provided by all Java EE 7 certified application servers.
*/
@Inject private JMSContext jmsContext;
/* Inject a Queue through which messages
* will be published.
*/
// @Resource(mappedName = "/jms/queue/sendToClientQueue")
// private Queue sendQueue;
@Resource(name="SendToClientQueue", mappedName = "java:/jms/queue/sendToClientQueue")
private Queue sendToClientQueue;
private static final Set<Session> sessions
= Collections.synchronizedSet(new HashSet<Session>());
/* Then add add a business method: sendMessage() */
public void sendMessage(String message) {
jmsContext.createProducer().send(sendToClientQueue, message);
/* And you are done with the SessionBean. */
}
}