SOAP Workflow Reference Documentation
General
What is a Customer in Rator
A customer in Rator is a complex structure consisting of an account with a number of users, billing groups and subscriptions.
Basically, a user object represents a person or a company including address details, email address, personal Id etc. A User object can be used to represent ownership of an account, billing groups and subscriptions as well as to represent a billing address or a delivery address. Multiple Users objects associated with one account.
An Account must have at least one billing group. The billing group represents financial information such as a monetary balance, currency, billing cycle, payment details etc.
When a customer subscribes to a product, a subscription is created. The subscription has information such a start date, sales channel/sales rep, user of subscription (link to a Users object). A Subscription always has a Service which is the object where information such as phone number and device info is stored.
A simple customer consists of:
- One Account
- One User
- One Billing Group
- One Subscription
- One Service
See diagram:
Account
An account is the primary entity in the Rator system. Customers cannot exist in the system without an account.
An account:
- has only one account owner (this person is legally responsible for paying the invoices)
- has one or more users
- has one or more subscriptions, with relevant services
- has one or more billing groups.
The account contains information that applies to all users, subscriptions and billing groups within that account, e.g. whether the account is private or corporate, who is the customer's contact or sales agent.
Click /wiki/spaces/NWRARSDEPRECATED/pages/113422732 for more information about the Account tab.
Billing Group
A Billing Group is a simple group of subscribers within an account. The process of creating an invoice or handling the balance is done at Billing Group level. A Billing Group can be a postpaid, a prepaid cash card billing group, or an advanced prepaid billing group, respectively.
The Billing Group:
- can have one or more subscriptions.
- may not have a subscription, that already is linked to another billing group.
- has one owner to whom the bill is sent.
- can have one alert group.
The Billing Group can contain the following information:
- a name for the Billing Group which is a unique identifier within the account and can be perceived as a kind of “sub-account” identifier.
- credit information
- information about to whom to send the invoice.
- discount information
- information about manual fees
- information of the price plan history of the group members/subscriptions
An example of a Billing Group setup could be a small firm wishing to keep invoices separate for, e.g. Sales, Administration and Development, i.e. creating a Billing Group for each department.
For more information about the Billing Group tab, click /wiki/spaces/NWRARSDEPRECATED/pages/113422546.
Subscription
An account may contain a number of subscriptions. A subscription is usually a setup where a customer must pay a subscription price to have access to the product/service that a company sells. A subscription sells periodical, i.e. monthly, annual, or seasonal use or access to a product or service.
A subscription:
- has one user
- can be linked to one billing group
- can have one or more related services
- can have one rate plan.
The subscription list can contain the following information:
- Type of product/service
- status of the subscription (active, terminated etc.)
- start date and end date
- usage if the usage of the product/service is monitored
- details about the subscription, e.g. rate plan and add-on services.
Examples:
Industries can use a model with multiple subscriptions on one account include book clubs, record clubs, telephone companies, cable television providers, cell phone companies, internet providers, pay-TV channels, software providers, business solutions providers, financial services firms, fitness clubs, and pharmaceuticals, as well as the traditional newspapers and magazines.
For more information about the subscription tab, see /wiki/spaces/NWRARSDEPRECATED/pages/113422560.
User
One or several users can be attached to an account. The user is a person or a company with an address and other personal information.
A user:
- can be linked to one or more billing groups
- can be linked to one or more subscriptions
- can exist on one or more times on one account
- can exist on one or more accounts.
- can be linked to the account as an owner and be legally responsible for the overall account.
The user can have the following information:
- Name, address
- Personal or Company ID
- Contact information
For more information about the user window, see /wiki/spaces/NWRARSDEPRECATED/pages/113422778.
How the API Works
This document briefly describes usage of the SOAP workflow framework when developing a service consumer.
The below diagram illustrates how the SOAP calls can be implemented using workflow inProcess functionality:
The structure of the Request and Response is presented in the image below.
The SOAP layer remains unchanged for all SOAP calls, and each type of SOAP call is associated with the corresponding inProcess workflow.
RequestDTO contains the hookpointKey which identifies the associated workflow and array of ValueDTO objects. Each ValueDTO object contains the KEY and VALUE. Depending on the subclass used, VALUE can be long, String, double, Data or an array of ValueDTO objects.
The SOAP layer transforms the array of ValueDTO objects into the hash table of context objects with the corresponding keys provided in the request and starts the workflow with the hookpointKey provided in the request.
After the workflow is executed, the hash table with the result objects is passed back to the SOAP layer, which performs the transformation of the result hash table to ResponseDTO object, which is returned as a result of the SOAP call.
Getting Started
The first thing to do is to check the service end-point description page and WSDL document using the provided end-point address.
Usually the address 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 should display something like this:
and when it is attempted to access the WSDL location, the valid WSDL document should be displayed.
When you have the WSDL document, you can start generating the DTO classes. Many programming languages have their own tools for class generation from WSDL.
One of the easiest ways to do this in Java is to use JAX-WS and Maven with a plugin called jaxws-maven-plugin.
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:
<?xml version='1.0' encoding='UTF-8'?><!-- Published by JAX-WS RI at http://jax-ws.dev.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://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/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> <xsd:import namespace="http://soap.CDRator.com/" schemaLocation="definition.xsd"/> </xsd:schema> </types> <message name="executeMethod"> <part name="parameters" element="tns:executeMethod"/> </message> <message name="executeMethodResponse"> <part name="parameters" element="tns:executeMethodResponse"/> </message> <portType name="InvokerService"> <operation name="executeMethod"> <input wsam:Action="http://soap.CDRator.com/InvokerService/executeMethodRequest" message="tns:executeMethod"/> <output wsam:Action="http://soap.CDRator.com/InvokerService/executeMethodResponse" message="tns:executeMethodResponse"/> </operation> </portType> <binding name="InvokerServicePortBinding" type="tns:InvokerService"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <operation name="executeMethod"> <soap:operation soapAction=""/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> </binding> <service name="InvokerService"> <port name="InvokerServicePort" binding="tns:InvokerServicePortBinding"> <soap:address location="http://localhost:8080/simyo-workflow-soap/InvokerService"/> </port> </service> </definitions>
<?xml version='1.0' encoding='UTF-8'?> <!-- Published by JAX-WS RI 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> <xs:element name="arg0" type="tns:requestDTO" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:complexType name="requestDTO"> <xs:sequence> <xs:element name="hookpointKey" type="xs:string" minOccurs="0"/> <xs:element name="values" type="tns:valueDTO" nillable="true" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="valueDTO" abstract="true"> <xs:sequence> <xs:element name="key" type="xs:string" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:complexType name="dateValueDTO"> <xs:complexContent> <xs:extension base="tns:valueDTO"> <xs:sequence> <xs:element name="value" type="xs:dateTime" minOccurs="0"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="complexValueDTO"> <xs:complexContent> <xs:extension base="tns:valueDTO"> <xs:sequence> <xs:element name="value" type="tns:valueDTO" nillable="true" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="stringValueDTO"> <xs:complexContent> <xs:extension base="tns:valueDTO"> <xs:sequence> <xs:element name="value" type="xs:string" minOccurs="0"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="longValueDTO"> <xs:complexContent> <xs:extension base="tns:valueDTO"> <xs:sequence> <xs:element name="value" type="xs:long"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="doubleValueDTO"> <xs:complexContent> <xs:extension base="tns:valueDTO"> <xs:sequence> <xs:element name="value" type="xs:double"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="booleanValueDTO"> <xs:complexContent> <xs:extension base="tns:valueDTO"> <xs:sequence> <xs:element name="value" type="xs:boolean"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="executeMethodResponse"> <xs:sequence> <xs:element name="return" type="tns:responseDTO" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:complexType name="responseDTO"> <xs:sequence> <xs:element name="errorCode" type="xs:long"/> <xs:element name="errorMessage" type="xs:string" minOccurs="0"/> <xs:element name="status" type="xs:long"/> <xs:element name="values" type="tns:valueDTO" nillable="true" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </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:
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 = new RequestDTO(); request.setHookpointKey(YOUR_HOOKPOINT_KEY); StringValueDTO language = new StringValueDTO(); language.setKey(LANGUAGE_KEY); language.setValue(LANGUAGE_EN); StringValueDTO operator = new StringValueDTO(); language.setKey(OPERATOR_KEY); language.setValue(OPERATOR_DUMMY); ComplexValueDTO context = new ComplexValueDTO(); context.setKey(CONTEXT_KEY); context.getValue().add(language); context.getValue().add(operator); request.getValues().add(context); 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:
private static final String ROOT_KEY = "ROOT"; private static final String CHILD_ONE_KEY = "CHILD_ONE"; private static final String SUB_CHILD_ONE_KEY = "SUB_CHILD_ONE"; private static final String SUB_CHILD_TWO_KEY = "SUB_CHILD_TWO"; private static final String DUMMY_KEY = "DUMMY"; private static final String DUMMY_VALUE = "DUMMY" <...> public void doSomething() { <...> StringValueDTO dummy = new StringValueDTO(); dummy.setKey(DUMMY_KEY); dummy.setValue(DUMMY_VALUE); ComplexValueDTO subChildOne = new ComplexValueDTO(); subChildOne.setKey(SUB_CHILD_ONE_KEY); subChildOne.getValue().add(dummy); ComplexValueDTO subChildTwo = new ComplexValueDTO(); subChildTwo.setKey(SUB_CHILD_TWO_KEY); subChildTwo.getValue().add(dummy); ComplexValueDTO childOne = new ComplexValueDTO(); childOne.setKey(CHILD_ONE_KEY); childOne.getValue().add(subChildOne); childOne.getValue().add(subChildTwo); ComplexValueDTO root = new ComplexValueDTO(); context.setKey(ROOT_KEY); context.getValue().add(childOne); <...> } <...>
This becomes useful when you have to transfer some kind of very complex object and pass it to the workflow framework.