cancel
Showing results for 
Search instead for 
Did you mean: 

Throwing an exception from a signal() method

dstone_dalet_co
Champ in-the-making
Champ in-the-making
Hi,

We are currently extending TaskActivityBehavior to implement a ServiceTask that submits a long running job to our system and waits to be signaled when the job has completed.  During the submission (the execute() method) we can throw a regular or BpmnError exception which will cause the process to error or transition into an BPMN error path. 

I'm aware that this behavior isn't currently supported in the signal() method.  Throwing an exception from signal() doesn't cause the process to error or take an error transition path.  (see http://forums.activiti.org/content/bpmnerror-taskactivitibehabior-signal & JIRA issue http://jira.codehaus.org/browse/ACT-1999).

Is there any way we can work around this?  Is it seen as an issue?  Can we help to try and fix the issue? We need to throw an exception / error the process when a job failed message is received.  I realise that it should be possible to split the submit job and receive into discrete activities in a sub-process but we are reluctant to expose this complexity in our system.  Are we going about this the wrong way?
Best regards,
Daniel


9 REPLIES 9

trademak
Star Contributor
Star Contributor
Hi Daniel,

Yes the supported way would be to split up the submit job and receive into discrete activities. Then you can also add an error boundary event. If you create a unit test showing what you would like to do and create a JIRA we can look into it and see if there's a way to implement it like you are describing.

Best regards,

dstone_dalet_co
Champ in-the-making
Champ in-the-making
Hi Tijs,

Thanks for the response.  I can create a new test and issue but what I'm trying to do is exactly the same as the scenario described in this JIRA issue:
https://activiti.atlassian.net/browse/ACT-1999?jql=
Is it possible that this issue will be resolved in the future or is the functionality not supported?  If it is seen as an issue that will be fixed in future is there any way we can help to resolve it?
Best regards,
Dan

jbarrez
Star Contributor
Star Contributor
We look and try to fix jira issues on a regular basis, so it will be picked up eventually.
Speeding up that process can be done with submitting a pull request with a fix, as that is way quicker for us to manage.

pmesmeur
Champ in-the-making
Champ in-the-making
Hello,

I also have dealing with long running task () and I got the same problem than yours. I browsed the web and found this page but unfortunately I saw that there is not yet any reliable solution.

So I tried to find how exceptions are handled for "normal" service-task, in order to see if it is possible to reproduce this behavior from the signal method. Here is what I found…

With "normal" service-tasks, an important point occurs in ServiceTaskDelegateExpressionActivityBehavior.execute() with the "exception-propagation":
[java]
  public void execute(ActivityExecution execution) throws Exception {

    try {
      …
    } catch (Exception exc) {

      Throwable cause = exc;
      BpmnError error = null;
      while (cause != null) {
        if (cause instanceof BpmnError) {
          error = (BpmnError) cause;
          break;
        }
        cause = cause.getCause();
      }

      if (error != null) {
        ErrorPropagation.propagateError(error, execution);
      } else {
        throw exc;
      }

    }
  }
[/java]

However, for signal management, no such a behavior:
[java]
  public void signal(ActivityExecution execution, String signalName, Object signalData) throws Exception {
    Object delegate = expression.getValue(execution);
    if( delegate instanceof SignallableActivityBehavior){
      ClassDelegate.applyFieldDeclaration(fieldDeclarations, delegate);
      ((SignallableActivityBehavior) delegate).signal( execution , signalName , signalData);
    }
  }
[/java]

I my project, I tried to overload ServiceTaskDelegateExpressionActivityBehavior and in particular the signal method:
[java]
public class CustomServiceTaskDelegateExpressionActivityBehavior extends ServiceTaskDelegateExpressionActivityBehavior {

    @Override
    public void signal(ActivityExecution execution, String signalName, Object signalData) throws Exception {
        try {
            super.signal(execution, signalName, signalData);
        }

        /// code copy-pasted from ServiceTaskDelegateExpressionActivityBehavior.execute() ///
        catch (Exception exc) {

            Throwable cause = exc;
            BpmnError error = null;
            while (cause != null) {
                if (cause instanceof BpmnError) {
                    error = (BpmnError) cause;
                    break;
                }
                cause = cause.getCause();
            }

            if (error != null) {
                ErrorPropagation.propagateError(error, execution);
            } else {
                throw exc;
            }

        }
        /////////////////////////////////////////////////////////////////////////////////////
    }
}
[/java]

And it seems to work fine, at least for the cases I tested (please, cf the attached file)

@Activiti team: do you think that my solution is reliable? do you think that is covers all the cases related to exceptions? Is there any issue handling exceptions like this?

Thank you

jbarrez
Star Contributor
Star Contributor
@pmesmeur: that actually makes sense. I'm thinking it should be part of the engine code. Can you create a Pull Request with this change for the signal method. We can continue our discussion further there with the actual code.

pmesmeur
Champ in-the-making
Champ in-the-making
you can find my pull request here
Philippe

dstone_dalet_co
Champ in-the-making
Champ in-the-making
Many thanks for the suggested code.  This looks good but I just want to check something.  Am I correct in thinking this will handle BpmnError based exceptions but the signal() method will still behave as previously for other exception types?  This is different from the execute() method which will handle and fail the activity if any exception is thrown.  Is there anyway to do something like this for all exceptions in signal()?

jbarrez
Star Contributor
Star Contributor
> This is different from the execute() method which will handle and fail the activity if any exception is thrown

Afaik, this is the same for a signal, if an exception happens, the transaction will be rolled back, like in the regular use case.

dstone_dalet_co
Champ in-the-making
Champ in-the-making
This is slightly different from what we have experienced.  When a regular Java exception is thrown from the execute() method it causes the job to persist in the DB with an exception message but when an exception is thrown from the signal() method it unwinds to the code that called RuntimeService.signal() and no job exists in the DB.  I assume this happens as the job is considered complete once the execute() method completes.  Is that correct?