Setting up reverse ajax(using jquery socket)/comet/Asynchronous servlet in Jboss AS 7.1.1
jbrazil5 Jul 18, 2012 10:03 AMI am new to developing Java Servlets and Java EE in general, I am attempting to get the example from jquery socket working here : https://github.com/flowersinthesand/jquery-socket The problem is that when I deploy it to the server I keep getting this warning and my servlet is not getting deployed :
09:57:16,560 WARN [org.jboss.as.ee] (MSC service thread 1-2) JBAS011006: Not installing optional component com.saviops.rst.service.ChatServlet$2 due to exception: org.jboss.as.server.deployment.DeploymentUnitProcessingException: JBAS011054: Could not find default constructor for class com.saviops.rst.service.ChatServlet$2
at org.jboss.as.ee.component.ComponentDescription$DefaultComponentConfigurator.configure(ComponentDescription.java:606)
at org.jboss.as.ee.component.deployers.EEModuleConfigurationProcessor.deploy(EEModuleConfigurationProcessor.java:81)
at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:113) [jboss-as-server-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811) [jboss-msc-1.0.2.GA.jar:1.0.2.GA]
at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746) [jboss-msc-1.0.2.GA.jar:1.0.2.GA]
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) [classes.jar:1.6.0_33]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) [classes.jar:1.6.0_33]
at java.lang.Thread.run(Thread.java:680) [classes.jar:1.6.0_33]
I am using Jboss AS 7.1.1 and using Jboss Developer Studio to do the development. Everything is running using the default configuration, so it is possible I do not have something setup correctly. Here is the code example I am trying to get working.
package com.saviops.rst.service;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
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 com.google.gson.Gson;
@WebServlet(urlPatterns = "/chat", asyncSupported = true)
public class ChatServlet extends HttpServlet {
private static final long serialVersionUID = -6741151503530066933L;
private Map connections = new ConcurrentHashMap();
private BlockingQueue queue = new LinkedBlockingQueue();
private Thread broadcaster = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Event event = queue.take();
for (Entry entry : connections.entrySet()) {
try {
send(entry.getValue(), event);
} catch (IOException ex) {
fire(new Event("close").socket(entry.getKey()));
}
}
} catch (InterruptedException e) {
break;
}
}
}
});
@Override
public void init() throws ServletException {
broadcaster.setDaemon(true);
broadcaster.start();
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
final String id = request.getParameter("id");
String transport = request.getParameter("transport");
AsyncContext asyncContext = request.startAsync();
response.setCharacterEncoding("utf-8");
response.setHeader("Access-Control-Allow-Origin", "*");
response.setContentType("text/" + ("sse".equals(transport) ? "event-stream" : "plain"));
asyncContext.addListener(new AsyncListener() {
public void onStartAsync(AsyncEvent event) throws IOException {
}
public void onComplete(AsyncEvent event) throws IOException {
cleanup(event);
}
public void onTimeout(AsyncEvent event) throws IOException {
cleanup(event);
}
public void onError(AsyncEvent event) throws IOException {
cleanup(event);
}
private void cleanup(AsyncEvent event) {
fire(new Event("close").socket(id));
}
});
PrintWriter writer = response.getWriter();
for (int i = 0; i < 2000; i++) {
writer.print(' ');
}
writer.print("\n");
writer.flush();
connections.put(id, asyncContext);
fire(new Event("open").socket(id));
}
private void send(AsyncContext asyncContext, Event event) throws IOException {
String data = new Gson().toJson(event);
PrintWriter writer = asyncContext.getResponse().getWriter();
for (String datum : data.split("\r\n|\r|\n")) {
writer.print("data: ");
writer.print(datum);
writer.print("\n");
}
writer.print("\n");
writer.flush();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setHeader("Access-Control-Allow-Origin", "*");
String data = request.getReader().readLine();
if (data != null) {
data = data.substring("data=".length());
fire(new Gson().fromJson(data, Event.class));
}
}
private void fire(Event event) {
if (event.type.equals("close")) {
connections.remove(event.socket);
}
handle(event);
}
private void handle(Event event) {
if (event.type.equals("message")) {
queue.offer(new Event("message").data(event.data));
}
}
private static class Event {
private String socket;
private String type;
private Object data;
@SuppressWarnings("unused")
public Event() {
}
public Event(String type) {
this.type = type;
}
public Event data(Object data) {
this.data = data;
return this;
}
public Event socket(String socket) {
this.socket = socket;
return this;
}
}
}
Just for reference I want to be able to have a constant connection from the client to the server so that the server can push status updates. I don't necessarily need this chat program working, I just wanted to get a working example of doing the server push. Also if there are any better ways to do this I am open to implementing this in a different manner.
Thanks for the help!