Oracle SOA 11g – BPEL 1.1 to BPEL 2.0 Upgrade

In my current project we were using BPEL 1.1 processes. Then SOA Suite 11gR1PS3 came along and gave use BPEL 2.0. So, we decided to start upgrading our already build BPEL 1.1 processes to version 2.0 for making it a standard implementation considering future enhancements.

As there are no BPEL 2.0 upgrade tools we had basically two options. The first was to complete rebuild all our processes. Not a very good option to redo all the work. The second option was to manually upgrade the BPEL 1.1 definitions to 2.0. Expecting this to be less work we choose the second option.

Step by Step Process:-

  1. Open the 11g migrated Composite in the JDeveloper and goto BPEL source File,  And then change the BPEL namespace just like below:
            Then add the below namespace after the xmlns,
             xmlns:bpel="http://docs.oasis-open.org/wsbpel/2.0/process/executable"
  1. In the Composite.xml, open the source and add the composite version for the BPEL component as below:
                <component name="bpelprocessname" version="2.0">             
  1. Finally close JDeveloper, delete the SCA-INF directory and restart JDeveloper. The SCA-INF was created again. When opened the bpel process in the editor it was recognized as a BPEL 2.0 process

            

Now, when you rebuild, you can see lot of errors.
  1. Assign Activity (Xpath to XSL):-
The assignment (assign activity) has a major shift in BPEL 2.0. In BPEL 1.1 the assignments were based on XPath but in BPEL 2.0 the assignments are based on XSL notation. Change all the Assign activities like below either changing the Source file (if you are comfortable with XSL & XPATH) or using the BPEL designer.

BPEL 1.1 assign activity looks like:

<assign name="Assign1">
  <copy>
    <from variable=”inputVariable” part=”payload” query=”ns2:/StartRequest/ns2:procesId”/>
    <to variable=”start_InputVariable” part=”payload” query=”/ns6:/Parameters/ns6:procesId”/>
  </copy>
  <copy>
    <from expression=”concat(bpws:getVariableData(‘inputVariable’,’in’,’ns2:/StartRequest/ns2:procesId’,’ tmp’))/>
    <to variable=”tempvalue” />
  </copy>
</assign>

BPEL 2.0 assign activity would be a XSL notation and it looks like:

<assign>
  <copy>
    <from>$inputVariable.payload/ns2:procesId</from>
    <to>$start_InputVariable.payload/ns6:procesId</to>
  </copy>
  <copy>
    <from>concat($inputVariable.in/ns2:procesId,’tmp’)</from>
    <to>$tempvalue</to>
  </copy>
</assign>

Note:-
First open the assign editor for all assignments and closed it again (press ok). If you look at the source before and after, you will notice the contents of the variable and part attribute have been moved to the correct location. The expression and query attribute have not been moved and are still there. You will have to do this yourself. Add them to the variable but remove the first level of the xpath as it is no longer needed.


  1. Assign Activity (XML fragment):-
IF you have assigned a XML fragment to a variable you need to do the following. Enclose the fragment inside a <literal> element.

BPEL 1.1 assign activity looks like:
<assign>
   <copy>
      <from>
         <result xmlns="http://samples.otn.com">
            <name/>
            <symbol/>
            <price>12.3</price>
            <quantity>0</quantity>
            <approved/>
            <message/>
         </result>
      </from>
      <to variable="output" part="payload"/>
   </copy>
</assign>

BPEL 2.0 assign activity would look like:

<assign>
   <copy>
      <from>
       <literal>
         <result xmlns="http://samples.otn.com">
            <name/>
            <symbol/>
            <price>12.3</price>
            <quantity>0</quantity>
            <approved/>
            <message/>
         </result>
      </literal>
      </from>
      <to>$output.payload</to>
   </copy>
</assign>

  1. Assign Activity (insertBefore, insertAfter, remove):-
Often in BPEL we use BPEL extension functions like insertBefore, InsertAfter, remove. In BPEL 2.0 these extension functions are change a bit and also follow the same XML literal pattern.  For Remove operations just add the entire bpelx inside the element “extensionAssignOperation”. But for insertBefore & insertAfter follow the above pattern as well as XML fragment pattern.
BPEL 1.1 assign activity looks like:

<bpel:assign>
    <bpelx:append>
          <bpelx:from variable="billOfMaterialVar"
                query="/b:bom/b:parts/b:part" />
          <bpelx:to variable="consolidatedBillOfMaterialVar"
                query="/b:bom/b:parts" />
    </bpelx:append>
</bpel:assign>
<bpel:assign>
    <bpelx:remove>
       <bpelx:target variable="ncname" part="ncname" query="xpath_str" />
    </bpelx:remove>
</bpel:assign>
<bpel:assign>
    <bpelx:insertBefore>
        <bpelx:from>
             <a:city>Redwood Shore></a:city>
        </bpelx:from>
        <bpelx:to "addrVar" query="/a:usAddress/a:state" />
    </bpelx:insertBefore>
</bpel:assign>
<bpel:assign>
    <bpelx:insertAfter>
        <bpelx:from>
             <a:addressLine>Mailstop 1op6</a:addressLine>
        </bpelx:from>
        <bpelx:to "addrVar" query="/a:usAddress/a:addressLine[1]" />
    </bpelx:insertAfter>
</bpel:assign>

BPEL 2.0 assign activity would look like:

<bpel:assign>
   <bpelx:append>
      <bpelx:from>$billOfMaterialVar/b:parts/b:part</bpelx:from>
      <bpelx:to>$consolidatedBillOfMaterialVar/b:parts</bpelx:from>
   </bpelx:append>
</bpel:assign>
<assign>
   <extensionAssignOperation>
      <bpelx:remove>
         <bpelx:target>$ncname.ncname/xpath_str</bpelx:target>
      </bpelx:remove>
   </extensionAssignOperation>
</assign>
<assign>
   <extensionAssignOperation>
      <bpelx:insertBefore>
         <bpelx:from>
            <bpelx:literal>
               <a:city>Redwood Shore></a:city>
            </bpelx:literal>
         </bpelx:from>
         <bpelx:to>$addrVar/a:state</bpelx:to>
         </bpelx:insertBefore>
   </extensionAssignOperation>
</assign>
<assign>
   <extensionAssignOperation>
      <bpelx:insertAfter>
         <bpelx:from>
            <bpelx:literal>
               <a:addressLine>Mailstop 1op6</a:addressLine>
            </bpelx:literal>
         </bpelx:from>
                     <bpelx:to>$addrVar/a:addressLine[1]</bpelx:to>
      </bpelx:insertAfter>
   </extensionAssignOperation>
</assign>
                    BPEL designer screen for changing these, 
 
  1. JAVA embedding (bpelx:exec & import):-
Sometimes, in our BPEL we import java classes to utilize those functions on the java embedding object.  And also for regular java embedding activity, enclose the Embedded Java activity element (bpelx:exec) by the extensionActicity element and removed the version attribute.
BPEL 1.1 java exec import:-
                <bpelx:exec import="org.w3c.dom.Element"/>

                <bpelx:exec name="evaluateCriteria" language="java" version="1.3">
                                        <![CDATA[// initialize ]]>
                </bpelx:exec>

BPEL 2.0 java exec import is changed to a process level import using the java extension:- This import should be specified at the top of the BPEL, just after the “<process>” element
            <import importType="http://schemas.oracle.com/bpel/extension/java" location="org.w3c.dom.Element"/>

                                <extensionActivity>
                                    <bpelx:exec name="evaluateCriteria" language="java">
                                        <![CDATA[// initialize ]]>
                                    </bpelx:exec>
                                    </extensionActivity>


  1. Switch & Case:-
The switch activity has been replaced by if activity, which is just like our Java language.
·         Just rename the switch to if
·         Make the condition attribute of the first case element a child element of the if element and change it’s xsl variable format (see earlier)
·         All other Case elements become elseif’s. For the condition the same applies as explained before
·         Otherwise becomes else

BPEL 1.1 Switch & Case activity looks like:

<switch name="switch-1">
     <case condition="bpws:getVariableData('loanOffer1','payload', '/autoloan:loanOffer/autoloan:APR') < 10">
          <assign name="selectUnitedLoan">
            <copy>
               <from variable="loanOffer1" part="payload">
               </from>
               <to variable="selectedLoanOffer" part="payload"/>
            </copy>
         </assign>
     </case>
     <case condition="bpws:getVariableData('loanOffer1','payload', '/autoloan:loanOffer/autoloan:APR') > 10">
          <assign name="selectUnitedLoan">
            <copy>
               <from variable="loanOffer1" part="payload">
               </from>
               <to variable="selectedLoanOffer" part="payload"/>
            </copy>
         </assign>
     </case>
     <otherwise>
         <assign name="selectStarLoan">
          <copy>
            <from variable="loanOffer2" part="payload">
            </from>
            <to variable="selectedLoanOffer" part="payload"/>
          </copy>
         </assign>
     </otherwise>
</switch>


BPEL 2.0 Switch & Case activity looks like:

<if name="switch-1">
     <condition>$loanOffer1/autoloan:loanOffer/autoloan:APR < 10</condition>
          <assign name="selectBankLoan">
            <copy>
               <from>$loanOffer1.payload</from>
               <to>$selectedLoanOffer.payload</to>
            </copy>
         </assign>
     <elseif>             
     <condition>$loanOffer2/autoloan:loanOffer/autoloan:APR < 10</condition>
          <assign name="selectUnitedLoan">
            <copy>
               <from>$loanOffer2.payload</from>
               <to>$selectedLoanOffer.payload</to>
            </copy>
         </assign>
     </elseif>
     <else>
         <assign name="selectStarLoan">
            <copy>
               <from>$loanOffer3.payload</from>
               <to>$selectedLoanOffer.payload</to>
            </copy>
         </assign>
     </else>
</if>
  1. The checkpoint element can be replaced by the dehydrate element also enclosed by an extensionActicity element as it is a oracle specific bpel 2.0 extension like the embedded java activity.
  2. The terminate activity just needs to be renamed to exit.
  3. Need to add an additional attribute to the catch element when you are catching faults. This can be a faultMessageType or faultElement. Open the catch fault editor and select the right one.
  4. The until attribute of the BPEL 1.1 Pick/onAlarm element has become a child element in 2.0 and needed to be moved.
  5. Not all annotations <bpelx:annotation> are supported anymore. Comment some of them out for now as they were mainly for documentation purposes only.
  6. Unfortunately the skipCondition attribute is no longer supported.  Its a little disappointment about this although it’s understood why it was removed. This attribute is just not part of the BPEL 2.0 standard. So, we have to add if/then/else constructions to mimic the same.
  7. BPEL 2.0 refactoring:-
Since the BPEL process is upgraded to 2.0 from 1.1, we have some refactoring options also which would be worth doing it.
·         In BPEL 2.0 there is the notation of variable initialization. Where in BPEL 1.1 we needed an additional assign activity to initialize a variable, in 2.0 it can be done as part of the variable definition. So we can make the BPEL process cleaner by moving the initialization to the definition part.
·         The assign activity has some additional functionality: keepSrcElementName (in BPEL 2.0 projects only): Select this option to toggle the keepSrcElementName attribute on the copy rule on and off. This option enables to replace the element name of the destination (as selected by the to-spec) with the element name of the source.
·         Change Rule Type (in BPEL 2.0 projects only): Select this option to change the type of the selected rule to one of the BPEL extension rules: bpelx:copyList, bpelx:insertAfter, bpelx:insertBefore, or bpelx:append.

For six moderate to complex BPEL processes this cost me about a week work. For our project it was not cost effective to automate this. We could have created  an xsl transformation to do parts of the migration. I wonder if you could fully automate this especially the refactoring part.

Ant deployment scripts for Oracle SOA 11g composites - Windows


This blog post provides Ant scripts that simplify the deployment, undeployment, and management of code to Oracle SOA Suite 11g. These scripts are designed for Windows (will release the Linux instructions soon). For those familiar with it, I do not use the configuration plan (long story).

Who these scripts are designed for:

·                     Developers who want an automated approach to deploy/undeploy/manage code
·                     App Admins who want to manage code from a Windows-based operating system

What you can do with the scripts:

·                     Deploy multiple composites using a single Ant command
·                     Undeploy multiple composites using a single Ant command
·                     Start multiple composites using a single Ant command
·                     Stop multiple composites using a single Ant command
·                     List deployed composites
·                     Tokenize and detokenize code
·                     Import artifacts (XSDs, DVMs, WSDLs, fault policies) to the MDS
·                     Export the entire MDS (for backup or browsing purposes)


One-time Setup and Configuration

1. Download
 ant_soa11g_windows.zip from here

2. Unzip
 ant_soa11g_windows.zip to your local c:\ drive (it should exist as c:\ant)

3. Edit
 setEnvironmentVars.bat and modify the following:
CODE_FOLDER  <-- top-level directory where your code exists (e.g., c:\ant\code)
ORACLE_HOME  <-- directory of JDev 11g (e.g., c:\jdev11g)
JAVA_HOME    <-- ensure that the JDK path is correct
4. Edit soa-environment.properties and modify only the following variables:
wn.bea.home=C:/jdev11g              <-- directory of JDev 11g (similar to ORACLE_HOME above)
tmp.output.dir=c:/ant/temp          <-- temp directory for MDS generation, default is c:\ant\temp
local.mds.repository=c:/ant/apps    <-- location of local MDS copy (for MDS imports)
local.mds.export=c:/ant/apps.backup <-- location of local MDS backup folder (for MDS exports)
5. Double-click on winInstall.bat so that it copies the necessary JARs to the appropriate directories

6. For every SOA Suite 11g environment, create the following 3 files.
For example, if you have a DEV, TEST, and PROD environments, then create the following 9 files:
soa-build-dev.properties
soa-build-test.properties
soa-build-prod.properties
soa-cfgplan-dev.xml
soa-cfgplan-test.xml
soa-cfgplan-prod.xml
soa-token-dev.properties
soa-token-test.properties
soa-token-prod.properties
The ant_soa11g_windows.zip file includes samples for a DEV environment, so just make copies of those files for your other environments.
7. Edit all soa-build-*.properties and soa-token-*.properties files and modify the following:
USERNAME    <-- weblogic username (e.g., 'weblogic')
PASSWORD    <-- weblogic password
SOAHOST     <-- hostname or IP address of SOA Suite 11g server
SOAPORT     <-- port for the soa_server1 managed server (e.g., 8001)
DBUSERNAME  <-- MDS database username (e.g., 'dev_mds')
DBPASSWORD  <-- MDS database password
DBHOST      <-- database host
DBPORT      <-- database port
DBSID       <-- database name

Deploy, Undeploy, Start, Stop, and Detokenize Composites

1. Define the
 CustomProcessList.txt (see Define the Custom Process List below)

2. Open a command prompt window and type the following
cd c:\ant
call setEnvironmentVars.bat
call ant -f build.soa.xml  -Dtargetenv=
Where is deployComposites, undeployComposites, startComposites, stopComposites, ordetokenizeComposites. This will loop through and perform the action against all the composites listed in theCustomProcessList.txt file.
Where is your dev, test, or whatever environments you configured earlier.

List Composites

1. Open a command prompt window and type the following
cd c:\ant
call setEnvironmentVars.bat
call ant -f build.soa.xml listComposites -Dtargetenv=
Where is your dev, test, or whatever environments you configured earlier.

Export MDS

1. Open a command prompt window and type the following
cd c:\ant
call setEnvironmentVars.bat
call ant -f build.soa.xml exportMDS -Dtargetenv=
Where is your dev, test, or whatever environments you configured earlier.
2. The export file will be saved to c:\ant\apps.backup in the format of MDSbackup..YYYY-MM-DD-HHMI.jar (e.g.,MDSbackup.dev.2011-01-20_1140.jar)


Import Artifacts to MDS

1. Define the
 CustomMDSList.txt (see Define the Custom MDS List below)

2. Add all the schemas, WSDLs, DVMs, fault policies, to the c:\ant\apps\ directory.
For example:
c:\ant\apps\App1MetaData\dvm\Currency.dvm
c:\ant\apps\App1MetaData\dvm\Country.dvm
c:\ant\apps\App1MetaData\config\fault-bindings.xml
c:\ant\apps\App1MetaData\config\fault-policies.xml
c:\ant\apps\App1MetaData\schemas\shared\Types.xsd
c:\ant\apps\App1MetaData\schemas\hr\Account.xsd
3. Open a command prompt window and type the following
cd c:\ant
call setEnvironmentVars.bat
call ant -f build.soa.xml importMDS -Dtargetenv=
Where is your dev, test, or whatever environments you configured earlier.

Define the Custom Process List

Before using any of these Ant scripts that are related to code, you must create a
 CustomProcessList.txt file.

1. Create the
 c:\ant\CustomProcessList.txt file, using the following format:
,,,,

For example, the file may look like this:
HelloWorld1,default,1.0,true,hrprojects\employees\HelloWorld1
HelloWorld2,default,1.0,true,hrprojects\employees\HelloWorld2
HelloWorld3,hello99,2.0,false,hrprojects\test\synchronize\HelloWorld3
This says that there are 3 composites to loop through; HelloWorld1, HelloWorld2, and HelloWorld3. If deployed, the first 2 will be deployed to the 'default' partition and a revision of '1.0' while the last one will be deployed to the 'hello99' partition with a revision of '2.0'. The last composite will not be set as the default composite, designated by the value of 'false'.
  
 
The directory path shown is relative to the
 %CODE_FOLDER% environment variable set earlier. For example, if%CODE_FOLDER% is set to c:\ant\code, then the three projects above should exist in the following local directories:
c:\ant\code\hrprojects\employees\HelloWorld1
c:\ant\code\hrprojects\employees\HelloWorld2
c:\ant\code\hrprojects\test\synchronize\HelloWorld3

Define the Custom MDS List

Before using any of the Ant targets that are related to the MDS, you must create a
 CustomMDSList.txt file.

1. Create the
 c:\ant\CustomMDSList.txt file, using the following format:
,false

For example, the file may look like this:
App1MetaData,false
App2MetaData,false
If you run the MDS import script, it will import the following local directory to its relative MDS directory as follows:
c:\ant\apps\App1MetaData  -->  oramds:/apps/App1MetaData
c:\ant\apps\App2MetaData  -->  oramds:/apps/App2MetaData
For example, you may have a combination of XSDs, DVMs, and fault policies as shown:  
c:\ant\apps\App1MetaData\dvm\Currency.dvm
c:\ant\apps\App1MetaData\dvm\Country.dvm
c:\ant\apps\App1MetaData\config\fault-bindings.xml
c:\ant\apps\App1MetaData\config\fault-policies.xml
c:\ant\apps\App1MetaData\schemas\shared\Types.xsd
c:\ant\apps\App1MetaData\schemas\hr\Account.xsd
When you run the MDS import script, because the CustomMDSList.txt file is referencing the localc:\ant\apps\App1MetaData directory, all files under that local directory will be imported to the MDS.

Adding Additional Tokens

The
 detokenizeComposites target loops through all code in your CustomProcessList.txt file, and detokenizes your code. For example, if your code has the following string @SOAServer@, the command below will replace it with whatever value is specified in the soa-token-*.properties file. This allows you to not hardcode values in your code.

If you want to add additional token variables, say @SomeEndpoint@, you must do the following:

1. Add the new token to the
 soa-token-*.properties file. For example:
SomeEndpoint = http://dev.ipnweb.com:7777
2. Edit build.soa.xml and add the token in two separate targets (detokenizeComposites and tokenizeComposites):