I have a @ServerEndpoint
that adds web socket sessions and I want it to @Observes
an event that will be fired by a servlet and then broadcast a message to all the web sockets.
I get a NullPointerException
in my servlet when I try to use the event that was defined with @Inject
. What am i doing wrong?
WebSocket Handler:
import javax.ejb.Asynchronous;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.Any;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@ServerEndpoint("/events")
public class WebSocketHandler
{
//This holds our sessions for async retrieval
private static final Set<Session> sessions = Collections.synchronizedSet( new HashSet<Session>() );
@OnOpen
public void open(Session session)
{
//Add to our collection
sessions.add( session );
}
@OnClose
public void close(Session session, CloseReason closeReason)
{
//Just remove it
sessions.remove( session );
}
...elided...
@Asynchronous
public void notify(@Observes @Any TestEvent event)
{
synchronized( sessions )
{
//Loop through and send to all listeners
for ( Session session : sessions )
{
//Make sure it's still open
if ( session.isOpen() )
{
try
{
session.getBasicRemote().sendText( event.getMessage() );
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
}
}
Event type:
import java.io.Serializable;
public class TestEvent implements Serializable
{
private String message;
public TestEvent()
{
}
public TestEvent(String message)
{
this.message = message;
}
public void setMessage(String message)
{
this.message = message;
}
public String getMessage()
{
return message;
}
@Override
public String toString()
{
return "TestEvent: " + message;
}
}
Servlet:
import javax.ejb.Asynchronous;
import javax.enterprise.event.Event;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/broadcast")
public class SendMessageServlet extends HttpServlet
{
@Inject
Event<TestEvent> testEvent;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
//Fire the event (THIS "testEvent" IS NULL)
testEvent.fire( new TestEvent( "{\"message\":\"An event occurred at " + System.currentTimeMillis() + "\",\"status\":200}" ) );
}
}
beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>groupId</groupId>
<artifactId>TestWebSocket</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<!-- Tell Maven what language version to use -->
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!-- Enables the annotations, etc needed -->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
</dependencies>
</project>