Uploaded image for project: 'WildFly'
  1. WildFly
  2. WFLY-9624

Improper handling of application exceptions on asynchronous ejb invocations

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • Major
    • 12.0.0.Beta1, 12.0.0.Final
    • 11.0.0.Final
    • EJB
    • None
    • Hide

      Create the following ejb:

      @Singleton
      public class AsyncBean {
      
      	@Asynchronous
      	public Future<Void> doSomeStuff() throws MyException {
      		throw new MyException();
      	}
      }
      

      Call ths bean and poll the result via isDone(). It will never return true.

      On wildfly 10, it would immidiatly return true.

      Show
      Create the following ejb: @Singleton public class AsyncBean { @Asynchronous public Future<Void> doSomeStuff() throws MyException { throw new MyException(); } } Call ths bean and poll the result via isDone(). It will never return true. On wildfly 10, it would immidiatly return true.
    • Compatibility/Configuration
    • Low

    Description

      If an asynchronous invocation of an ejb method throws an application exception (declared exception) then the returned future will always return false on isDone(). That means: the client will never know that the operation has finished (unscuccessfully) unless get() is called which would rethrow the original exception.

      This behavior has changed from wildfly 10.1.0.Final to 11.0.0.Final.

      I pretty sure that the problem is in org.jboss.as.ejb3.component.interceptors.AsyncInvocationTask.

      The isDone Method is implemented like this:

          @Override
          public boolean isDone() {
              return status == ST_DONE;
          }
      

      But status can be one of:

          private static final int ST_RUNNING = 0;
          private static final int ST_DONE = 1;
          private static final int ST_CANCELLED = 2;
          private static final int ST_FAILED = 3;
      

      And and exception sets the status to

          private synchronized void setFailed(final Exception e) {
              this.failed = e;
              status = ST_FAILED;
              done();
          }
      

      So it's pretty obvious.

      The javadoc on java.util.concurrent.Future states:

      Completion may be due to normal termination, an exception, or cancellation – in all of these cases, this method will return true.

      So the isDone() method should look more like this:

          @Override
          public boolean isDone() {
              return status == ST_DONE || status == ST_FAILED || status == ST_CANCELLED;
          }
      

      In wildfly 10, there was a single boolean variable "done" which was set to true in all three cases:

      • cancel()
      • setResult(...) and
      • setFailed(...)

      Attachments

        Issue Links

          Activity

            People

              Unassigned Unassigned
              andrejkolontai Andrej Kolontai (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: