Hi Joakim,

Thanks for your response, I changed the code as you suggested but it still
does not work. *But it works in Tomcat.*

This is the error I got.
[qtp990355670-43] WARN org.eclipse.jetty.util.thread.QueuedThreadPool -
java.lang.IllegalStateException
at
org.eclipse.jetty.server.HttpOutput$AsyncICB.onCompleteSuccess(HttpOutput.java:990)
at
org.eclipse.jetty.server.HttpOutput$AsyncWrite.onCompleteSuccess(HttpOutput.java:1126)
at
org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:325)
at
org.eclipse.jetty.util.IteratingCallback.succeeded(IteratingCallback.java:365)
at
org.eclipse.jetty.server.HttpConnection$SendCallback.onCompleteSuccess(HttpConnection.java:747)
at
org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:325)
at
org.eclipse.jetty.util.IteratingCallback.succeeded(IteratingCallback.java:365)
at
org.eclipse.jetty.io.WriteFlusher$PendingState.complete(WriteFlusher.java:269)
at org.eclipse.jetty.io.WriteFlusher.completeWrite(WriteFlusher.java:394)
at
org.eclipse.jetty.io.SelectChannelEndPoint$3.run(SelectChannelEndPoint.java:89)
at
org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceAndRun(ExecuteProduceConsume.java:213)
at
org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:147)
at
org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:654)
at
org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:572)
at java.lang.Thread.run(Thread.java:745)
[qtp990355670-43] WARN org.eclipse.jetty.util.thread.QueuedThreadPool -
Unexpected thread death:
org.eclipse.jetty.util.thread.QueuedThreadPool$3@2b35b7fd in
qtp990355670{STARTED,8<=21<=200,i=11,q=0}
[qtp990355670-32] WARN org.eclipse.jetty.server.HttpChannel -
//localhost:56447/async
java.nio.channels.WritePendingException
at
org.eclipse.jetty.server.HttpConnection$SendCallback.reset(HttpConnection.java:622)
at
org.eclipse.jetty.server.HttpConnection$SendCallback.access$300(HttpConnection.java:584)
at org.eclipse.jetty.server.HttpConnection.send(HttpConnection.java:510)
at org.eclipse.jetty.server.HttpChannel.sendResponse(HttpChannel.java:650)
at org.eclipse.jetty.server.HttpChannel.write(HttpChannel.java:699)
at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:177)
at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:163)
at org.eclipse.jetty.server.HttpOutput.close(HttpOutput.java:211)
at org.eclipse.jetty.server.Response.closeOutput(Response.java:987)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:412)
at org.eclipse.jetty.server.HttpChannel.run(HttpChannel.java:262)
at
org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:654)
at
org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:572)
at java.lang.Thread.run(Thread.java:745)

On Wed, Sep 9, 2015 at 11:07 AM, Joakim Erdfelt <[email protected]> wrote:

