Novice modeler question about the SOAP connector

So here’s a stupid question…
I see the camunda modeler offers the connector property. And as far as I know there is a SOAP connector.
Now I saw some models that had the soap call in there but I did not quite understand them…
What I would like to know is it possible to invoke a SOAP call from the modeler, and get the response back as project variables or somehow parse them to the project variables.
I looked through 3 different examples and when I wanted to change the SOAP call I never seemed to get it right.
I found this fixed example here: Redirecting to Google Groups posted by Sebastian and I cant get it to work on my camunda wildfly distro. I will try it again on JBoss, later.
But for now can anyone give me a working, runnable example that works on wildfly of a SOAP call? That is made in the modeler?
Thanks for the help!

Hi @greaneagle,

do I understand your question properly that you want your process to start a SOAP call from a script task or Delegate execution? in this case please take a look here

I think it’s not possible to trigger soap calls from modeler, calls to whatever can be performed only during execution by engine and not during modelling process itself.

Cheers,
Askar

Firstly, and this may be an unpopular opinion, I was adamantly against the termination of the Eclipse plugin because it offered a much richer environment for development. One thing that can be incorporated into Eclipse is SoapUI, which would have provided information and help in situations like this. Moreover, the underlying tooling that Eclipse supports would have made such a thing possible within the Eclipse Modeler Plugin or an ancillary tool to it.

I don’t work in the standalone Modeler except to create DMN tables. So what follows is from my Eclipse experience, though it should be applicable in Modeler.

That said, the easiest way I’ve found to drive SOAP calls is to use the Freemark Template Language (FTL) support within Camunda. FTL allows you to build your SOAP message almost “natively” and then substitute in process variables for certain parts of the SOAP message. The response from the SOAP web service can then be parse using SPIN, though I can’t help you with that.

To use the FTL template, you need a “prototype” request. Within that request will be values that are part of the specific request. An FTL template file entry for ticket number value might look like this:

tkns:FieldsList
tkns:String${ticketNum}</tkns:String>
</tkns:FieldsList>

This would be surrounded by the rest of the XML text that is part of your request. This goes into a separate file in the same directory as your BPMN code.

In the properties of the service task (that’s what I use to do this), On the connector tab you will use an “Id” of “soap-http-connector” and input parameters “url”, “payload”, and “headers”. The “ticketNum” value must exist as a process variable to be picked up by the FTL code. The “payload” is a reference to the FTL file you created. The “url” is the SOAP service endpoint URL. The “headers” is mostly just fixed text (see below). The output parameter will contain the response from the SOAP service and must be further processed using SPIN or separate code.

Here is the “Parameter Details” panel of the FTL file for the “payload” input parameter:

Name: payload
Type: Script
Script Format: freemarker
Script Resource: bpmn/soapTicketLookup.ftl

The “url” input parameter can be a process variable or even hard-coded I suppose.

The “headers” input parameter can generally be hard-coded, but here are the parameters for my example:

Name: headers
Type: Map
Key: Content-Type
value: application/soap+xml;charset=UTF-8;action=""

The BPMN code itself provides additional information as to what is required:

   <camunda:connector>
      <camunda:connectorId>soap-http-connector</camunda:connectorId>
      <camunda:inputOutput>
        <camunda:inputParameter name="url">${ticketWsUrl}</camunda:inputParameter>
        <camunda:inputParameter name="payload">
          <camunda:script scriptFormat="freemarker" resource="bpmn/soapTicketLookupEnvelope.ftl"/>
        </camunda:inputParameter>
        <camunda:inputParameter name="headers">
          <camunda:map>
            <camunda:entry key="Content-Type"><![CDATA[application/soap+xml;charset=UTF-8;action=""]]></camunda:entry>
          </camunda:map>
        </camunda:inputParameter>
        <camunda:outputParameter name="ticketWsResponse">${response}</camunda:outputParameter>
      </camunda:inputOutput>
    </camunda:connector>

The documentation provides some additional information, but the examples that can be found in the Camunda section of GitHub provide even more examples.

Hope this helps.

1 Like

Aha, I see.
Yes I did see something similar in the examples and that is what sparked my questions, since most of it is done in the modeler in your example.
Could you perhaps send me the class that you use to envoke this webservice of yours?
I will probably be able to figure out the parsing but it would help me a lot if I could see your example.

With all the data you provided you could write a really nice tutorial for SOAP calls in camunda, or if you are interested I would be willing to write it once I do it corectly, since I believe SOAP calls are very important to BPM and should be utalized.
It bugs me that it takes me so long to figure out a SOAP call in camunde where as in another BPM software it is literarly just 4 clicks and it works…

