Событие ошибки Граница изменяемой электронной почты не отслеживается

Я хотел бы BpmnError быть брошенным, когда электронная почта не может быть отправлена ​​по какой-либо причине, поэтому я могу обработать ее в потоке процесса.

Я заметил, что org.flowable.engine.impl.bpmn.behavior.MailActivityBehavior бросает FlowableException который не может быть пойман граничным событием, поэтому я сделал следующий класс:

@Slf4j
public class MailBpmnThrowingBehaviour extends MailActivityBehavior {

  @Override
  protected void handleException(final DelegateExecution execution, final String msg, final Exception e, final boolean doIgnoreException, final String exceptionVariable) {
    if (doIgnoreException) {
      log.info("Ignoring email send error: {}", msg, e);
      if (exceptionVariable != null && exceptionVariable.length() > 0) {
        execution.setVariable(exceptionVariable, msg);
      }
    } else {
      if (e instanceof EmailException) {
        throw new BpmnError("mailFailed", e.getMessage());
      }

      if (e instanceof FlowableException) {
        throw (FlowableException) e;
      } else {
        throw new FlowableException(msg, e);
      }
    }
  }
}

Единственная разница между моей реализацией и версией по умолчанию состоит в том, что я перебрасываю EmailException как BpmnError вместо FlowableException,

Вот мой простой процесс для тестирования:

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns:flowable="http://flowable.org/bpmn" xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" targetNamespace="http://www.flowable.org/processdef">
  <process id="MailErrorTest" name="MailErrorTest" isExecutable="true">
    <startEvent id="start" name="start"/>

    <sequenceFlow sourceRef="start" targetRef="pauseTask"/>

    <userTask id="pauseTask" name="pauseTask"/>

    <sequenceFlow sourceRef="pauseTask" targetRef="emailTask"/>

    <serviceTask id="emailTask" name="emailTask" flowable:type="mail">
      <extensionElements>
        <flowable:field name="to">
          <flowable:string><![CDATA[receiver@localhost]]></flowable:string>
        </flowable:field>
        <flowable:field name="from">
          <flowable:string><![CDATA[sender@localhost]]></flowable:string>
        </flowable:field>
        <flowable:field name="subject">
          <flowable:string><![CDATA[BPMN MailErrorTest]]></flowable:string>
        </flowable:field>
        <flowable:field name="text">
          <flowable:string><![CDATA[Test...]]></flowable:string>
        </flowable:field>
      </extensionElements>
    </serviceTask>

    <sequenceFlow sourceRef="emailTask" targetRef="successEnd"/>

    <endEvent id="successEnd" name="successEnd"/>

    <boundaryEvent id="mailError" name="mailError" attachedToRef="emailTask">
      <errorEventDefinition/>
    </boundaryEvent>

    <sequenceFlow sourceRef="mailError" targetRef="failEnd"/>

    <endEvent id="failEnd" name="failEnd"/>
  </process>
</definitions>

Визуализация:

процесс

pauseTask служит точкой, где я могу убить почтовый сервер и возобновить процесс, чтобы он не сработал.

Вот упомянутый тест Spring Boot:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {
    ExampleApplication.class,
    MailErrorTestConfiguration.class
})
public class MailErrorTest {

  @Autowired
  @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
  private ProcessEngine processEngine;

  // this is a fake SMTP server
  private Wiser wiser;

  @Before
  public void setUp() {
    wiser = new Wiser();
    wiser.start();
  }

  @After
  public void tearDown() {
    wiser.stop();
  }

  @Test
  public void shouldSendEmailSuccessfully() {
    assertThat(processEngine.getTaskService().createTaskQuery().list()).isEmpty();

    final ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceByKey("MailErrorTest");
    final Task pauseTask = processEngine.getTaskService().createTaskQuery().singleResult();

    processEngine.getTaskService().complete(pauseTask.getId());

    final HistoricProcessInstance historicProcessInstance = processEngine.getHistoryService().createHistoricProcessInstanceQuery()
        .processInstanceId(processInstance.getProcessInstanceId())
        .singleResult();

    assertReceivedMessage(wiser)
        .from("sender@localhost")
        .to("receiver@localhost")
        .withSubject("BPMN MailErrorTest")
        .withContent("Test...");

    assertThat(historicProcessInstance.getEndActivityId()).isEqualTo("successEnd");
  }

  @Test
  public void shouldCatchEmailBoundaryErrorEvent() {
    assertThat(processEngine.getTaskService().createTaskQuery().list()).isEmpty();

    final ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceByKey("MailErrorTest");
    final Task pauseTask = processEngine.getTaskService().createTaskQuery().singleResult();

    // killing SMTP server to cause sending error
    wiser.stop();

    processEngine.getTaskService().complete(pauseTask.getId());

    final HistoricProcessInstance historicProcessInstance = processEngine.getHistoryService().createHistoricProcessInstanceQuery()
        .processInstanceId(processInstance.getProcessInstanceId())
        .singleResult();

    assertThat(historicProcessInstance.getEndActivityId()).isEqualTo("failEnd");
  }

  @Configuration
  public static class MailErrorTestConfiguration implements EngineConfigurationConfigurer<SpringProcessEngineConfiguration> {
    @Override
    public void configure(final SpringProcessEngineConfiguration engineConfiguration) {
      engineConfiguration.setActivityBehaviorFactory(new CustomActivityBehaviorFactory());
    }
  }
}

CustomActivityBehaviorFactory также почти как по умолчанию, с той лишь разницей, что я возвращаю MailActivityBehaviour вместо значения по умолчанию:

public class CustomActivityBehaviorFactory extends DefaultActivityBehaviorFactory {

  @Override
  protected MailActivityBehavior createMailActivityBehavior(final String taskId, final List<FieldExtension> fields) {
    final List<FieldDeclaration> fieldDeclarations = createFieldDeclarations(fields);
    return (MailBpmnThrowingBehaviour) ClassDelegate.defaultInstantiateDelegate(MailBpmnThrowingBehaviour.class, fieldDeclarations);
  }
}

Первый тест работает, как и ожидалось, когда почтовый сервер работает, процесс завершается, как и ожидалось. Тем не менее, второй тест не работает, как я ожидал, BpmnError граничное событие не перехватывается, исключение выдается до конца и тест не пройден.

Может кто-нибудь помочь мне понять, что я делаю не так? Почему граничное событие не ловит BpmnError? Есть ли более чистое решение для перехвата исключений MailTask?

0 ответов

Другие вопросы по тегам