Page 1 of 1

About Question enthuware.jwpv6.2.595 :

Posted: Mon Aug 24, 2015 12:17 pm
by kannattaa
Option "In case of an Exception thrown by the Runnable passed to asyncContext.start(runnable)" seems to be incorrect.

F.E. this code doesn't invoke AsyncListener.onError(AsyncEvent), though it must have been invoked according to the answer:

Code: Select all

        ac.start(new Runnable() {
             public void run() {
                 throw new RuntimeException();
             }
        });

The spec says:
Any errors or exceptions that may occur during the execution of the dispatch
methods
MUST be caught and handled by the container as follows:
i. invoke the AsyncListener.onError(AsyncEvent)
...
Thus AsyncListener.onError(AsyncEvent) will be invoked only if dispatch() method has been called and an exception occurs during its processing. It seems to be logically since error handling works only in container managed thread.

Re: About Question enthuware.jwpv6.2.595 :

Posted: Mon Aug 24, 2015 8:21 pm
by admin
Exceptions during the dispatch method is one of the cases when onError is invoked. If you look at Page 2-14 of Servlet 3.1 specification, it says :
public void addListener(AsyncListener listener, ServletRequest req, ServletResponse res) - Registers the given listener for notifications of onTimeout, onError, onComplete or onStartAsync. The first three are associated with the most recent asynchronous cycle started by calling one of the ServletRequest.startAsync methods.
The description on onError also says, "Is used to notify the listener that the asynchronous operation has failed to complete.". This implies that if there is an exception in the async operation, onError will be invoked.

So I think it should be invoked. I am not sure why it is not being invoked in your example. It could also be because the implementation does not implement the specification correctly.

HTH,
Paul.

Re: About Question enthuware.jwpv6.2.595 :

Posted: Tue Aug 25, 2015 6:55 am
by kannattaa
I think it is impossible to container to control threads created by users (f.e. with new Thread() call).

In order to implement exception handling container managed threads must have something like try-catch block in their run() (it is required at least for invoking service method, which throws checked IOException and ServletException).

With AsyncContext.start(Runnable) method container has an opportunity to wrap received Runnable with similar try-catch. So it is expectable to have onError() invoked in that case. But specification doesn't differ cases when thread is created with AsyncContext.start() and new Thread(), so exception handling (onError() invoking) can't be requirement for container implementation.

However, when dispatch() method is called, container managed thread processes the request, which has built-in exception handling mechanism. So the spec has explicit requirements described in my first post.

Re: About Question enthuware.jwpv6.2.595 :

Posted: Wed Oct 21, 2015 9:48 pm
by admin
User is not creating a new Thread using new Thread() call. User is only supplying a Runnable.

Re: About Question enthuware.jwpv6.2.595 :

Posted: Sat May 28, 2016 6:56 pm
by himaiMinh

Code: Select all

@WebServlet (value="/MyServlet", asyncSupported=true)
public class MyServlet extends HttpServlet {
   @Override
   public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
         request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true);
         final AsyncContext  ac = request.startAsync();
         ac.addListener(new MyAsyncListener());
         ac.start(new Runnable(){
             @Override
             public void run(){
                  
                 // ac.dispatch("/MyServlet1");   // the onError method of the AsyncListener is called
                  throw new RuntimeException();   // the timeout method of the AsyncListener is called.
             }
         });
       
   }   
}

Code: Select all

@WebServlet(name = "MyServlet1", urlPatterns = {"/MyServlet1"})
public class MyServlet1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
           throw new RuntimeException();
    }
}

Code: Select all

@WebListener 
public class MyAsyncListener implements AsyncListener {
     ...
    @Override
    public void onTimeout(AsyncEvent event) throws IOException {
       System.out.println("time out.");
    }

    @Override
    public void onError(AsyncEvent event) throws IOException {
       System.out.println("Error");   
    }
   ...
    
}
What I observed is:
1. when the exception is thrown from the runnable, timeout method of the AsyncListener is called.
2. but when the async servlet dispatches the request to another servlet and the exception is thrown from the second servlet, the onError method is called.

Re: About Question enthuware.jwpv6.2.595 :

Posted: Sun Jun 26, 2016 11:01 am
by himaiMinh
For the last option, if the asynContext.start(runnable) enters an infinite loop , it will call the AsyncListener. onTimeout.
But if the asynContext.setTimeOut(0), it will never time out. So, the onTimeout will never be called.