Uploaded image for project: 'JBoss Enterprise Application Platform'
  1. JBoss Enterprise Application Platform
  2. JBEAP-18365

[GSS](7.1.z) Improper handling of application exceptions on asynchronous ejb invocations

    XMLWordPrintable

Details

    • Bug
    • Resolution: Won't Do
    • Major
    • None
    • 7.1.6.GA
    • EJB
    • Compatibility/Configuration
    • Low
    • 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.

    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
              rhn-support-bmaxwell Brad Maxwell
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: