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