This document briefly describes a brief usage of the SOAP workflow framework when developing a service consumer.
Include Page | ||||
---|---|---|---|---|
|
Getting
...
Started
First The first thing you need to do is to check the service endpoint end-point description page and WSDL document using the provided endpoint end-point address.
Usually the address for endpoint of the end-point description page looks like this:
- http://<host>:<port>/application-name/InvokerService
and the WSDL location like this:
- http://<host>:<port>/application-name/InvokerService?wsdl
...
Accessing the end-point description page you should see display something like this:
and when trying it is attempted to access the WSDL location you should be able to see , the valid WSDL document should be displayed.
When you have the WSDL document, you can start generating the DTO classes. Many programming languages have it's their own tools for class generation from WSDL.
One of the easiest ways to do this in JAVA Java is to use JAX-WS and Maven with a plugin called jaxws-maven-plugin. The example Maven pom.xml file could look like this:
When you have successfully generated the class sources, you can start developing your service client using these classes and invoking the workflows.
The WSDL and data types XSD definitions:
Code Block | ||||
---|---|---|---|---|
| ||||
<?xml version="'1.0"' encoding="'UTF-8"?> <project xmlns="'?><!-- Published by JAX-WS RI at http://mavenjax-ws.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocationdev.java.net. RI's version is JAX-WS RI 2.2.7b06 svn-revision#12863. --><!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2.7b06 svn-revision#12863. --> <definitions xmlns:wsu="http://mavendocs.apacheoasis-open.org/POM/4wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.0 xsd" xmlns:wsp="http://mavenwww.apachew3.org/ns/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example.integration.crm</groupId> <artifactId>example-client</artifactId> <version>1.0-SNAPSHOT</version> <name>Example integration project</name> <description>Example integration project</description> <scm> <developerConnection>scm:svn:https://svn.example.com/svn/dev/integration/example-client</developerConnection> </scm> <properties> ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://soap.CDRator.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://soap.CDRator.com/" name="InvokerService"> <types> <xsd:schema> <project.java.version>1.6</project.java.version> </properties><xsd:import namespace="http://soap.CDRator.com/" schemaLocation="definition.xsd"/> <dependencyManagement></xsd:schema> </types> <message name="executeMethod"> <dependencies> <part name="parameters" element="tns:executeMethod"/> </message> <message name="executeMethodResponse"> <dependency> <part name="parameters" element="tns:executeMethodResponse"/> <groupId>javax.xml.ws</groupId></message> <portType name="InvokerService"> <operation name="executeMethod"> <artifactId>jaxws-api</artifactId> <input wsam:Action="http://soap.CDRator.com/InvokerService/executeMethodRequest" message="tns:executeMethod"/> <version>2.2.7</version> <output wsam:Action="http://soap.CDRator.com/InvokerService/executeMethodResponse" message="tns:executeMethodResponse"/> </operation> </dependency>portType> <binding name="InvokerServicePortBinding" type="tns:InvokerService"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <dependency> <operation name="executeMethod"> <groupId>javax.xml.bind</groupId><soap:operation soapAction=""/> <input> <artifactId>jaxb-api</artifactId><soap:body use="literal"/> </input> <output> <version>2.2.6</version> <soap:body use="literal"/> </dependency>output> </operation> </binding> <service name="InvokerService"> <dependency> <port name="InvokerServicePort" binding="tns:InvokerServicePortBinding"> <soap:address location="http://localhost:8080/simyo-workflow-soap/InvokerService"/> <groupId>javax.xml.soap</groupId> </port> </service> </definitions> |
Code Block | ||
---|---|---|
| ||
<?xml version='1.0' encoding='UTF-8'?> <!-- Published by JAX-WS RI <artifactId>saaj-api</artifactId> <version>1.3.4</version> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>com.sun.xml.ws</groupId> at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2.7b06 svn-revision#12863. --> <xs:schema xmlns:tns="http://soap.CDRator.com/" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://soap.CDRator.com/"> <xs:element name="executeMethod" type="tns:executeMethod"/> <xs:element name="executeMethodResponse" type="tns:executeMethodResponse"/> <xs:complexType name="executeMethod"> <xs:sequence> <artifactId>jaxws-rt</artifactId> <xs:element name="arg0" type="tns:requestDTO" minOccurs="0"/> <version>2.1.4</version></xs:sequence> </xs:complexType> <xs:complexType name="requestDTO"> <scope>provided</scope> <xs:sequence> </dependency> <xs:element name="hookpointKey" type="xs:string" minOccurs="0"/> <dependency> <xs:element name="values" type="tns:valueDTO" nillable="true" <groupId>javax.xml.bind</groupId>minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <artifactId>jaxb-api</artifactId></xs:complexType> </dependency><xs:complexType name="valueDTO" abstract="true"> <xs:sequence> <dependency> <xs:element name="key" type="xs:string" minOccurs="0"/> <groupId>javax.xml.ws</groupId> </xs:sequence> </xs:complexType> <artifactId>jaxws-api</artifactId> <xs:complexType name="dateValueDTO"> <xs:complexContent> </dependency> <dependency><xs:extension base="tns:valueDTO"> <xs:sequence> <groupId>javax.jws</groupId> <xs:element <artifactId>jsr181-api</artifactId>name="value" type="xs:dateTime" minOccurs="0"/> </dependency>xs:sequence> <dependency></xs:extension> </xs:complexContent> <groupId>javax.xml.soap</groupId></xs:complexType> <xs:complexType name="complexValueDTO"> <artifactId>saaj-api</artifactId><xs:complexContent> </dependency><xs:extension base="tns:valueDTO"> <dependency> <xs:sequence> <groupId>javax.xml</groupId> <xs:element name="value" type="tns:valueDTO" nillable="true" minOccurs="0" maxOccurs="unbounded"/> <artifactId>jax-qname</artifactId> </xs:sequence> <version>1.1</version> </xs:extension> </dependency>xs:complexContent> </dependencies>xs:complexType> <build> <xs:complexType name="stringValueDTO"> <sourceDirectory>src/main/java</sourceDirectory><xs:complexContent> <testSourceDirectory>src/test/java</testSourceDirectory> <xs:extension base="tns:valueDTO"> <resources> <xs:sequence> <resource> <xs:element name="value" type="xs:string" minOccurs="0"/> <directory>src/main/resources</directory></xs:sequence> </xs:extension> </resource> </xs:complexContent> </resources>xs:complexType> <xs:complexType name="longValueDTO"> <testResources> <xs:complexContent> <testResource> <xs:extension base="tns:valueDTO"> <xs:sequence> <directory>src/test/resources</directory> <xs:element name="value" type="xs:long"/> </testResource> </testResources>xs:sequence> </xs:extension> <plugins> </xs:complexContent> </xs:complexType> <plugin> <xs:complexType name="doubleValueDTO"> <xs:complexContent> <groupId>org.apache.maven.plugins</groupId> <xs:extension base="tns:valueDTO"> <xs:sequence> <artifactId>maven-compiler-plugin</artifactId> <xs:element name="value" type="xs:double"/> <configuration> </xs:sequence> </xs:extension> <source>${project.java.version}</source>xs:complexContent> </xs:complexType> <xs:complexType name="booleanValueDTO"> <xs:complexContent> <target>${project.java.version}</target> <xs:extension base="tns:valueDTO"> </configuration> <xs:sequence> </plugin> <xs:element name="value" type="xs:boolean"/> <plugin> </xs:sequence> </xs:extension> <groupId>org.jvnet.jax-ws-commons</groupId></xs:complexContent> </xs:complexType> <xs:complexType name="executeMethodResponse"> <artifactId>jaxws-maven-plugin</artifactId> <xs:sequence> <xs:element name="return" <version>2.1</version>type="tns:responseDTO" minOccurs="0"/> </xs:sequence> </xs:complexType> <executions> <xs:complexType name="responseDTO"> <xs:sequence> <xs:element name="errorCode" type="xs:long"/> <execution> <xs:element name="errorMessage" type="xs:string" minOccurs="0"/> <xs:element name="status" type="xs:long"/> <goals> <xs:element name="values" type="tns:valueDTO" nillable="true" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <goal>wsimport</goal> </goals> </execution> </xs:schema> |
Assuming the workflow must be invoked which expects you to send the following structure:
Request:
Key | Value type | Mandatory | Description |
---|---|---|---|
CONTEXT | ComplexValueDTO | true | Context object, mandatory in each request. |
CONTEXT:
Key | Value type | Mandatory | Description |
---|---|---|---|
LANGUAGE | StringValueDTO | true | Language code. EN, FR, DK, etc. Used for displaying error messages. |
OPERATOR | StringValueDTO | true | Operator information. |
BRAND_ID | StringValueDTO | false | Id of the brand if applicable. |
then your client code would look something like this:
Code Block | ||
---|---|---|
| ||
private static final String YOUR_HOOKPOINT_KEY = "YOUR_HOOKPOINT_KEY"; private static final String CONTEXT_KEY = "CONTEXT"; private static final String LANGUAGE_KEY = "LANGUAGE"; private static final String OPERATOR_KEY = "OPERATOR"; private static final String LANGUAGE_EN = "EN"; private static final String OPERATOR_DUMMY = "DUMMY"; <...> public void invokeYourWorkflow() { InvokerService_Service service = new InvokerService_Service(); InvokerService servicePort = service.getInvokerServicePort(); RequestDTO request = </executions> new RequestDTO(); request.setHookpointKey(YOUR_HOOKPOINT_KEY); StringValueDTO language = new <configuration>StringValueDTO(); language.setKey(LANGUAGE_KEY); language.setValue(LANGUAGE_EN); StringValueDTO operator = new <packageName>com.example.service</packageName>StringValueDTO(); language.setKey(OPERATOR_KEY); language.setValue(OPERATOR_DUMMY); ComplexValueDTO context </configuration>= new ComplexValueDTO(); context.setKey(CONTEXT_KEY); </plugin>context.getValue().add(language); context.getValue().add(operator); </plugins> request.getValues().add(context); </build> </project> |
Place the WSDL document in <project_dir>/src/wsdl and run the following command to generate the class source files:
Code Block |
---|
mvn generate-sources |
When you have successfully generated the class sources, you can start developing your service client using these classes and invoking the workflows.
Lets say you have to invoke the workflow which expects you to send the following structure.
Request:
Key | Value type | Mandatory | Description |
---|---|---|---|
CONTEXT | ComplexValueDTO | true | Context object, mandatory in each request. |
CONTEXT:
Key | Value type | Mandatory | Description |
---|---|---|---|
LANGUAGE | StringValueDTO | true | Language code. EN, FR, DK, etc. Used for displaying error messages. |
OPERATOR | StringValueDTO | true | Operator information. |
BRAND_ID | StringValueDTO | false | Id of the brand if applicable. |
...
ResponseDTO response = servicePort.executeMethod(request);
} |
This approach gives a lot of flexibility as the changes to the service may be applied rapidly, it is just a matter of adding another DTO to a value list.
Note: You can also have a tree-like structure using ComplexValueDTO objects, i.e. you can have a list of ComplexValueDTO objects inside another ComplexValueDTO object. The example would look like this:
Code Block | ||
---|---|---|
| ||
private static final String YOURROOT_HOOKPOINT_KEY = "YOUR_HOOKPOINT_KEYROOT"; private static final String CONTEXTCHILD_ONE_KEY = "CONTEXTCHILD_ONE"; private static final String LANGUAGESUB_CHILD_ONE_KEY = "LANGUAGESUB_CHILD_ONE"; private static final String OPERATORSUB_CHILD_TWO_KEY = "OPERATORSUB_CHILD_TWO"; private static final String LANGUAGEDUMMY_ENKEY = "ENDUMMY"; private static final String OPERATORDUMMY_DUMMYVALUE = "DUMMY"; <...> public void invokeYourWorkflowdoSomething() { InvokerService_Service service = new InvokerService_Service(); InvokerService servicePort = service.getInvokerServicePort<...> StringValueDTO dummy = new StringValueDTO(); RequestDTO request = new RequestDTO(dummy.setKey(DUMMY_KEY); requestdummy.setHookpointKeysetValue(YOURDUMMY_HOOKPOINT_KEYVALUE); StringValueDTOComplexValueDTO languagesubChildOne = new StringValueDTOComplexValueDTO(); languagesubChildOne.setKey(LANGUAGESUB_CHILD_ONE_KEY); language.setValue(LANGUAGE_ENsubChildOne.getValue().add(dummy); StringValueDTOComplexValueDTO operatorsubChildTwo = new StringValueDTOComplexValueDTO(); languagesubChildTwo.setKey(OPERATORSUB_CHILD_TWO_KEY); language.setValue(OPERATOR_DUMMY subChildTwo.getValue().add(dummy); ComplexValueDTO contextchildOne = new ComplexValueDTO(); contextchildOne.setKey(CONTEXTCHILD_ONE_KEY); contextchildOne.getValue().add(languagesubChildOne); contextchildOne.getValue().add(operator().add(subChildTwo); ComplexValueDTO root = new ComplexValueDTO(); context.setKey(ROOT_KEY); requestcontext.getValuesgetValue().add(contextchildOne); ResponseDTO response = servicePort.executeMethod(request); } |
This approach gives a lot of flexibility as the changes to service maybe applied rapidly, it's just a matter of adding another DTO to a value list.
...
<...>
}
<...> |
This becomes useful when you have to transfer some kind of very complex object and pass it to the workflow framework.