> I think AsyncListener.onError() is a terminal state/call.
> The AsyncContext is no longer valid once that is called.
> The response is committed/closed as well.
> Moving to the complete() state isn't even possible.
> (Note: I could be wrong in this assumption)
>
> Some other advice, don't rely on context.getRequest and
> context.getResponse to always be there and be available.
> The lifecycle of an AsyncContext, and WriteListener can be longer than the
> lifecycle of a Request/Response.
> Its very possible for the Request/Response to be recycled / cleaned up
> before the AsyncContext and WriteListener are done.
>
> Yank them out into variables and use them that way.
> For example, your call to context.getRequest.getServletContext.log is just
> asking for problems (especially in an onError)
>
>
>
> Joakim Erdfelt / [email protected]
>
> On Wed, Sep 9, 2015 at 10:54 AM, Xiaodong Wang <[email protected]>
> wrote:
>
>> I try to use the asynchronous servlet with Jetty 9, but I
>> get IllegalStateException from HttpOutput class. The same code works well
>> with Tomcat.
>>
>> This is my test code (in Scala).
>>
>> TestServers.scala
>> ------------------------------------------------------------------------------------------------------------------------
>> package playground.webserver
>>
>> import java.io.File
>> import javax.servlet.Servlet
>>
>> import org.apache.catalina.startup.Tomcat
>> import org.eclipse.jetty.server.Server
>> import org.eclipse.jetty.servlet.{ServletHolder, ServletContextHandler}
>> ;
>>
>> trait TestServer {
>>   val port: Int
>>   def start: Unit
>>   def stop: Unit
>>   def addServlet(servlet: Servlet, contextPath: String)
>> }
>>
>> class TomcatTestServer(val port: Int) extends TestServer {
>>   private val tomcat = new Tomcat()
>>   tomcat.setPort(port)
>>
>>   override def start: Unit = tomcat.start()
>>
>>   override def stop: Unit = tomcat.stop()
>>
>>   override def addServlet(servlet: Servlet, contextPath: String): Unit =
>> {
>>   val base = new File(System.getProperty("java.io.tmpdir"));
>>   val context = tomcat.addContext(contextPath, base.getAbsolutePath());
>>
>>   tomcat.addServlet(contextPath, contextPath, servlet)
>>   context.addServletMapping("/", contextPath)
>>   }
>> }
>>
>> class JettyTestServer(val port: Int) extends TestServer {
>>   private val jetty = new Server(port)
>>   private val context = new
>> ServletContextHandler(ServletContextHandler.SESSIONS)
>>   context.setContextPath("/")
>>   jetty.setHandler(context)
>>
>>   override def start: Unit = jetty.start()
>>
>>   override def stop: Unit = jetty.stop()
>>
>>   override def addServlet(servlet: Servlet, contextPath: String): Unit =
>> {
>>   context.addServlet(new ServletHolder(servlet), contextPath)
>>   }
>> }
>>
>>
>>
>> AsyncIoTest.scala------------------------------------------------------------------------------------------------------------------------------------
>> package playground.webserver
>>
>> import java.net.ServerSocket
>> import javax.servlet.http.{HttpServlet, HttpServletRequest,
>> HttpServletResponse}
>> import javax.servlet.{AsyncContext, WriteListener}
>>
>> import org.apache.http.client.methods.HttpGet
>> import org.apache.http.impl.client.HttpClients
>> import org.scalatest.{BeforeAndAfterAll, FunSpec, Matchers}
>>
>> import scala.concurrent.ExecutionContext.Implicits.global
>> import scala.concurrent.duration.Duration
>> import scala.concurrent.{Await, Future}
>>
>> abstract class AsyncIoTest extends FunSpec with Matchers with
>> BeforeAndAfterAll {
>>   private val data = new Array[Byte](1024 * 1024 * 128)
>>
>>   *class DataWriteListener(context: AsyncContext) extends WriteListener
>> {*
>> *    private[this] var pos = 0*
>>
>> *    override def onError(t: Throwable): Unit = {*
>> *      context.getRequest.getServletContext.log("Async Error", t)*
>> *      context.complete()*
>> *    }*
>>
>> *    override def onWritePossible(): Unit = {*
>> *      val out = context.getResponse.getOutputStream*
>> *      while (out.isReady && pos < data.length) {*
>> *        val toWrite = math.min(1024, data.length - pos)*
>> *        out.write(data, pos, toWrite)*
>> *        pos += toWrite*
>> *      }*
>>
>> *      if (pos >= data.length) {*
>> *        context.complete()*
>> *      }*
>> *    }*
>> *  }*
>>
>>   *class AsyncServlet extends HttpServlet {*
>> *    override def doGet(req: HttpServletRequest, resp:
>> HttpServletResponse): Unit = {*
>> *      req.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true);*
>>
>> *      resp.setStatus(200)*
>> *      resp.setContentLength(data.length)*
>>
>> *      val async = req.startAsync()*
>> *      val out = resp.getOutputStream*
>>
>> *      out.setWriteListener(new DataWriteListener(async))*
>> *    }*
>> *  }*
>>
>>   class SyncServlet extends HttpServlet {
>>     override def doGet(req: HttpServletRequest, resp:
>> HttpServletResponse): Unit = {
>>       resp.setStatus(200)
>>       resp.setContentLength(data.length)
>>       val out = resp.getOutputStream
>>       var pos = 0
>>       while(pos < data.length) {
>>         out.write(data, pos, 1024)
>>         pos += 1024
>>       }
>>     }
>>   }
>>
>>   protected val server: TestServer
>>   protected lazy val port: Int = findAvailablePort()
>>   private val requestNum = 100
>>
>>   private def findAvailablePort(): Int = {
>>     val serverSocket = new ServerSocket(0)
>>     val port = serverSocket.getLocalPort()
>>     serverSocket.close()
>>
>>     port
>>   }
>>
>>   describe("Sync IO") {
>>     it("trigger some traffic") {
>>       testWithUrl(s"http://localhost:${port}/sync";)
>>     }
>>   }
>>
>>   describe("Async IO") {
>>     it("trigger some traffic") {
>>       testWithUrl(s"http://localhost:${port}/async";)
>>     }
>>   }
>>
>>   override protected def beforeAll(): Unit = {
>>     server.addServlet(new AsyncServlet, "/async")
>>     server.addServlet(new SyncServlet, "/sync")
>>     server.start
>>   }
>>
>>
>>   override protected def afterAll(): Unit = {
>>     server.stop
>>   }
>>
>>   private def testWithUrl(url: String): Unit = {
>>     val start = System.currentTimeMillis
>>
>>     val futures = (1 to requestNum).map { i =>
>>       Future {
>>         val total = readData(url)
>>         total should be(1024 * 1024 * 128)
>>         total
>>       }
>>     }
>>
>>     Await.result(Future.sequence(futures), Duration.Inf)
>>
>>     println(s"Total millis used: ${System.currentTimeMillis - start}")
>>   }
>>
>>   private def readData(url: String): Long = {
>>     val httpclient = HttpClients.createDefault()
>>     val httpGet = new HttpGet(url)
>>     val resp = httpclient.execute(httpGet)
>>     val is = resp.getEntity.getContent
>>     val buf = new Array[Byte](1024 * 1024)
>>     var read = 0
>>     var total = 0L
>>     while(read != -1) {
>>       total += read
>>       read = is.read(buf)
>>     }
>>
>>     resp.close()
>>     total
>>   }
>> }
>>
>> class AsyncIoWithJettyTest extends AsyncIoTest {
>>   override protected val server: TestServer = new JettyTestServer(port)
>> }
>>
>> class AsyncIoWithTomcatTest extends AsyncIoTest {
>>   override protected val server: TestServer = new TomcatTestServer(port)
>> }
>>
>>
>> This is the error I got.
>> [qtp990355670-39] WARN org.eclipse.jetty.util.thread.QueuedThreadPool -
>> [qtp990355670-32] WARN org.eclipse.jetty.server.HttpChannel -
>> //localhost:51809/async
>> java.lang.IllegalStateException
>> at
>> org.eclipse.jetty.server.HttpOutput$AsyncICB.onCompleteSuccess(HttpOutput.java:990)
>> at
>> org.eclipse.jetty.server.HttpOutput$AsyncWrite.onCompleteSuccess(HttpOutput.java:1126)
>> at
>> org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:325)
>> at
>> org.eclipse.jetty.util.IteratingCallback.succeeded(IteratingCallback.java:365)
>> at
>> org.eclipse.jetty.server.HttpConnection$SendCallback.onCompleteSuccess(HttpConnection.java:747)
>> at
>> org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:325)
>> at
>> org.eclipse.jetty.util.IteratingCallback.succeeded(IteratingCallback.java:365)
>> at
>> org.eclipse.jetty.io.WriteFlusher$PendingState.complete(WriteFlusher.java:269)
>> at org.eclipse.jetty.io.WriteFlusher.completeWrite(WriteFlusher.java:394)
>> at
>> org.eclipse.jetty.io.SelectChannelEndPoint$3.run(SelectChannelEndPoint.java:89)
>> at
>> org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceAndRun(ExecuteProduceConsume.java:213)
>> at
>> org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:147)
>> at
>> org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:654)
>> at
>> org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:572)
>> at java.lang.Thread.run(Thread.java:745)
>> [qtp990355670-39] WARN org.eclipse.jetty.util.thread.QueuedThreadPool -
>> Unexpected thread death:
>> org.eclipse.jetty.util.thread.QueuedThreadPool$3@26b0a9dd in
>> qtp990355670{STARTED,8<=20<=200,i=9,q=0}
>> java.lang.NullPointerException
>> at
>> playground.webserver.AsyncIoTest$DataWriteListener.onError(AsyncIoTest.scala:22)
>> at org.eclipse.jetty.server.HttpOutput.close(HttpOutput.java:201)
>> at org.eclipse.jetty.server.Response.closeOutput(Response.java:987)
>> at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:412)
>> at org.eclipse.jetty.server.HttpChannel.run(HttpChannel.java:262)
>> at
>> org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:654)
>> at
>> org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:572)
>> at java.lang.Thread.run(Thread.java:745)
>> ......
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> _______________________________________________
>> jetty-users mailing list
>> [email protected]
>> To change your delivery options, retrieve your password, or unsubscribe
>> from this list, visit
>> https://dev.eclipse.org/mailman/listinfo/jetty-users
>>
>
>
> _______________________________________________
> jetty-users mailing list
> [email protected]
> To change your delivery options, retrieve your password, or unsubscribe
> from this list, visit
> https://dev.eclipse.org/mailman/listinfo/jetty-users
>
_______________________________________________
jetty-users mailing list
[email protected]
To change your delivery options, retrieve your password, or unsubscribe from 
this list, visit
https://dev.eclipse.org/mailman/listinfo/jetty-users

Reply via email to