2017-02-22 3 views
0

Environnement:Appel startAsync() sur une demande de servlet lancers francs IllegalStateException dans une chaîne de filtre terminée par ProxyServlet de la jetée 9

  • Dans mon environnement, Kibana 4.5.2 fonctionne derrière un "servlet proxy inverse" qui est créé en étendant la classe "ProxyServlet" de Jetty.
  • Ceci est fait pour que l'interface Web de Kibana soit accessible en utilisant l'URL https://Jetty_Server_IP:8443/visual-analytics/proxy/ ... Les demandes pour cette URL sont interceptées par le proxy inverse fonctionnant dans le serveur Jetty et redirigé vers https://localhost:5601/ ... ie, vers le serveur Kibana qui s'exécute dans la même machine que le serveur Jetty.
  • Le serveur Kibana traite ensuite la demande transmise par le serveur Jetty et renvoie la réponse au navigateur Web.
  • REMARQUE: Jetty fonctionne en "mode intégré" dans mon application.

Problème:

Le "servlet proxy inverse" est mis en correspondance avec l'URL "/ visuel-analytique/proxy/*".

Il y a un autre « filtre » qui est mis en correspondance avec l'URL « /visual-analytics/proxy/elasticsearch/.kibana/search/* » dans lequel un ContinuationListener est utilisé comme indiqué par le code suivant:

ContinuationSupport.getContinuation(myRequestWrapper).addContinuationListener(new ContinuationListener() { 

         @Override 
         public void onTimeout(Continuation continuation) { 
          logger.log(Level.WARNING, "Request timeout..."); 
         } 

         @Override 
         public void onComplete(Continuation continuation) { 

          HttpServletResponse httpResponse = (HttpServletResponse)continuation.getServletResponse(); 
          if (httpResponse.getStatus() == HttpServletResponse.SC_OK || httpResponse.getStatus() == HttpServletResponse.SC_CREATED) { 
            //some business logic 
          } 

         } 
        }); 

    chain.doFilter(myRequestWrapper, response); 

le ContinuationListener ci-dessus fonctionnait très bien avec la version jetée 8.1.15.v20140411 et méthode onComplete() de l'auditeur est appelé. Mais après la mise à niveau de la version Jetty vers 9.3.14.v20161028, ContinuationListener ne fonctionne plus, c'est-à-dire que ni la méthode onComplete() de l'écouteur ni la méthode onTimeout() ne sont appelées.

Depuis le ContinuationListener ne fonctionne plus, je l'ai remplacé par une mise en œuvre « javax.servlet.AsyncListener » comme indiqué par le code suivant:

   AsyncContext asyncContext = myRequestWrapper.startAsync(); 
       asyncContext.addListener(new AsyncListener() { 

        @Override 
        public void onTimeout(AsyncEvent event) throws IOException 
        { 
           logger.log(Level.WARNING, "Async timeout..."); 
        } 

        @Override 
        public void onStartAsync(AsyncEvent event) throws IOException 
        { 
           logger.log(Level.INFO, "Async start..."); 
        } 

        @Override 
        public void onError(AsyncEvent event) throws IOException 
        { 
           logger.log(Level.SEVERE, "Async error..."); 
        } 

        @Override 
        public void onComplete(AsyncEvent event) throws IOException 
        { 
          HttpServletResponse httpResponse = (HttpServletResponse) event.getSuppliedResponse(); 
         //HttpServletResponse httpResponse = (HttpServletResponse) event.getAsyncContext().getResponse(); 
         if (httpResponse.getStatus() == HttpServletResponse.SC_OK || httpResponse.getStatus() == HttpServletResponse.SC_CREATED) { 
            //some business logic 
         } 
        } 
     }, myRequestWrapper, httpServletResponse); 

     chain.doFilter(myRequestWrapper, response); 

Mais en ajoutant la mise en œuvre « AsyncListener » ci-dessus a donné lieu à le "IllegalStateException" suivante:

https://164.99.175.139:8443/visual-analytics/proxy/elasticsearch/.kibana/search/test1?op_type=create 
    java.lang.IllegalStateException: s=DISPATCHED i=true a=STARTED 
      at org.eclipse.jetty.server.HttpChannelState.startAsync(HttpChannelState.java:264) 
      at org.eclipse.jetty.server.Request.startAsync(Request.java:2235) 
      at javax.servlet.ServletRequestWrapper.startAsync(ServletRequestWrapper.java:432) 
      at javax.servlet.ServletRequestWrapper.startAsync(ServletRequestWrapper.java:432) 
      at javax.servlet.ServletRequestWrapper.startAsync(ServletRequestWrapper.java:432) 
      at org.eclipse.jetty.proxy.ProxyServlet.service(ProxyServlet.java:88) 
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) 
      at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:845) 
      at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1712) 
      at com.netiq.sentinel.kibana.search.KibanaSearchFilter.doFilter(KibanaSearchFilter.java:249) 
      at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1699) 
      at com.netiq.sentinel.kibana.proxy.AcceptEncodingHeaderModificationFilter.doFilter(AcceptEncodingHeaderModificationFilter.java:37) 
      at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1699) 
      at com.netiq.sentinel.kibana.proxy.SecurityFilter.doFilter(SecurityFilter.java:41) 
      at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1699) 
      at com.netiq.sentinel.kibana.proxy.AuditFilter.doFilter(AuditFilter.java:104) 
      at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1699) 
      at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:582) 
      at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) 
      at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548) 
      at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226) 
      at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180) 
      at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:512) 
      at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) 
      at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112) 
      at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) 
      at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:213) 
      at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:119) 
      at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134) 
      at org.eclipse.jetty.server.Server.handle(Server.java:534) 
      at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:320) 
      at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251) 
      at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273) 
      at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95) 
      at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:202) 
      at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273) 
      at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95) 
      at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93) 
      at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303) 
      at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148) 
      at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136) 
      at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671) 
      at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589) 
      at java.lang.Thread.run(Thread.java:745) 

numéro de ligne 88 dans "ProxyServlet.java" qui est mentionné dans ce qui précède st trace ack a le code suivant:

final AsyncContext asyncContext = request.startAsync(); 

est « IllegalStateException » étant jeté parce que la méthode startAsync() est appelée deux fois sur la même demande - pour la première fois dans mon filtre et pour la deuxième fois à la jetée La méthode service() de ProxyServlet? Si oui, n'y a-t-il aucun moyen d'utiliser un "AsyncListener" dans une chaîne de filtres qui est terminée par ProxyServlet de Jetty?

Tout pointeur sur la façon d'aller plus loin serait grandement apprécié. Dans l'attente de toute réponse ...

Répondre

1

Pour votre information, je résolu ce problème comme suit:

  1. Au lieu d'utiliser « ContinuationListener », j'ai utilisé Servlet « de la AsyncListener », puisque « ContinuationListener » de la jetée de 3,0 de la jetée ne semble pas fonctionner après la mise à niveau Jetée 9.3.14.v20161028. Cela peut être un bug Jetty.
  2. Le segment de code associé à l'écouteur se trouvait AVANT l'appel "chain.doFilter()" du filtre. J'ai déplacé ce segment de code à une position après l'appel "chain.doFilter()" du filtre, de sorte que je puisse récupérer le AsyncContext qui est "déjà créé" dans la méthode service() de Jetty ProxyServlet. Je peux ensuite ajouter un AsyncListener à l'AsyncContext récupéré.
  3. J'ai changé l'appel "request.startAsync()" dans mon filtre en "request.getAsyncContext()" afin que je ne démarre pas un nouveau AsyncContext qui mène à l'exception IllegalStateException, mais seulement récupérer le AsyncContext qui est déjà créé dans ProxyServlet de Jetty.

Ainsi, le segment de code mis à jour ressemble à ceci:

  chain.doFilter(myRequestWrapper, response); 

      AsyncContext asyncContext = myRequestWrapper.getAsyncContext(); 
      asyncContext.addListener(new AsyncListener() { 

       @Override 
       public void onTimeout(AsyncEvent event) throws IOException 
       { 
          logger.log(Level.WARNING, "Async timeout..."); 
       } 

       @Override 
       public void onStartAsync(AsyncEvent event) throws IOException 
       { 
          logger.log(Level.INFO, "Async start..."); 
       } 

       @Override 
       public void onError(AsyncEvent event) throws IOException 
       { 
          logger.log(Level.SEVERE, "Async error..."); 
       } 

       @Override 
       public void onComplete(AsyncEvent event) throws IOException 
       { 
         HttpServletResponse httpResponse = (HttpServletResponse) event.getSuppliedResponse(); 
        //HttpServletResponse httpResponse = (HttpServletResponse) event.getAsyncContext().getResponse(); 
        if (httpResponse.getStatus() == HttpServletResponse.SC_OK || httpResponse.getStatus() == HttpServletResponse.SC_CREATED) { 
           //some business logic 
        } 
       } 
    }, myRequestWrapper, httpServletResponse);