Apache Tomcat Простой кометный сервлет - PullRequest
4 голосов
/ 06 ноября 2011

Я пытаюсь создать очень простой Comet Servlet, который будет выдавать подписчикам приветственное сообщение Hello World:

@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");
    }
    }
}

, и тогда мой Runnable будет выглядеть так:

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());
          }
         }
    }
}

теперь мой DojoКод cometd выглядит следующим образом:

  <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>

Теперь, когда я загружаю клиент, я получаю следующую ошибку:

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

Что я делаю не так?Почему подписка на cometD вызывает CometEvent.EventType.READ?У кого-нибудь есть пример работающей кометы?

PS: я переключился на Nio в соответствии с конфигурацией Tomcat.

1 Ответ

1 голос
/ 04 марта 2014

Документация для init(ServletConfig):

public void init(ServletConfig config) throws ServletException Вызывается контейнером сервлетов, чтобы указать сервлету, что сервлет ввод в эксплуатацию.

См. Сервлет # init. Эта реализация хранит объект ServletConfig он получает от контейнера сервлета для последующего использования. При переопределении эту форму метода, вызовите super.init (config).

И документация для init ():

public void init() throws ServletException Удобный метод, который может быть переопределено, так что нет необходимости вызывать super.init (config).

Вместо переопределения init (ServletConfig), просто переопределите этот метод и он будет вызываться GenericServlet.init (конфигурация ServletConfig). Объект ServletConfig все еще можно получить через getServletConfig ().

При переопределении init (ServletConfig) ваш первый вызов должен быть super.init(config);

...