简体   繁体   中英

Apache Tomcat Simple Comet Servlet

I'm trying create very simple Comet Servlet which will push Hello World message to subscribers:

@WebServlet("/ChatServlet")
public class ChatServlet extends HttpServlet implements CometProcessor {
    private static final long serialVersionUID = 1L;

    private MessageSender messageSender = null;
    private static final Integer TIMEOUT = 60 * 1000;    

    public void init(ServletConfig config) throws ServletException {
          messageSender = new MessageSender();
            Thread messageSenderThread =
                    new Thread(messageSender);
            messageSenderThread.setDaemon(true);
            messageSenderThread.start();
        }

    public void destroy() {
     //   messageSender.stop();
        messageSender = null;
        }

    @Override
    public void event(CometEvent event) throws IOException, ServletException {
        HttpServletRequest request = event.getHttpServletRequest();
        HttpServletResponse response = event.getHttpServletResponse();
        if (event.getEventType() == CometEvent.EventType.BEGIN) {
            request.setAttribute("org.apache.tomcat.comet.timeout", TIMEOUT);
            System.out.println("Begin for session: " + request.getSession(true).getId());
            messageSender.setConnection(response);
        }
        else if (event.getEventType() == CometEvent.EventType.ERROR) {
            System.out.println("Error for session: " + request.getSession(true).getId());
            event.close();
        } else if (event.getEventType() == CometEvent.EventType.END) {
            System.out.println("End for session: " + request.getSession(true).getId());
            event.close();
        } else if (event.getEventType() == CometEvent.EventType.READ) {
            throw new UnsupportedOperationException("This servlet does not accept data");
    }
    }
}

and then my Runnable looks like this:

public class MessageSender implements Runnable {

       protected boolean running = true;
        protected final List<String> messages = new ArrayList<String>();
        private ServletResponse connection;

        public synchronized void setConnection(ServletResponse connection){
            this.connection = connection;
            notify();
        }

    @Override
    public void run() {
         while (running) {
             if (messages.size() == 0) {
                    try {
                        synchronized (messages) {
                            messages.wait();
                        }
                    } catch (InterruptedException e) {
                        // Ignore
                    } 
         }
         String[] pendingMessages = null;
          synchronized (messages) {
              pendingMessages = messages.toArray(new String[0]);
              messages.clear();
          }
          try {
              if (connection == null){
                  try{
                      synchronized(this){
                          wait();
                      }
                  } catch (InterruptedException e){
                      // Ignore
                  }
              }
              PrintWriter writer = connection.getWriter();

                  writer.println("hello World");
                  System.out.println("Writing Hello World");                  
              writer.flush();
              writer.close();
              connection = null;
              System.out.println("Closing connection");
          } catch (IOException e) {
              System.out.println("IOExeption sending message"+e.getMessage());
          }
         }
    }
}

now my Dojo cometd code looks like this:

  <script src="dojo/dojo.js"></script>    
    <script type="text/javascript">
    dojo.require("dojox.cometd");

    dojo.addOnLoad(function(){
        dojox.cometd.init("ChatServlet");
        dojox.cometd.subscribe("ChatServlet", window, "alertMessage");
    });

    function alertMessage(message) {
        alert("Message: " + message);
    }

    </script>

Now when I load client I'm getting the following error:

Begin for session: C898A372F1B1199C04CA308F715ABC36Nov 6, 2011 2:00:48 PM org.apache.catalina.core.StandardWrapperValve event
SEVERE: Servlet.service() for servlet [com.vanilla.servlet.ChatServlet] in context with path [/Servlet3Comet] threw exception
java.lang.UnsupportedOperationException: This servlet does not accept data
    at com.vanilla.servlet.ChatServlet.event(ChatServlet.java:75)

Error for session: C898A372F1B1199C04CA308F715ABC36
End for session: C898A372F1B1199C04CA308F715ABC36

What am I doing wrong? Why does cometD subscription invokes CometEvent.EventType.READ ? Does anybody have any working comet example?

PS: I did switch to Nio according to Tomcat configuration.

Documentation for init(ServletConfig) :

public void init(ServletConfig config) throws ServletException Called by the servlet container to indicate to a servlet that the servlet is being placed into service.

See Servlet#init. This implementation stores the ServletConfig object it receives from the servlet container for later use. When overriding this form of the method, call super.init(config).

And Documentation for init():

public void init() throws ServletException A convenience method which can be overridden so that there's no need to call super.init(config).

Instead of overriding init(ServletConfig), simply override this method and it will be called by GenericServlet.init(ServletConfig config). The ServletConfig object can still be retrieved via getServletConfig().

When overriding init(ServletConfig), your first call must be super.init(config);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM