Wednesday, December 12, 2012

Approval based user registration process for WSO2 AppFactory


Human-in-the-Loop


 1. User enters information to register in the Appfactory

 2. User gets a notification 'Registration request has been submitted and it's under approval'

 3. Admin logins to the system

 4. Checking the available tasks

 5. User registration request is available in the Claimable Task list (Task is in READY state)


 6. Admin progressing the task (Task moves from READY to IN_PROGRESS state)


 7. Admin performs 'Approve' or 'Reject'  to complete the task


 8. Task moves from IN_PROGRESS to COMPLETED state


Now the task is no longer in Claimable or MyTasks categories. Earlier performed tasks can only be found in AllTasks list.

If the approval is done by the administrator, new user gets an email with login instructions.

In the next post, I'll discuss how this has been implemented using bpel, humantasks and 
jaggery(jaggery UI).

Monday, October 22, 2012

How to secure a BPEL Process

Here we will learn how to secure a BPEL process, so that it can only be accessed by authenticated users. 

In a nutshell, we will,
  • Create and protect a BPEL process by user authentication, the process is exposed as a service which requires providing a username and password inside the UsernameToken of the WS-Security specification.
In tutorial part 1 and 2, we learnt how to create a WS-BPEL process. Now we are going to enable security in that process.

[1] Enable security after the deployment
Add a security scenario (for eg: scenario 1, that is UsernameToken) using the Management Console.

[2] Enable security at the deployment time
This is vital when it comes to securing BPELs. Here we are following a service.xml based approach. The BPEL package contains an additional configuration(xml) file to keep the security policy. A sample BPEL process can be found here.

ServicePasswordCallbackHandler is the default password callbackhandler in Carbon, it  resides in the org.wso2.carbon.security package. If you prefer, you can create your own password callback handler and refer it in the policy configuration, so that it will overwrite the default handler;
<rampart:passwordCallbackClass>org.wso2.carbon.appfactory.pwcb.PWCBHandler</rampart:passwordCallbackClass>


Copy password callback handler jar to BPS_HOME/repository/components/lib directory and restart the server.

              






Invoking WSO2 Carbon Admin Services using BPEL

(1) UEP Approach [Relevant to: BPS 3.0.0]
Add basic auth credentials (username and password) as http headers in unified endpoint configuration.

A sample configuration (.epr) is shown below.

<wsa:EndpointReference
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.w3schools.com uep_schema.xsd"
        xmlns:wsa="http://www.w3.org/2005/08/addressing"
        xmlns:wsdl11="http://schemas.xmlsoap.org/wsdl/">
   <wsa:Address>https://localhost:9443/services/UserRegistrationService</wsa:Address>
   <wsa:Metadata>
           <id>SInvokeEPR</id>
           <transport type="http">
     <authorization-username>admin</authorization-username>
    <authorization-password>admin</authorization-password>
           </transport>
       </wsa:Metadata>
</wsa:EndpointReference>

A Sample is available at [1].


(2) Using a proxy service [Relevant to: BPS 3.0.0 and older (carbon 3.2.* ) versions]
First login to AuthenticationAdmin service and get a authenticated cookie, that cookie value can be used for all subsequent invocations.

  • BPEL process invokes the login method in the AuthenticationAdminProxy service which in turn invokes the backend servers' AuthenticationAdmin service. On the return path, this proxy service retrieves the authenticated cookie and sends to BPEL as value in the SOAP message, so the BPEL can keep this value in a variable.
  • For all the subsequent requests from the BPEL process, it sends this cookie to the corresponding proxy services. These proxy services set the cookie as a HTTP header and invoke the backend service.

Monday, October 15, 2012

Part 2: Developing a WS-BPEL Process using WSO2 Developer Studio


Tutorial 1 is a step by step instruction to implement a bpel process using WSO2 Developer Studio and deploy on WSO2 Business Process Server.

Today with tutorial 2, I am going to develop a BPEL process (let's call it as FunctionProcess) which has multiple service invocations. This is also going to be a synchronous  process as it does not involve any long-lasting operations. If you have already followed-up tutorial 1, then follow up of tutorial 2 is real easy.

The following flowchart illustrates the bpel process that we are going to develop in this tutorial.


Figure 1

This can simply be shown using an equation as follows.

f(x) = [(a * b) - (a + b) ]^2

Now we are going to design it using WSO2 Developer Studio, BPEL editor. 

Here, we have four service invocations, meaning that four Invoke activities such as InvokeMultiplyService, InvokeAdderService, InvokeSubtractService and InvokeSquareService.

Multiply and Adder activities are not depending on each other, or in other words, these activities can be invoked concurrently. So that they will be defined inside a flow activity (<flow/>) as shown in Figure 2.

Figure2
Open the FunctionProcessArtifacts.wsdl and click on the arrow next to FunctionProcessRequest.  Add two integer elements as shown in Figure 3.
Figure 3

Open the FunctionProcessArtifacts.wsdl and click on the arrow next to FunctionProcessResponse. Add resulting integer element.
Figure4

Let's configure four Assign activities. The source is given for each assign activity below, if you need to know how to do this with Developer Studio Graphical Editor, please follow-up tutorial 1.

AssignActivityInputParams Configuration
<bpel:assign validate="no" name="AssignInputParams">
            <bpel:copy>
                <bpel:from>
                    <bpel:literal>
                        <ns:add xmlns:ns="http://demo.carbon.wso2.org" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                            <ns:a>0</ns:a>
                              <ns:b>0</ns:b>
                        </ns:add>
                    </bpel:literal>
                </bpel:from>
                <bpel:to variable="adderPLRequest" part="parameters"></bpel:to>
            </bpel:copy>
            <bpel:copy>
                <bpel:from>
                    <bpel:literal>
                        <ns:multiply xmlns:ns="http://demo.carbon.wso2.org" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                            <ns:a>0</ns:a>
                              <ns:b>0</ns:b>
                        </ns:multiply>
                    </bpel:literal>
                </bpel:from>                
                <bpel:to variable="multiplyPLRequest" part="parameters"></bpel:to>
            </bpel:copy>            
            <bpel:copy>
                <bpel:from part="payload" variable="input">
                    <bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0"><![CDATA[tns:a]]></bpel:query>
                </bpel:from>
                <bpel:to part="parameters" variable="multiplyPLRequest">
                    <bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0"><![CDATA[ns:a]]></bpel:query>
                </bpel:to>
            </bpel:copy>          
            <bpel:copy>
                <bpel:from part="payload" variable="input">
                    <bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0"><![CDATA[tns:b]]></bpel:query>
                </bpel:from>
                <bpel:to part="parameters" variable="multiplyPLRequest">
                    <bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0"><![CDATA[ns:b]]></bpel:query>
                </bpel:to>
            </bpel:copy>
            <bpel:copy>
                <bpel:from part="payload" variable="input">
                    <bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0"><![CDATA[tns:a]]></bpel:query>
                </bpel:from>
                <bpel:to part="parameters" variable="adderPLRequest">
                    <bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0"><![CDATA[ns:a]]></bpel:query>
                </bpel:to>
            </bpel:copy>
            <bpel:copy>
                <bpel:from part="payload" variable="input">
                    <bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0"><![CDATA[tns:b]]></bpel:query>
                </bpel:from>
                <bpel:to part="parameters" variable="adderPLRequest">
                    <bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0"><![CDATA[ns:b]]></bpel:query>
                </bpel:to>
            </bpel:copy>
        </bpel:assign>




 AssignActivity2 Configuration
<bpel:assign validate="no" name="AssignActivity2">
            <bpel:copy>
                <bpel:from>
                    <bpel:literal>
                        <ns:substract xmlns:ns="http://demo.carbon.wso2.org" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                            <ns:a>0</ns:a>
                            <ns:b>0</ns:b>
                        </ns:substract>
                    </bpel:literal>
                </bpel:from>
                <bpel:to variable="subtractPLRequest" part="parameters"></bpel:to>
            </bpel:copy>            
            <bpel:copy><bpel:from part="parameters" variable="multiplyPLResponse">
                    <bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0"><![CDATA[ns:return]]></bpel:query>
                </bpel:from>
                <bpel:to part="parameters" variable="subtractPLRequest">
                    <bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0">
                        <![CDATA[ns:a]]>
                    </bpel:query>
                </bpel:to>            
            </bpel:copy>
            <bpel:copy><bpel:from part="parameters" variable="adderPLResponse">
                    <bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0">
                        <![CDATA[ns:return]]>
                    </bpel:query>
                </bpel:from>
                <bpel:to part="parameters" variable="subtractPLRequest">
                    <bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0">
                        <![CDATA[ns:b]]>
                    </bpel:query>
                </bpel:to>            
            </bpel:copy> </bpel:assign>



 AssignActivity3 Configuration

             <bpel:assign validate="no" name="AssignActivity3"> 
              <bpel:copy>
                <bpel:from>
                    <bpel:literal>
                        <ns:square xmlns:ns="http://demo.carbon.wso2.org" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                            <ns:a>0</ns:a>
                        </ns:square>
                    </bpel:literal>
                </bpel:from>
                <bpel:to variable="squarePLRequest" part="parameters"></bpel:to>
            </bpel:copy>
            <bpel:copy>
                <bpel:from part="parameters" variable="subtractPLResponse">
                    <bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0"><![CDATA[ns:return]]></bpel:query>
                </bpel:from>
                <bpel:to part="parameters" variable="squarePLRequest">
                    <bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0"><![CDATA[ns:a]]></bpel:query>
                </bpel:to>
            </bpel:copy>            
        </bpel:assign>



AssignOutputParams Configuration
      <bpel:assign validate="no" name="AssignOutputParams">
            <bpel:copy>
                <bpel:from>
                    <bpel:literal>
                        <tns:FunctionProcessResponse xmlns:tns="http://wso2.org/bps/sample" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                            <tns:result>0</tns:result>
                        </tns:FunctionProcessResponse>
                    </bpel:literal>
                </bpel:from>
                <bpel:to variable="output" part="payload"></bpel:to>
            </bpel:copy>
            <bpel:copy>
                <bpel:from part="parameters" variable="squarePLResponse">
                    <bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0"><![CDATA[ns:return]]></bpel:query>
                </bpel:from>
                <bpel:to part="payload" variable="output">
                    <bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0"><![CDATA[tns:result]]></bpel:query>
                </bpel:to>
            </bpel:copy>
        </bpel:assign>


Now we have completed, implementation of the business logic  of our work flow.
 
Figure 5

Configuring deployment descriptor(deploy.xml)

This process has 4 service invocations, therefore there should have four partnerlinks in the outbound interface section.

Figure 6

Now we have completed the bpel process development. Let's deploy it on WSO2 BPS and test the flow.
Make sure to deploy four external(partner) services on a AppServer.

Testing the bpel process with TryIt (or with any other testing tool) gives the answer as;
  eg: f(x) = [(4*9) - (4+9)]^2 = 529


Figure 7

Thursday, October 11, 2012

Part 1: Developing a WS-BPEL Process using WSO2 Developer Studio


In this post I'll be discussing following list of items.

What's a BPEL Process?
A BPEL Process is a container where you can declare relationships to external partners, declarations for process data, handlers for various purposes and most importantly, the activities to be executed. 

Let's start with designing a simple workflow.

Create a BPEL process that returns addition of two integer numbers. For the number addition operation the BPEL process invokes an existing service and gets the result from the web service. This web service takes two integers and returns addition of the two integer values. The web service will be hosted on WSO2 AppServer (or else you can use any other appserver).

Figure 1, shows the axis2 service that we are going to invoke via the BPEL process. 
Create the axis2 archive (.aar) [Right click on the AdderService Project --> Export Project as a deployable archive and save it].

Now Start WSO2 AppServer (Goto AppServer_HOME/bin --> sh wso2server.sh)

Deploy AdderService.aar on AppServer.
1. Copy aar file to AppServer_HOME/repository/deployment/server/axis2services directory
      OR
2. Using the AppServer Management Console (Add --> AAR Service --> upload the service archive) 
We need to keep the wsdl file for the AdderService as, that is required later when developing the  BPEL process.

wget http://localhost:9763/services/AdderService?wsdl
Save the AdderService.wsdl to your local file system.

Figure 1

Let's start with designing the BPEL workflow.
Open eclipse which has WSO2 Developer Studio installed. 
Goto Dashboard (Developer Studio --> Open Dashboard menu and click on BPEL Workflow under Business Process Server category)
Figure 2: Create New BPEL Project


Give a project Name, Namespace and select the Template type. As we are going to create a short running bpel process, select the template type as Synchronous.

Synchronous interaction - Suppose a BPEL process invokes a partner service. The BPEL process then waits for the partner service's operation to be completed, and responded. After receiving this completion response from the partner service, the BPEL process will continue to carry on its execution flow. This transmission does not apply for the In-Only operations defined in the WSDL of the partner service.

Usually we'll use asynchronous services for long-lasting operations and synchronous services for operations that return a result in a relatively short time.
Figure 3 

Figure 4

Here you can see the template for our business process. The BPEL editor automatically generates receiveInput and replyOutput activities(Figure 5). Also it will generate partnerLink and variables used in these two activities.

Note: It will automatically generate AdderProcessArtifacts.wsdl and AdderProcess.bpel. If we look at the folder structure of the BPEL process, we can easily figure out these two files.

Figure 5

In our BPEL process we need to invoke an external service which is AdderService. To invoke this service we need to assign the input variables into external service’s input and again the reply from the external service to our BPEL process output. So that, here we need two assign activities and one invoke activity. 

Let’s add an assign activity in between receiveInput and replyOutput activities. To add assign activity drag it from the Action section of the Palette.

Figure 6 : AdderProcess workflow

Before filling the invoke activity, you need to import the AdderService.wsdl to you workflow project. 
Figure 7

Now start implementing the business logic.  
Goto Properties of invoke activity.
Goto 'Details' tab and from the 'Operation' drop down list, select 'Create Global Partner Link'
Figure 8

Give a Partner Link Name and click OK.
Figure 9


Now you'll prompt to the window shown in Figure 10. Click on 'Add WSDL'
Figure 10

Select the WSDL file which you have already imported to the workflow project. Click OK.
Figure 11

In the Partner Link Type window, you should select the correct PortType. then click OK.
Figure 12

Give a name to the Partner Link Type and click Next.
Figure 13


Give a name to the partner role and then select the correct PortType. Now click Finish. We have only one role for this invoke activity. If we have multiple roles (partner roles and my roles, we need to click on Next and create the next role).
Figure 14

Now you need to pick the 'add' operation from the Quick Pick box. For that 'Double' click on it. 
Figure 15


Now you are done with implementing invoke activity. Next step is to implement two assign activities. Before doing that, you need to identify what are the inputs and outputs of your process. We have two integer values as the request parameters and a resulting integer as the response.

Open the AdderProcessArtifacts.wsdl and find the Service, PortType and the binding there. Click on the arrow next to AdderProcessRequest.
Figure 16


Add two integer elements as shown in Figure 17. [To add a element, RightClick --> Add Element] Select the element type as int from the drop down list.
Figure 17


Configure AdderProcessResponse part similarly the above step.
There you need to click on the arrow next to AdderProcessResponse.
Figure 18

For the request, you have only one integer element as the output.
Now save the wsdl file and close it.
Figure 19

Go back to the bpel file and start implementing the first assign activity, that is 'AssignInputVars'.
Goto 'Details' tab and click on 'New'.
Do the mapping as shown in Figure 20.
Figure 20


It will automatically prompt for the initialization. Click on 'Yes'.
Figure 21


Figure 22

Now you are done with configuring the First Assign Activity.
Figure 23


Configure the second assign activity, that is 'AssignoutputVars'. 
Figure 24

Allow for the automatic variable initialization for response.
Figure 25

Now you are done with the bpel process flow design. Now open the deploy.xml (Deployment Descriptor).

Here you can specify the process state (whether it activated, deactivated or retired) after the deployment, set the process executed only in memory, Inbound Interfaces (Service) and Outbound Interfaces (Invokes) etc.

Figure 26

Now make the BPEL process as a deployable archive (Right click on the AdderProcess workflow --> Export Project as a deployable archive).

Start WSO2 Business Process Server (BPS_HOME/bin --> sh wso2server.sh)
Make the port offset to 1 (Change offset to 1 in BPS_HOME/repository/conf/carbon.xml)

Deploy AdderProcess.zip on WSO2 BPS.
1. Copy zip file to BPS_HOME/repository/deployment/server/bpel directory
      OR
2. Using the BPS Management Console (Processes --> Add --> BPEL Archive(zip) --> upload) 

Figure 27

To test the process use TryIt wizard or any other tool(eg: SOAP UI).
Figure 28 : Click on TryIt


Figure 29 : SOAP Request

Figure 30 : SOAP Request/Response 

Here, we get integer (a+b) as the response in the xml output.