Thank you again and could you provide me your BPM code? You can also pm me.

Thanks!

Hi @greaneagle,

the example from above is based on

https://docs.camunda.org/manual/7.5/reference/connect/soap-connector/

which is configured in bpmn directly

you can find connectors source code here

Does that help you?
Askar

Yes and no,
I did look at this one, but what if I want to call a webservice with a WSDL?
This onw uses a an asmx file which I am not familiar with…

For example what if I wanted to make a SOAP call to this webservice:

http://webservices.daehosting.com/services/TemperatureConversions.wso?WSDL

This is my irst goal.
Create a simple proces. On the start of the proces you input the clsius, and in the next task you read the fharenheit.
It works OK in SOAP UI and I got it to work nicely with our other BPM suite but I would like to get it working on camunda…

Thank you for your help.

@greaneagle,

have you already tried to replace

http://www.webservicex.net/globalweather.asmx

with

http://webservices.daehosting.com/services/TemperatureConversions.wso

and

http://www.webserviceX.NET/GetWeather

with your operation?

No I did not…
OK, lets see, I will come back and post about my result.
Thanks for now.

OK I am getting closer…
I replaced everything and fixed the first bug I ran into and now have a problem with SPIN
When trying to maven build the project i get this error:

shouldInvokeService(org.camunda.bpm.example.servicetask.soap.ServiceTaskSoapTest): SPIN-01004 No matching data format detected

I have no experiance with spin so I might have messed something up.

Do you perhaps see the error in the folowing script?

package org.camunda.bpm.example.servicetask.soap;

import java.util.HashMap;
import java.util.Map;

import org.camunda.bpm.engine.RuntimeService;
import org.camunda.bpm.engine.TaskService;
import org.camunda.bpm.engine.task.Task;
import org.camunda.bpm.engine.test.Deployment;
import org.camunda.bpm.engine.test.ProcessEngineRule;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
/**

  • @author Daniel Meyer

*/
public class ServiceTaskSoapTest {

@Rule
public ProcessEngineRule processEngineRule = new ProcessEngineRule();

@Test
@Deployment(resources={“invokeSoapService.bpmn”})
public void shouldInvokeService() {
Map<String, Object> variables = new HashMap<String, Object>();
variables.put(“celsius”, “20”);

RuntimeService runtimeService = processEngineRule.getRuntimeService();
TaskService taskService = processEngineRule.getTaskService();

runtimeService.startProcessInstanceByKey("weatherForecast", variables);

Task task = taskService.createTaskQuery().singleResult();
Assert.assertNotNull(task);

int temperature = Integer.parseInt( taskService.getVariable(task.getId(), "temperature").toString() );
if(temperature >= 18) {
  Assert.assertEquals("UserTask_1", task.getTaskDefinitionKey());
} else {
  Assert.assertEquals("UserTask_2", task.getTaskDefinitionKey());
}

}

}

@greaneagle,

yes, let’s try this out. You would ofcourse have to also adjust response processing scripts. Please let me know how it goes once you have more information.

Alternatively you could just do it using pache cxf or any other frameowrk of your choice in the delegate.

About providing documentation, it would be great if you would contribute a nice explanation on how the things are working may be paired with your example code on the github. We can probably publish it on our blog then.

Cheers,
Askar

could you publish that on github, so that I can try it our too?

Cheers,
Askar.

Sure, here is the link

@greaneagle,

you don’t really need spin there. You are getting parsed temperature already. Your parseTemperature.js should look like this

var rawForecast = execution.getVariable(‘forecast’);
rawForecast.substring(rawForecast.indexOf("\n"));

then all works fine.

Hope that helps,
Askar

Thanks for the help Askar!
It worked but since the example project was made as just a test it got built correctly but into a jar file which I can’t deploy to my Wildfly server (or did I miss something?)
Which led to me creating a new project, coppying the code, adding dependencies and everything else (took a while since I had to figure out the errors that I was getting, but hey, that’s how we learn, right?)
Anyway, when I got it to build corectly I still could not deploy it.
As I said I am running the standard Wildfly camunda distribution that coes prepacked.
I have posted my new project to github https://github.com/greaneagle/camundaSOAPtest
in the folder convertest

Where did I go wrong this time?

@greaneagle,
if you want to deploy it in prepackaged camunda wildfly you have to exclude camunda dependencies from your pom as they are already available in wildfly distribution.

i.e. this folder should not contain camunda jars

Cheers,
Askar.

