REST Activity Feature

Hi,

Ok great. No I think the next step is to make the harcoded params flexible with using field properties on the REST service task. The field property elements needs to be defined like the Mule task (http://www.flowable.org/docs/userguide/index.html#bpmnMuleTask). When this is done, I can help to write some unit tests and maybe you can extend them a bit. Adding the REST task to the Modeler would be the final step to my opinion, when the core engine work is full ready and tested.

Best regards,

Tijs

Hi,

I see standard rest task would be a nice addition.
We have a set of field properties, we use for a similar rest task.
Please consider, if this is a good enough specification.

// Request url
private Expression reqUrl;
// Request method (GET,POST,PUT etc)
private Expression reqMethod;
// Request headers, comma separated KV pairs ( Accept: application/json, Authorization: Basic) (Optional)
private Expression reqHeaders;
// Timeout in seconds for the request (Optional)
private Expression reqTimeout;
// Number of retries of the http client, this is not the task job retry count (Optional)
private Expression reqRetries;
// Request signature in header/cookies (Optional)
private Expression reqSign;
// Request Authenticator object delegate expression, for example OAuth etc (Optional)
private Expression reqAuth;
// Request body expression (Optional)
private Expression reqBody;
// Response headers(by default this is added to execution variables as taskId.respHeaders)
// To override we can mention the variable name as string value (Optional)
private Expression respHeaders;
// Response headers(by default this is added to execution variables as taskId.respCode)
// To override we can mention the variable name as string value (Optional)
private Expression respCode;
// Response headers(by default this is added to execution variables as taskId.respBody)
// To override we can mention the variable name as string value (Optional)
private Expression respBody;
// Response converter delegate expression, like say xml to json, json to xml (Optional)
private Expression respConverter;
// Response filter delegate expression, sometimes we may need to parse response, extract fields (Optional)
private Expression respFilter;
// Response error handler delegate expression( for example to specify HTTP status codes to ignore or retry
// Also, can be a list of KV pairs ( retry: [404, 500], ignore: [400]) (Optional)
private Expression errHandler;

Thanks,
Harsha

Hi @Sibok666,

I would like to help with development of this feature.
Please let me know If I can be of any help.

Thanks,
Harsha

hi @h7kanna for sure you can help, please take a look at my repo for seeing the changes i have maded to the code.

I think that if we can code all the feature with the

callRestService(String protocol,String host, Integer port, String restPath, Map<String,String> inputParameters)

tha its a very simple aproach to the rest call, after that it will be more easy to implement the specification that youre saying.

Tell me if you have doubt about my code and the changes in my repo.

Hi @Sibok666,
Thank you, will start looking into the changes.

Harsha

Hi @tijs, I do a lot of changes, maybe Im nod doing the things correctly, I think the most important thibg that I do in my latest commit to my repo was add the next class:

/**

  • @author Alfredo Suarez
    */
    public class RestTaskJsonConverter extends BaseBpmnJsonConverter {

    public static void fillTypes(Map<String, Class<? extends BaseBpmnJsonConverter>> convertersToBpmnMap, Map<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>> convertersToJsonMap) {

     fillJsonTypes(convertersToBpmnMap);
     fillBpmnTypes(convertersToJsonMap);
    

    }

    public static void fillJsonTypes(Map<String, Class<? extends BaseBpmnJsonConverter>> convertersToBpmnMap) {
    convertersToBpmnMap.put(STENCIL_TASK_RESTCALL, RestTaskJsonConverter.class);
    }

    public static void fillBpmnTypes(Map<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>> convertersToJsonMap) {
    }

    protected String getStencilId(BaseElement baseElement) {
    return STENCIL_TASK_RESTCALL;
    }

    protected void convertElementToJson(ObjectNode propertiesNode, BaseElement baseElement) {
    // done in service task
    }

    protected FlowElement convertJsonToElement(JsonNode elementNode, JsonNode modelNode, Map<String, JsonNode> shapeMap) {
    ServiceTask task = new ServiceTask();
    task.setType(“rest”);
    addField(“protocol”, PROPERTY_RESTTASK_HOST, elementNode, task);
    addField(“host”, PROPERTY_RESTTASK_HOST, elementNode, task);
    addField(“port”, PROPERTY_RESTTASK_PORT, elementNode, task);
    addField(“path”, PROPERTY_RESTTASK_PATH, elementNode, task);
    addField(“inputParameters”, PROPERTY_RESTTASK_INPUT_PARAMETERS, elementNode, task);
    addField(“resultVariable”, PROPERTY_RESTTASK_RESULT_VARIABLE, elementNode, task);
    return task;
    }
    }

Where I get the properties that the user is going to put on the modeler app.

How can I get thesse values in the RestCallActivityBehavior?

So If I can get thesse values, the input párameters, on Behavior activity will be no more hardcoded.

In general terms, I have modified the classes where exist a mule task call to add a rest call here are the classe I have modified until now.

Please give a clue of whats next?

Hi @h7kanna any suggestions?

Hi @Sibok666,

Please check your message box.
Will discuss these changes further.

Thanks,
Harsha

Ok thanks. From what I see on your Github fork, the RestCallActivityBehavior implementation is still a bit empty. I think we first need a full implementation of the RestCallActivityBehavior class with a good amount of unit tests, testing the REST task behavior, also when used in BPMN XML. So I think that would be my suggestion as the next steps.

Best regards,

Tijs

Thanks @tijs Ill work on them.

So I need to start to look at some test.

Harsha and me are talking about the changes needed to be done.

When we have any advance we will update you.

Best regards.

Is the REST service task run asynchronously or as some type of blocking call?

Hi @jchayes,

Implementation I am working on is synchronous( will block the thread running the service task), because it will be part of the transaction.
I’m not sure how this could be asynchronous. Any ideas?

Thanks,
Harsha

Hi @tijs,

Planning to use Jetty as mock server for unit tests.
Do you have any suggestion/conditions?

Thanks,
Harsha

Hi @h7kanna,

I would suggest to use the unit tests of the flowable-rest module as a starting point.
It’s also using Jetty.

Best regards,

Tijs

Hi @tijs,

Need a clarification on this.

Should the HTTP Task/Behavior be in a separate project like flowable-mule and flowable-camel?
Is it ok to have it in flowable-engine module itself. This would lead to hard dependency for flowable-engine on apache http client?

Also thinking if it is a separate module like flowable-mule, multiple implementations based on different type of http clients(apache, jetty, okhttp, java9) libraries can be possible without hard dependency for flowable-engine.

Thanks,
Harsha

Hi Harsha,

Having a separate module makes a lot of sense I think.

Best regards,

Tijs

Thanks @tijs,

Creating a separate module for it called ‘flowable-http’.

Also the HTTP service task is of type ‘http’

serviceTask id=“simpleGet” flowable:type=“http”

@Sibok666 Will commit changes to my fork this week, we can coordinate further on this.

Thanks,
Harsha

Hello @tijs,

Before moving forward with my commits.
I want to confirm if the below HTTP Task spec is good.
Please review, so that I can go ahead, commit and raise pull request for implementation specific commits.

https://github.com/h7kanna/flowable-engine/blob/b3b5e8f3c180c16913bd267b99da823a64f14234/userguide/src/en/ch07b-BPMN-Constructs.adoc

Thanks,
Harsha

Hi Harsha,

Thanks, it’s looking very good. Couple of points:

  • could you keep HTTPClientConfig lower case in the process engine config, so httpClientConfig?
  • do you also allow expressions in the requestUrl and requestHeaders field extensions? I would guess so, but just to verify.
  • I’m curious about the retry feature, are you using async jobs for this or something else?
  • Maybe a resultVariable name would also be good as a property, so you can define the execution variable where you want to store the response.
  • Authentication is an important part of the HTTP task, so maybe it would be good to add a specific property to add a http request header or another token in the HTTP request for authentication purpose.
  • It might also be nice to be able to define a response parser, so you can easily inject some logic to set certain parts of the response as execution variables.

These are not all points for a version 1 implementation, but just stuff that crossed my mind.

Best regards,

Tijs

Hi @tijs,

  • Will change HTTPClientConfig to httpClientConfig.

  • expressions are allowed as mentioned.

  • Retry feature would be Http Client retrying the request( we can set this by configuring retry handler on apache client). This is just for resiliency for temporary network issues. As sync job is concerned, I am planning to throw Flowable exception based on ignore,retry settings so that Job Executor retries based on ‘flowable:failedJobRetryTimeCycle’. I am not sure if this can be implemented like Camel receive task.

  • Updated resultVariables handling. Needed a clarification though. I am using a prefix value to give variables unique names in the execution. Will ‘taskId.fieldName’ suffice to make it unique? User can override this by ‘variableNamePrefix’

  • Will start working on Authentication, Request parsing once version 1 is done and reviewed.

Thanks,
Harsha