{table-plus:enableSorting=false|width=665}
*Change log:*
|| Date: || Author: || Version: || Changes: || Completed || Ext. || Int. || Is in Core || Jira Ref. ||
| {page-info:created-date|dateFormat=dd MMMM yyyy} | {page-info:created-user} | 0.1 | Doc. created | Yes | x | | N/A | |
| 20. June 2012 \\ | Eduardas Kazakas | 0.2 \\ | Added section on Client authentication | Yes \\ | x \\ | | N/A \\ | |
| 2. July 2012 \\ | Anders Dinesen \\ | 0.3 \\ | Updated section on Client authentication | Yes \\ | x \\ | | N/A \\ | |
| 23. May 2013 | Jon Fuglsang | 0.4 | Added parameter to disable caching of validation XML files | Yes \\ | x \\ | | N/A \\ | |
| 18. Nov 2013 | Jon Fuglsang | 0.5 | Added parameter to to enable default brand in workflow SOAP workflows | Yes \\ | x \\ | | N/A \\ | |
\\
----
{include:Workflows SOAP API}
h2. Requirements to the Workflow
# Workflows started by the SOAP method should contain only inProcess activities and be completely executed by the Tomcat, since SOAP methods are synchronous and should return the result within relatively short period of time.
\\
\\
# The hash table which is returned as the result of the workflow execution must contain only values of type long, double, String, Date or Hashtable.
## It is possible however to configure transformation of PersistentObjects to extract specific fields and add them to the response. This is for some reason configured in the Validation xml - see below.
# The hash table which is returned as the result of the workflow execution must contain the values with the following keys used in the ResponseDTO to identify the status of the SOAP call: STATUS, ERROR_LEVEL, ERROR_MESSAGE.
\\
\\
# In most of the cases SOAP calls are used as a part of direct user interaction so the response time should be fast, which means embedded inProcess workflow should be executed within the corresponding time frames.
h2. Getting Started
In order to get started with the SOAP workflow framework you will have to include the Maven artifact in your pom.xml file as a runtime dependency.
{code:language=html/xml} Wiki Markup
Include Page | ||||
---|---|---|---|---|
|
Requirements to the Workflow
- Workflows started by the SOAP method should contain only inProcess activities and be completely executed by the Tomcat, since SOAP methods are synchronous and should return the result within relatively short period of time.
- The hash table which is returned as the result of the workflow execution must contain only values of type long, double, String, Date or Hashtable.
- It is possible however to configure transformation of PersistentObjects to extract specific fields and add them to the response. This is for some reason configured in the Validation xml - see below.
- The hash table which is returned as the result of the workflow execution must contain the values with the following keys used in the ResponseDTO to identify the status of the SOAP call: STATUS, ERROR_LEVEL, ERROR_MESSAGE.
- In most of the cases SOAP calls are used as a part of direct user interaction so the response time should be fast, which means embedded inProcess workflow should be executed within the corresponding time frames.
Getting Started
In order to get started with the SOAP workflow framework you will have to include the Maven artifact in your pom.xml file as a runtime dependency.
Code Block | ||
---|---|---|
| ||
<dependency>
<groupId>com.cdrator.integration.soap</groupId>
<artifactId>rator-soap-workflow</artifactId>
<version>2.4</version>
<scope>runtime</scope>
</dependency> |
...
If you are adding the SOAP workflow functionality to an existing customer project, then it is best to implement this as a project module, e.g.: SIMYO/modules/workflowSoap/pom.xml. Note that usually the artifact dependency is specified in the parent pom.xml file with the version specified (e.g.: SIMYO/pom.xml): {
Code Block |
---|
...
|
...
|
...
<dependency>
<groupId>com.cdrator.integration.soap</groupId>
<artifactId>rator-soap-workflow</artifactId>
<version>2.4</version>
</dependency> |
...
and in the module pom.xml file with the scope (e.g.: SIMYO/modules/workflowSoap/pom.xml): {
Code Block |
---|
...
|
...
|
...
<dependency>
<groupId>com.cdrator.integration.soap</groupId>
<artifactId>rator-soap-workflow</artifactId>
<scope>runtime</scope>
</dependency> |
...
Also, don't forget to include the following dependency to build the deployable WEB application WAR file: {code:language=html/xml}remember to include the following dependency to build the deployable WEB application WAR file:
Code Block | ||
---|---|---|
| ||
<dependency>
<groupId>com.cdrator.integration.soap</groupId>
<artifactId>rator-soap-workflow</artifactId>
<classifier>webapp</classifier>
<type>war</type>
<scope>runtime</scope>
</dependency> |
...
In addition to that, configure the build process, Maven renamer and Maven WAR plugins. The example build section configuration might look like this: {
Code Block |
---|
...
|
...
|
...
<build>
<finalName>simyo-workflow-soap</finalName>
<plugins>
<plugin>
<groupId>com.cdrator.maven.plugins</groupId>
<artifactId>rator-maven-renamer-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<outputDirectory>${project.parent.build.directory}</outputDirectory>
</configuration>
</plugin>
</plugins>
</build> |
...
The last thing about this artifact is that +starting from version 2.0 it uses JAX-WS+ for exposing end-point and providing WSDL document.
If you try to create the separate project that uses SOAP workflow framework, then just include the dependencies in the main pom.xml file and configure the build section to create the correct WAR file.
In order to test that your setup is correct, build the project using Maven and deploy the built WAR file on Tomcat. If the deployment is successful, then go to the following address in your browser: *
- http://<host>:<port>/your-application/InvokerService
...
You should see the minimal description of your end-point. Note that this applies to the framework versions starting from 2.0 (JAX-WS based web services). If you want to get the WSDL document, then access the following URL: *
- http://<host>:<port>/your-application/InvokerService?wsdl
...
You should be able to see the valid WSDL document. If the application was deployed without errors, but you are unable to access WSDL or end-point description page, then please refer to log files, there might be some issues regarding parameter tree configuration. h5. Configuring Parameters Before creating the workflows and building your service layer, you should consider configuring the following parameters: || Parameter key || Possible values || Description || Available from version || | SOAP.MONITORING.ENABLE_RATOR_MONITORING_HANDLER | T/F | | | | SOAP.MONITORING.ENABLE_XML_PERSISTENCY | T/F | | | |
Configuring Parameters
Before creating the workflows and building your service layer, you should consider configuring the following parameters:
Parameter key | Possible values | Description | Available from version |
---|---|---|---|
SOAP.MONITORING.ENABLE_RATOR_MONITORING_HANDLER | T/F |
|
|
SOAP.MONITORING.ENABLE_XML_PERSISTENCY | T/F |
|
|
SOAP.MONITORING.OBJ_ID_KEY.<HookpointKeyName> | <Key name for Request XML Element whose value should be saved to the OBJECT_ID column of the SOAP_MONITORING table> | A generic request object value can be saved to the SOAP_MONITORING table into the new column called OBJECT_ID by configuring this parameter tree entry with the key name of the Element to be saved. So, it is possible to save a different object_id values for different soap hookpoints by configuring parameter entries with corresponding key name. Note that it is not possible to save ComplexValueDTO object values in this column OBJECT_ID. Only simple object type value can be saved. i.e the key name provided in the parameter tree entry must correspond to a request XML element of simple ValueDTO type (String/Boolean/Long/Date/Double) , not a ComplexValueDTO type. | 2.16-SNAPSHOT |
SOAP.VALIDATION.IS_ENABLED |
...
Y/N |
...
|
| |
SOAP.VALIDATION.PATH_TO_XMLS |
...
| Any path on a HDD where the application is deployed |
| |
SOAP.VALIDATION.CACHE_ENABLED |
...
Y/N |
...
Sets |
...
if |
...
caching |
...
of |
...
validation |
...
XML |
...
files |
...
is |
...
enabled. |
...
If |
...
parameter |
...
is |
...
not |
...
present, |
...
caching |
...
is |
...
enabled |
...
2.8 |
...
SOAP.WORKFLOW.AUTHENTICATION.ENABLED |
...
Y/N |
...
|
| |
SOAP.WORKFLOW.AUTHENTICATION.HOOKPOINT_KEY |
...
| Authentication/Role |
...
management |
...
workflow |
...
hookpoint |
...
key |
|
SOAP.WORKFLOW.AUTHENTICATION.ADAPTER |
...
| Optional class name to handle authentication process |
| |
BRAND.DEFAULT_ENABLED |
...
Y/N |
...
When |
...
enabled, |
...
workflows |
...
started |
...
by |
...
workflow |
...
SOAP |
...
will |
...
have |
...
brand |
...
in |
...
the |
...
context. |
...
|
...
default |
...
brand |
...
is |
...
based |
...
on |
...
the |
...
brand_key |
...
from |
...
the |
...
properties.txt |
...
file |
...
2.14 |
...
If you set the parameter SOAP.MONITORING.ENABLE_RATOR_MONITORING_HANDLER to T, then the framework monitoring handler will try to store the log record in the SOAP_MONITORING table. If there is no such table , then you might use the following script to create one: {
Code Block |
---|
...
|
...
|
...
CREATE TABLE SOAP_MONITORING
(
ID NUMBER NOT NULL,
CREATE_DATE DATE,
WEB_SERVICE_NAME VARCHAR2(200 BYTE),
WEB_METHOD_NAME VARCHAR2(200 BYTE),
ELAPSED NUMBER,
SERVICE_OUTCOME NUMBER,
REQUEST_XML CLOB,
RESPONSE_XML CLOB,
ERROR_CODE VARCHAR2(100 CHAR),
ERROR_MESSAGE VARCHAR2(200 CHAR),
HOOKPOINT_KEY VARCHAR2(100 CHAR)
);
ALTER TABLE SOAP_MONITORING ADD (PRIMARY KEY (ID)); |
...
If you want to store the SOAP request/response XML documents in the fields SOAP_MONITORING.REQUEST_XML and SOAP_MONITORING.RESPONSE_XML then you have to set the parameter SOAP.MONITORING.ENABLE_XML_PERSISTENCY to T.
If you want to enable the SOAP request validation using XML validation files, then you have to set the parameter SOAP.VALIDATION.IS_ENABLED to Y and specify the path to the location of the validation XML files using the parameter SOAP.VALIDATION.PATH_TO_XMLS. *
Note:* Recent versions of this framework support loading XML files from a specific folder in CLASSPATH called SOAP_XML, e.g.: *
- <...>/Tomcat/webapps/your-soap-application/WEB-INF/classes/SOAP_XML
...
SOAP workflow framework is also capable of handling client authentication if the parameter SOAP.WORKFLOW.AUTHENTICATION.ENABLED is set to Y. h4. Client Authentication If the parameter
Client Authentication
If the parameter SOAP.WORKFLOW.AUTHENTICATION.ENABLED is set to Y, then the framework will try to launch the authentication process for the client. The authentication process may be configured by specifying the SOAP.WORKFLOW.AUTHENTICATION.ADAPTER parameter. This parameter is optional and if it is not defined, the framework will use the internal default value, which is 'WORKFLOW'. WORKFLOW maps to WorkflowAdapter class which is responsible for invoking the authentication workflow. When using WorkflowAdapter, you have to specify mandatory parameter SOAP.WORKFLOW.AUTHENTICATION.HOOKPOINT_KEY which will point to a specific authentication workflow.
The Context of the authentication workflow will be all elements found in the CONTEXT section plus the HookpointKey element. New elements can (e.g. a password) can be added to the CONTEXT for extended authentication.
After you have designed your workflow and specified hookpoint keys, then you might start calling the service and invoking the workflows.
The most basic request structure should include the elements specified in the following table: *
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. | The example SOAP request for this structure would look like: {code:language=html/xml}
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. |
The example SOAP request for this structure would look like:
Code Block | ||
---|---|---|
| ||
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:executeMethod xmlns:ns2="http://soap.CDRator.com/">
<arg0>
<hookpointKey>YOUR_HOOKPOINT_KEY</hookpointKey>
<values xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:complexValueDTO">
<key>CONTEXT</key>
<value xsi:type="ns2:stringValueDTO">
<key>LANGUAGE</key>
<value>EN</value>
</value>
<value xsi:type="ns2:stringValueDTO">
<key>OPERATOR</key>
<value>eka</value>
</value>
</values>
</arg0>
</ns2:executeMethod>
</S:Body>
</S:Envelope> |
...
If you try to make the call to InvokerServer using this request, the framework should start the workflow that has the provided hookpoint key. {
Note |
---|
...
For |
...
every |
...
hookpoint |
...
key |
...
you |
...
call, |
...
you |
...
will |
...
have |
...
to |
...
provide |
...
the |
...
validation |
...
XML |
...
file |
...
with |
...
the |
...
same |
...
name |
...
as |
...
the |
...
hookpoint |
...
key |
...
. |
...
That |
...
means |
...
that |
...
if |
...
you |
...
want |
...
to |
...
invoke |
...
the |
...
workflow |
...
with |
...
the |
...
hookpoint |
...
key |
...
'YOUR_HOOKPOINT_KEY', |
...
then |
...
there |
...
should |
...
be |
...
a |
...
validation |
...
XML |
...
for |
...
this |
...
call |
...
named |
...
<path_to_xml_files>/YOUR_HOOKPOINT_KEY.xml. |
...
Validation XML Structure
One of the basic validation XMLs could look like this:
Code Block | ||
---|---|---|
| ||
<?xml version="1.0" encoding="UTF-8"?>
<soapcall>
<request>
<hookpointKey>SOAP_CREATE_PAYMENT</hookpointKey>
<values>
<value mandatory="true" type="c" key="CONTEXT" desc="Context object, mandatory in each request.">
<values>
<value mandatory="true" type="s" key="LANGUAGE" regexp="[A-Z]{2}" desc="Language code. EN, FR, DK, SE, etc. Used for displaying error messages." />
<value mandatory="true" type="s" key="OPERATOR" regexp="[a-z]{2,10}" desc="Operator information." />
<value type="s" key="BRAND_ID" desc="Id of the brand if applicable." />
</values>
</value>
<value mandatory="true" type="c" key="ACCOUNT_PAYMENT" class="com.CDRator.billing.financial.AccountPayment" desc="The account payment to store.">
<values>
<value mandatory="true" type="l" key="AMOUNT" desc="Amount paid." />
<value mandatory="true" type="d" key="PAYMENT_DATE" desc="Date of the payment." />
<value mandatory="true" type="s" key="REFERENCE" desc="Payment reference." />
<value type="b" key="IS_VALID" />
</values>
</value>
</values>
</request>
<response>
<values>
<value type="s" key="PAYMENT_ID" />
</values>
</response>
</soapcall> |
...
As appears, it includes the hookpoint key and the value structure definition as well as what values will be returned in the SOAP response document.
There are 6 possible data types to describe the structure of the data.
c - ComplexValueDTO
s - StringValueDTO
b - BooleanValueDTO
d - DateValueDTO
f - DoubleValueDTO
l - LongValueDTO
All data types except the ComplexValueDTO are basic, atomic data types and are specified with the following tag: {
Code Block |
---|
...
|
...
|
...
<value mandatory="true|false" type="s|d|l|b|f" regexp="[pattern if any]" key="VALUE_KEY" desc="Provide a brief description."/> |
...
There are also some special cases with Amount object and enums. When enum is set on StringValueDTO as a value then the framework will try to apply enum.toString() to get the value of the enum. Amount objects can be wrapped using StringValueDTO, DoubleValueDTO and LongValueDTO. THe framework will call appropriate conversion methods (toString, longValue, etc.) for each DTO when converting Amount object.
The ComplexValueDTO must have a class key that specifies what kind of object is passed to the request. It may also have a list of values, those are the object attributes and can be any kind of data type. Example tag structure: {
Code Block |
---|
...
|
...
|
...
<value mandatory="true|false" type="c" key="VALUE_KEY" class="fully qualified class name, e.g.: com.example.Dummy" desc="A brief description if any.">
<values>
<value mandatory="true|false" type="s|d|l|b|f|c" regexp="[pattern if any]" key="VALUE_KEY" desc="Provide a brief description."/>
...
<value>...</value>
</values>
</value> |
...
Attributes that describe the data structure and the constraints: *
- mandatory
...
- -
...
- element
...
- is
...
- mandatory
...
- in
...
- the
...
- request
...
- if
...
- this
...
- attribute
...
- =
...
- "true"
...
- key
...
- -
...
- key
...
- of
...
- the
...
- element
...
- regexp
...
- -
...
- regular
...
- expression,
...
- which
...
- could
...
- be
...
- used
...
- to
...
- validate
...
- string
...
- input
...
- parameters
...
- desc
...
- -
...
- description,
...
- used
...
- for
...
- generating
...
- the
...
- documentation
...
- from
...
- XML.
...
- If
...
- it
...
- is
...
- missing,
...
- the
...
- description
...
- in
...
- the
...
- documentation
...
- will
...
- be
...
- created
...
- from
...
- the
...
- KEY
...
- class
...
- -
...
- class
...
- name,
...
- can
...
- be
...
- specified
...
- for
...
- complex
...
- values.
...
- If
...
- it
...
- is
...
- specified,
...
- the
...
- instance
...
- of
...
- the
...
- class
...
- will
...
- be
...
- created
...
- and
...
- passed
...
- to
...
- the
...
- workflow
...
- instead
...
- of
...
- the
...
- hash
...
- table.
...
- Setters
...
- will
...
- be
...
- used
...
- to
...
- set
...
- the
...
- values,
...
- and
...
- the
...
- names
...
- of
...
- the
...
- method
...
- is
...
- generated
...
- from
...
- the
...
- key.
...
- If
...
- the
...
- key
...
- cannot
...
- be
...
- used
...
- for
...
- this
...
- purpose,
...
- additional
...
- attribute
...
- ("setter")
...
- has
...
- to
...
- be
...
- specified
...
- setter
...
- -
...
- used
...
- for
...
- specifying
...
- the
...
- setter
...
- method
...
- name
...
- in
...
- case
...
- it
...
- cannot
...
- be
...
- generated
...
- from
...
- the
...
- key
...
- (for
...
- the
...
- complex
...
- objects
...
- which
...
- should
...
- be
...
- translated
...
- to
...
- CDRator
...
- objects
...
- automatically)
...
- method
...
- -
...
- used
...
- for
...
- specifying
...
- the
...
- getter
...
- method
...
- name
...
- in
...
- case
...
- it
...
- cannot
...
- be
...
- generated
...
- from
...
- the
...
- key
...
- (for
...
- the
...
- cases
...
- when
...
- in
...
- response
...
- CDRator
...
- objects
...
- should
...
- be
...
- translated
...
- to
...
- ComplexObjectDTO
...
- automatically)
...
- list
...
- -
...
- attribute
...
- of
...
- the
...
- complex
...
- object,
...
- if
...
- =
...
- "true",
...
- complex
...
- object
...
- is
...
- translated
...
- to
...
- array
...
- list,
...
- valid
...
- both
...
- in
...
- request
...
- and
...
- response.
...
- convertToAmount
...
- -
...
- attribute
...
- that
...
- can
...
- be
...
- set
...
- on
...
- StringValueDTO,
...
- LongValueDTO
...
- and
...
- DoubleValueDTO
...
- (types:
...
- "l",
...
- "f"
...
- and
...
- "s")
...
- to
...
- convert
...
- the
...
- current
...
- value
...
- element
...
- to
...
- Amount
...
- object.
...
Take a look at the ACCOUNT_PAYMENT object definition above to get an idea of how the object validation is organized. *
Note:* If you make validation for nested complex types, then those objects and their attributes will be validated recursively. This gives a lot of flexibility and freedom to your service layer, but if you need to make some kind of very specific validation, e.g. you want to check whether key A is set and has a value only if key B equals to TRUE. This is a limitation of the framework and should be implemented in the workflow as this is more business logic related validation rather than data structure related.
After the validation XML file is created and being used by the framework, the validation utility will expect the workflow context to have the described data types. If any of the described keys are missing or fail to pass validation, then the framework will return the SOAP response with the corresponding error message.
The section which describes the message response (the response tag) tells the framework to look for the specified keys in the workflow context and return the corresponding values in the SOAP response message. This means that in designing your workflows make sure that the keys you have specified are present in the workflow context, before the workflow execution is finished. h5. Transformation You may have noticed that the validation xml example above contains a response element. This is used to configure transformation of complex objects (lists and persistent objects) on the workflow context to simple value DTO's that can be added to the response. The example below will transform an arraylist of productconfig objects to a response xml including the id and product code as string value elements. It also transform the product field of the product config to a child element containing the id and description for that product. {code}
Transformation
You may have noticed that the validation xml example above contains a response element. This is used to configure transformation of complex objects (lists and persistent objects) on the workflow context to simple value DTO's that can be added to the response.
The example below will transform an arraylist of productconfig objects to a response xml including the id and product code as string value elements. It also transform the product field of the product config to a child element containing the id and description for that product.
Code Block |
---|
<response>
<values>
<value type="c" key="PRODUCT_CONFIGS" list="true">
<values>
<value type="c" key="PRODUCT_CONFIG" class="com.CDRator.billing.product.ProductConfig">
<values>
<value type="s" key="ID"/>
<value type="s" key="PRODUCT_CODE"/>
<value type="c" key="PRODUCT" class="com.CDRator.billing.main.Product">
<values>
<value type="s" key="ID"/>
<value type="s" key="DESCRIPTION"/>
</values>
</value>
</values>
</value>
</values>
</value>
</values>
</response>
|
...