Wait, but if I remove the camunda dependencies from my POM I can’t build my project…

use scope provided on dependencies and

<build> <defaultGoal>clean test</defaultGoal> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> </plugins> </build>

actually I wonder why don’t you wanna package it as jar and put on engine classpath. Would be easier I assume. In any case we are now out soap connectors scope, as this part is working.

Cheers,
Askar.

1 Like

Jup, we got off topic here :slight_smile: Thanks for all the help.
And as to why I don’t just package it into a jar and put it in the engine classpath is because I don’t know how to do that.
Maybe in another post.
I will somehow get this to work and maybe write a whole new post about it and how I did it incase someone else has these problems.
I understand It is quite simple for some people, but for me it just didn’t click…
Anyways thank you very much an again this community is awesome.

@greaneagle,

you’re welcome. If you ever feel like you want to share your experience you can use our blog to contribute it. You can prepare a pull request to https://github.com/camunda/blog.camunda.org.

Happy hacking :slight_smile:
Askar.

The Camunda SOAP connector doesn’t use a custom class. It is part of the main distribution of Camunda (one of two “connectors” provided by Camunda). If you give it the proper “url”, “payload”, and “headers”, it will do the rest. For me, this wasn’t the complicated part. Parsing the response sent by the SOAP service was complicated by the fact that I was trying to use SPIN in a version of Camunda that had a SPIN bug in it. I gave up on SPIN and we utilized a custom class to parse the SOAP XML.

This bug has been fixed and many of our developers are using SPIN now and I would recommend that you do this. That said, Camunda, like any software, has its strengths and weaknesses. For example, ActiveVos from Informatica (which I have also used) makes interacting with SOAP service much easier than Camunda. However, ActiveVos is very expensive and doesn’t scale like Camunda.

Another issue with Camunda is the transition to a standalone “Modeler” application. This standalone application doesn’t have nearly the functionality that Eclipse with the Camunda plugin has. It is, however, much easier to use for process design than Eclipse, which is probably why Camunda has chosen develop it further and stop development of the Eclipse plugin.

As far as the BPMN code is concerned, and this is just my opinion, you should avoid writing BPMN code directly whenever possible. Nearly every feature within Camunda is accessible through the Modeler interface. The advantage of staying in the Modeler application versus hand coding BPMN is, the Modeler will produce syntactically correct code nearly every time. So, you have to be very careful if you choose to directly modify the BPMN code itself. The code that I gave you is pretty much everything you need to make the SOAP call.

The following are from Eclipse and show the two main property pages that are used to make the SOAP call. The BPMN code for them is what I put in my previous post. The code I used to parse the response I cannot share, not because it’s it contains some sort of “magic”, but because I would have to clear it through our legal department first. Suffice it to say that’s it’s nothing more than a library that allows you to provide a key that returns a value from XML. In any event, you should be using SPIN for this.

In the property pages below, the key variables are in the SOAP connector input and output sections. Basically, “url”, “payload”, and “headers”, provide information to make the SOAP call itself. “aotsResponse” is the raw XML response from the SOAP web service. In this case, you would pass “aotsResponse” through SPIN to extract whatever values you wanted from the response. Remember, your SOAP request will be encoded in an FTL file that you reference in the SOAP connector configuration “payload” variable. That FTL file will look almost identical to the actual SOAP message sent, with the exception that any values within that need to modified by your process will be represented by process variables and in the form of “${variable}”.

Service Task Configuration:

[cid:image002.png@01D2291E.13B5E090]

Camunda HTTP SOAP Connector Configuration:

[cid:image001.png@01D2291E.72418560]

For example, if the SOAP service requires you to provide a user name for authentication and that user name might vary based upon how the process was started, your FTL file would contain something like this:

ns1:username
${soapUserName}
</ns1:username>

I can’t really tell you how your SOAP message will look. You need to use something like SoapUI (SmartBear Software provides a free version) to build the SOAP message itself. Once you have that, you put the message into the FTL file. Here is the parameter panel for the “payload” variable. In it you can see I have referenced an FTL file called bpmn/soapAotsTicketLookupEnvelope.ftl. The SOAP request that you build in SoapUI would be put into the FTL file and then you substitute any static values with FTL variables whose value is represented by a process variable of the same name (e.g. ${soapUserName} would have the value of process variable “soapUserName”). The value of the process variable must be set elsewhere in your process.

[cid:image004.png@01D22920.6EAC3EC0]

Michael Peoples (mp4783)
Global Customer Service BizOps Orchestration
Office: +1 614-886-0923
Mobile: +1 614-886-0923

Principal Applications Developer