Updating a connector in a Java Delegate during execution

I was wondering if anyone knew how to update a CamundaConnector while inside a Java Delegate during execution. My use case is to populate Connector specific variables before its execution by using a Java Delegate Execution Listener at the start phase of the Service Task. In my case I’m making use of a http-connector to make a call out to a REST service and would like to replace path and query parameters within the url input parameter eg:

http://example.com/service?make=${make}&model=${model}

where ${make} and ${model} are replaced with variables on the execution. Up to this point I’ve had the the url input parameter be of type script and I would evalute the variables with a Groovy inline script eg:

"http://example.com/service?make=${make}&model=${model}".toString()

This approach works well but has limitations. Lets say we only have a value for ${make} and not one for ${model}, upon execution this leads to an exception being thrown eg:

groovy.lang.MissingPropertyException: No such property: model for class: Script2

This led me to start looking at alternate solutions. My first thought, and what I’ve been trying to get working, is to use a Java Delegate Execution Listener to replace the values before the Service Task is executed. From the execution I pull out the connector and update the values on the Element Instance however this doesn’t actually update what gets executed, eg:

public void execute(DelegateExecution execution) throws Exception {
    ExtensionElements extensions = execution.getBpmnModelElementInstance().getExtensionElements();
    List<CamundaConnector> connectors = extensions.getElementsQuery().filterByType(CamundaConnector.class).list();
    CamundaConnector connector = connectors.get(0);
    CamundaInputOutput inputOutput = connector.getCamundaInputOutput();
    Collection<CamundaInputParameter> inputs = inputOutput.getCamundaInputParameters();
    for (CamundaInputParameter input : inputs) {
        switch (input.getCamundaName()) {
            case "url":
                input.setTextContent(handleURL(input.getTextContent()));
                break;
            case "payload":
                break;
            default:
                break;
        }
    }
}

I’ve tried the various methods exposed via the api to actually have the changes to the instance persist within the runtime but am starting to hit a wall with new things to try. I’m hoping it’s something silly I missed and it’s something one of you guys can point out.

Thanks,
Paul

Still haven’t had any luck figuring out how to change the instance of the connector but I came up with somewhat of a workaround:

private static final String VARIABLE_PATTERN = "\\$\\{(.*?)}";

private void addEmptyVariables(DelegateExecution execution, String content) {
    List<String> matches = new ArrayList<>();
    Matcher matcher = Pattern.compile(VARIABLE_PATTERN).matcher(content);
    while (matcher.find()) {
        matches.add(matcher.group(1));
    }
    for (String match : matches) {
        if (execution.getVariable(match) == null) {
            LOGGER.info("adding empty variable for: " + match);
            execution.setVariable(match, "");
        }
    }
}

This will find all variable instances within the content string and then check if they are known on the execution. If they aren’t, then they will be added as an empty string so that the Groovy evaluation of the variable doesn’t fail. I don’t like this solution for many reasons so if anyone else has an answer let me know!

Paul

@8bitoverflow use scripts on your connector inputs rather than expressions. So each input (such as the url) can dynamically determine the values based on the script execution.

Can also take a look at Replacing Http-Connector with Jsoup usage as a example for using a entire script for your HTTP connections rather than using the connector. (replace with your client of choice).