Uploaded image for project: 'camunda BPM'
  1. camunda BPM
  2. CAM-13974

Preparing External Task Action Listeners

    XMLWordPrintable

Details

    • Feature Request
    • Resolution: Won't Do
    • L3 - Default
    • None
    • 7.16.0-alpha5
    • None
    • None

    Description

      User Story (Required on creation):

      Hello Team.
      I hope you are doing well.
      Following this post, preparing related actions (Listeners) will be important for the end-user client that need to work with Rest API (between External task and Engine). Actually, there are more than 10 Rest API that will call around the application and could be trigger related event that would be useful.

      Functional Requirements (Required before implementation):

      The main goal is to prepare module's listener for catching state of each. it should be corporate with an External Task and manage three state (on,done,fail).

      As we describe the point, it will be like a package for listeners and make the main interface.

      According to your contribution structure, the idea is under the Community Extensions category.

      Technical Requirements (Required before implementation):

      We have prepared a package for listeners and make the main interface ExternalTaskClientListener.java as below source :

      ExternalTaskClientListener.java

      import org.apache.http.HttpRequest;
      import org.apache.http.client.HttpResponseException;
      import org.camunda.bpm.engine.variable.VariableMap;
      import tv.samim.iptv.cmts.client.exception.ExternalTaskClientException;
      import tv.samim.iptv.cmts.client.impl.EngineClientException;
      import tv.samim.iptv.cmts.client.task.ExternalTask;
      import tv.samim.iptv.cmts.client.topic.impl.dto.TopicRequestDto;
      
      import java.io.IOException;
      import java.util.List;
      import java.util.Map;
      
      public interface ExternalTaskClientListener {
          public void exceptionWhileClosingResourceStream(Object response, IOException e);
          public void requestInterceptorException(Throwable e);
          public void exceptionWhileExecutingExternalTaskHandler(String topicName, Throwable e);
          public void exceptionWhileShuttingDown(InterruptedException e);
          public void exceptionOnExternalTaskServiceMethodInvocation(String topicName, ExternalTaskClientException e);
          public void exceptionWhileExecutingBackoffStrategyMethod(Throwable e);
          public void exceptionWhileAcquiringTasks(Throwable e);
          public void exceptionWhileReceivingResponse(HttpRequest httpRequest, HttpResponseException e);
          public void exceptionWhileEstablishingConnection(HttpRequest httpRequest, IOException e);
          public void exceptionWhileParsingJsonObject(Class<?> responseDtoClass, Throwable t);
          public void exceptionWhileMappingJsonObject(Class<?> responseDtoClass, Throwable t);
          public void exceptionWhileDeserializingJsonObject(Class<?> responseDtoClass, Throwable t);
          public void exceptionWhileSerializingJsonObject(Object dto, Throwable t);
          public void taskHandlerIsNull(String topicName);
      
          public void onFetchAndLock(List<TopicRequestDto> topics);
          public void fetchAndLockDone(List<TopicRequestDto> topics, List<ExternalTask> externalTasks);
          public void fetchAndLockFail(List<TopicRequestDto> topics, EngineClientException e);
      
          public void onUnlock(String taskId);
          public void unlockDone(String taskId);
          public void unlockFail(String taskId, EngineClientException e);
      
          public void onSetVariable(String processInstanceId, VariableMap variables);
          public void setVariableDone(String processInstanceId, VariableMap variables);
          public void setVariableFail(String processInstanceId, VariableMap variables, EngineClientException e);
      
          public void onComplete(String taskId, Map<String, Object> variables, Map<String, Object> localVariables);
          public void completeDone(String taskId, Map<String, Object> variables, Map<String, Object> localVariables);
          public void completeFail(String taskId, Map<String, Object> variables, Map<String, Object> localVariables, EngineClientException e);
      
          public void onFailure(String taskId, String errorMessage, String errorDetails, int retries, long retryTimeout);
          public void failureDone(String taskId, String errorMessage, String errorDetails, int retries, long retryTimeout);
          public void failureFail(String taskId, String errorMessage, String errorDetails, int retries, long retryTimeout, EngineClientException e);
      
          public void onBpmnError(String taskId, String errorCode, String errorMessage, Map<String, Object> variables);
          public void bpmnErrorDone(String taskId, String errorCode, String errorMessage, Map<String, Object> variables);
          public void bpmnErrorFail(String taskId, String errorCode, String errorMessage, Map<String, Object> variables, EngineClientException e);
      
          public void onExtendLock(String taskId, long newDuration);
          public void extendLockDone(String taskId, long newDuration);
          public void extendLockFail(String taskId, long newDuration, EngineClientException e);
      
          public void onSendMessage(String taskId, String message, VariableMap correlationKeys, VariableMap processVariables, Boolean all);
          public void sendMessageDone(String taskId, String message, VariableMap correlationKeys, VariableMap processVariables, Boolean all);
          public void sendMessageFail(String taskId, String message, VariableMap correlationKeys, VariableMap processVariables, Boolean all, EngineClientException e);
      
      
          public void unAuthorizedException(EngineClientException e);
      }
      

      Then we developed the main class (DefaultExternalTaskClientListener) that was implemented follow the interface.

      DefaultExternalTaskClientListener.java

      package tv.samim.iptv.cmts.client.listener;
      
      import org.apache.http.HttpRequest;
      import org.apache.http.client.HttpResponseException;
      import org.camunda.bpm.engine.variable.VariableMap;
      import tv.samim.iptv.cmts.client.exception.ExternalTaskClientException;
      import tv.samim.iptv.cmts.client.impl.EngineClientException;
      import tv.samim.iptv.cmts.client.task.ExternalTask;
      import tv.samim.iptv.cmts.client.topic.impl.dto.TopicRequestDto;
      
      import java.io.IOException;
      import java.util.List;
      import java.util.Map;
      
      public class DefaultExternalTaskClientListener implements ExternalTaskClientListener {
          @Override
          public void exceptionWhileClosingResourceStream(Object response, IOException e) {
      
          }
      
          @Override
          public void requestInterceptorException(Throwable e) {
      
          }
      
          @Override
          public void exceptionWhileExecutingExternalTaskHandler(String topicName, Throwable e) {
      
          }
      
          @Override
          public void exceptionWhileShuttingDown(InterruptedException e) {
      
          }
      
          @Override
          public void exceptionOnExternalTaskServiceMethodInvocation(String topicName, ExternalTaskClientException e) {
      
          }
      
          @Override
          public void exceptionWhileExecutingBackoffStrategyMethod(Throwable e) {
      
          }
      
          @Override
          public void exceptionWhileAcquiringTasks(Throwable e) {
      
          }
      
          @Override
          public void exceptionWhileReceivingResponse(HttpRequest httpRequest, HttpResponseException e) {
      
          }
      
          @Override
          public void exceptionWhileEstablishingConnection(HttpRequest httpRequest, IOException e) {
      
          }
      
          @Override
          public void exceptionWhileParsingJsonObject(Class<?> responseDtoClass, Throwable t) {
      
          }
      
          @Override
          public void exceptionWhileMappingJsonObject(Class<?> responseDtoClass, Throwable t) {
      
          }
      
          @Override
          public void exceptionWhileDeserializingJsonObject(Class<?> responseDtoClass, Throwable t) {
      
          }
      
          @Override
          public void exceptionWhileSerializingJsonObject(Object dto, Throwable t) {
      
          }
      
          @Override
          public void taskHandlerIsNull(String topicName) {
      
          }
      
          @Override
          public void onFetchAndLock(List<TopicRequestDto> topics) {
      
          }
      
          @Override
          public void fetchAndLockDone(List<TopicRequestDto> topics, List<ExternalTask> externalTasks) {
      
          }
      
          @Override
          public void fetchAndLockFail(List<TopicRequestDto> topics, EngineClientException e) {
      
          }
      
          @Override
          public void onUnlock(String taskId) {
      
          }
      
          @Override
          public void unlockDone(String taskId) {
      
          }
      
          @Override
          public void unlockFail(String taskId, EngineClientException e) {
      
          }
      
          @Override
          public void onSetVariable(String processInstanceId, VariableMap variables) {
      
          }
      
          @Override
          public void setVariableDone(String processInstanceId, VariableMap variables) {
      
          }
      
          @Override
          public void setVariableFail(String processInstanceId, VariableMap variables, EngineClientException e) {
      
          }
      
          @Override
          public void onComplete(String taskId, Map<String, Object> variables, Map<String, Object> localVariables) {
      
          }
      
          @Override
          public void completeDone(String taskId, Map<String, Object> variables, Map<String, Object> localVariables) {
      
          }
      
          @Override
          public void completeFail(String taskId, Map<String, Object> variables, Map<String, Object> localVariables, EngineClientException e) {
      
          }
      
          @Override
          public void onFailure(String taskId, String errorMessage, String errorDetails, int retries, long retryTimeout) {
      
          }
      
          @Override
          public void failureDone(String taskId, String errorMessage, String errorDetails, int retries, long retryTimeout) {
      
          }
      
          @Override
          public void failureFail(String taskId, String errorMessage, String errorDetails, int retries, long retryTimeout, EngineClientException e) {
      
          }
      
          @Override
          public void onBpmnError(String taskId, String errorCode, String errorMessage, Map<String, Object> variables) {
      
          }
      
          @Override
          public void bpmnErrorDone(String taskId, String errorCode, String errorMessage, Map<String, Object> variables) {
      
          }
      
          @Override
          public void bpmnErrorFail(String taskId, String errorCode, String errorMessage, Map<String, Object> variables, EngineClientException e) {
      
          }
      
          @Override
          public void onExtendLock(String taskId, long newDuration) {
      
          }
      
          @Override
          public void extendLockDone(String taskId, long newDuration) {
      
          }
      
          @Override
          public void extendLockFail(String taskId, long newDuration, EngineClientException e) {
      
          }
      
          @Override
          public void onSendMessage(String taskId, String message, VariableMap correlationKeys, VariableMap processVariables, Boolean all) {
      
          }
      
          @Override
          public void sendMessageDone(String taskId, String message, VariableMap correlationKeys, VariableMap processVariables, Boolean all) {
      
          }
      
          @Override
          public void sendMessageFail(String taskId, String message, VariableMap correlationKeys, VariableMap processVariables, Boolean all, EngineClientException e) {
      
          }
      
      
          @Override
          public void unAuthorizedException(EngineClientException e) {
      
          }
      }
      

      We could check the new API (setVariable) that we developed in class ExternalTaskServiceImpl.java

        @Override
        public void setVariables(String processInstanceId, VariableMap variables) {
          try {
            externalTaskClientListener.onSetVariable(processInstanceId,variables);
            engineClient.setVariables(processInstanceId, variables,getXsrf());
            externalTaskClientListener.setVariableDone(processInstanceId,variables);
          } catch (EngineClientException e) {
            externalTaskClientListener.setVariableFail(processInstanceId,variables,e);
            throw LOG.externalTaskServiceException("setting variables for external task", e);
          }
        }
      

      As you could see, we have used three method listeners (onSetVariable,setVariableDone,setVariableFail)

      In the end, we have a tester for the API as below source code

              ExponentialBackoffStrategy backoffStrategy = new ExponentialBackoffStrategy(1000, 1, 1000);
      
              ExternalTaskClient taskClient = ExternalTaskClient.create()
                      .addInterceptor(new CookieAuthProvider())
                      .asyncResponseTimeout(2000)
                      .backoffStrategy(backoffStrategy)
                      .maxTasks(1)
                      .externalTaskClientListener(new DefaultExternalTaskClientListener() {
      
                          @Override
                          public void unAuthorizedException(EngineClientException e) {
                              System.out.println("state: unAuthorizedException");
                              states.add("unAuthorizedException");
                          }
      
                          @Override
                          public void onFetchAndLock(List<TopicRequestDto> topics) {
                              System.out.println("state: onFetchAndLock");
                              states.add("onFetchAndLock");
                          }
      
                          @Override
                          public void fetchAndLockDone(List<TopicRequestDto> topics, List<ExternalTask> externalTasks) {
                              System.out.println("state: fetchAndLockDone");
                              states.add("fetchAndLockDone");
                          }
      
                          @Override
                          public void fetchAndLockFail(List<TopicRequestDto> topics, EngineClientException e) {
                              System.out.println("state: fetchAndLockFail");
                              states.add("fetchAndLockFail");
                          }
      
                          @Override
                          public void onSetVariable(String processInstanceId, VariableMap variables) {
                              System.out.println("state: onSetVariable");
                              states.add("onSetVariable");
                          }
      
                          @Override
                          public void setVariableDone(String processInstanceId, VariableMap variables) {
                              System.out.println("state: setVariableDone");
                              states.add("setVariableDone");
                          }
      
                          @Override
                          public void setVariableFail(String processInstanceId, VariableMap variables, EngineClientException e) {
                              System.out.println("state: setvariableFail");
                              states.add("setvariableFail");
                          }
      
                      })
                      .baseUrl(host + baseUrl)
                      .build();
      

      So we could catch state of each External Task API distinctly and make a better error handing generally.

      Limitations of Scope (Optional):

      Hints (optional):

      It's our pleasure if we can help you( @Tassilo Weidner) with developing listeners package.
      According to the post, it could be such a necessary feature that would be helpful for users.

      Let me know your feedback.

      Thank you in advance

      Taha Arian

      mgm-controller-panel

        This is the controller panel for Smart Panels app

        Attachments

          Activity

            People

              Unassigned Unassigned
              tahaarian taha arian
              Tobias Metzke-Bernstein Tobias Metzke-Bernstein
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Salesforce