Friday, September 27, 2013

Apply Authorization Policy to SOA Composite

This blog demonstrates how to use Oracle authorization policy to restrict the access to one SOA composite in Oracle SOA 11g.
In this example SOA composite is consisted of a simple BPEL component which is exposed as Web service. 

In order to protect the SOA composite from unauthorized access Oracle policy oracle/binding_permission_authorization_policy need to be applied the service of the SOA composite.  This policy will ensure that the authenticated subject has the permission to access the resource specified in the policy.  In Oracle the application policy defines the resource to be protected, the permission class which is used to check the permission.  Here the permission class is: oracle.wsm.security.WSFunctionPermission.  The application policy also associates the resource with the application role, user or group. So the only authenticated subject which belongs to the application roles can will be granted to permission to the resource.

The authenticated subject is the entity that has been authenticated.  Thus before the authorization is applied the authentication is needed to apply first.  So the authentication policy oracle/wss_username_token_service_policy is also required.

The user and group are defined in Oracle Weblogic Admin Console and the application policy and application role are defined in Enterprise Manager.  The below diagram shows the the relationship:



Create the User and Group in Oracle Administrator Console
Login into Oracle Weblogic Administrator console.
Go to Security Realm->myrealm->Users and Groups->Users->New

Type in your user name and password and click on OK button.



Go to Security Realm->myrealm->Users and Groups->Groups->New

Type in your group and click on OK button.


Go to Security Realm->myrealm->Users and Groups->Users. Then click on the user: premium and then click on Group tab.



Select the group CustomerManager and add to chosen. 

Click on OK button.

Create the Application Role in Enterprise Manager console

Login into Oracle Enterprise Manager console
Go to Farm_soa_domain->SOA and then right click on soa-infra and choose Security->Application Roles.



Click on Create... and then type in the group information.

In Members click Add...

Change the type as Group and then click Search button.   Select the group: CustomerManager which is defined in Admin Console.  Then click on OK button.


Click on Save button.


Create the Application Policy in Enterprise Manager console

Go to Farm_soa_domain->SOA and then right click on soa-infra and choose Security->Application Policies.


Click on Create... 


Click on Grantee->Add

Search Principal with type as Application Role and select the application role: CustomerManagerRole and then click on OK button.



Click on Permissions->Add

Click on Continue button.  Type in oracle.wsm.security.WSFunctionPermission in Permission Class.
and http://www.toic.com/customer/wsdl/UpdateCustomerService#update in Rescource Name and invoke in Permission Actions.


Click on Select button.



Click on OK button.




Add the policies to the service of SOA composite in JDeveloper

In JDeveloper right click on the service of the SOA composite and choose the menu item Configure WS Policies...



Click on add icon of Security to add 



Choose oracle/binding_permission_authorization_policy and then click on OK button.

Do the same to add the oracle/wss_username_token_service_policy.


Then click on OK button.  

Deploy the SOA composite to the SOA server.


Test the authorization using soapUI

The first message is the one with right user name and password: premium/welcome1 which is set up in Oracle Admin console.


<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cus="http://www.toic.com/customer">
   <soapenv:Header>
         <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
         <wsse:UsernameToken>
            <wsse:Username>premium</wsse:Username>
            <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">welcome1</wsse:Password>
         </wsse:UsernameToken>
      </wsse:Security>
   </soapenv:Header>
   <soapenv:Body>
      <cus:UpdateCustomerRequest>
         <cus:CustomerID>1234567</cus:CustomerID>
      </cus:UpdateCustomerRequest>
   </soapenv:Body>
</soapenv:Envelope>
The SOA composite will be successfully invoked.  The response message comes back correctly without authorization error.

If the user name/password is changed to weblogic/welcome1 which is valid user set up in Oracle Weblogic Admin console.  But this user doesn't belong to the application role which has the permission to invoke the SOA composite in the policy. Now the response message shows that the authorization is not successful.
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
   <env:Header/>
   <env:Body>
      <env:Fault xmlns:ns0="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
         <faultcode>ns0:FailedAuthorization</faultcode>
         <faultstring>FailedAuthorization : failure in authorization</faultstring>
         <faultactor/>
      </env:Fault>
   </env:Body>
</env:Envelope>

Wednesday, August 21, 2013

Use logical directory path in File Adapter

Oracle SOA File adapter provides both physical and logical directory path in configuring File adapter. By its name the physical path is the physical path of the server. Obviously it is not so flexible to use physical path in the design time. Logical path provides advantages over the physical path. Firstly you can deploy the same composite into the various environments where the actual physical path may be different. For example in development environment the path is /u90/uminput while in the production the path is /u100/shared/uminput. Also with logical path you can change the physical path during the runtime without redeployment. 

Set logical path in FILE Adapter Configuration Wizard 

The first step is to select to use logical path when configuring the file adapter as shown in the below. Here XML_FILE_PATH is the logical name of the directory path for the File adapter.



composite.xml 

After the configuration the file adapter using File Adapter Wizard there will one property called XML_FILE_PATH for the service in composite.xml.

cfgplan.xml 

For each environment the different value can be set for the property XML_FILE_PATH in the configuration plan. The value is the actual physical path in the environment.

Enterprise Manager Console 

Also the value for XML_FILE_PATH can be set at runtime by using Enterprise Manager Console as shown in below.



Wednesday, July 17, 2013

File Adapter in Oracle SOA 11g cluster environment

A couple days ago I had an issue with Oracle SOA Adapter in cluster environment.  File Adapter is used as inbound file reader in the composite. It works fine with the development environment which is single node.  The issue is that the file will be read twice, each time by a File Adapter instance on one cluster node.

From the search for the solution of this issue there are two ways to tackle this problem:

1. Use Singleton property for the inbound endppoint for SOA composite.
To enable this just add singletom property to composite.xml.

 
 <service name="InvoiceXMLReader" ui:wsdlLocation="InvoiceXMLReader.wsdl">

    <interface.wsdl interface="http://xmlns.oracle.com/pcbpel/adapter/file/EInvoiceProcessing/InvoiceXMLReader/InvoiceXMLReader#wsdl.interface(Read_ptt)"/>

    <binding.jca config="InvoiceXMLReader_file.jca">

        <property name="singleton">true</property>

    </binding.jca>

  </service>



2. To use HAFielAdapter for File Adapter.

Thus in the .jca fiel change to use eis/HAFileAdapter instead of eis/FileAdapter.

 
<adapter-config name="InvoiceXMLReader" adapter="File Adapter" wsdlLocation="InvoiceXMLReader.wsdl" xmlns="http://platform.integration.oracle/blocks/adapter/fw/metadata">

 

  <connection-factory UIexcludeWildcard="*.tif;*.lock" location="eis/HAFileAdapter" UIincludeWildcard="*.*"/>

  <endpoint-activation portType="Read_ptt" operation="Read">

    <activation-spec className="oracle.tip.adapter.file.inbound.FileActivationSpec">

      <property name="DeleteFile" value="false"/>

      <property name="MinimumAge" value="0"/>

      <property name="PhysicalDirectory" value="/u01/shared/einvoice"/>

      <property name="Recursive" value="true"/>

      <property name="PollingFrequency" value="10"/>

      <property name="IncludeFiles" value=".*\..*"/>

      <property name="UseHeaders" value="false"/>

      <property name="ExcludeFiles" value=".*\.tif;.*\.lock"/>

    </activation-spec>

  </endpoint-activation>

</adapter-config>


Behind HAFileAdapter is the database used as mutex to ensure the one file is only handled by one instance.  By default it uses jdbc/SOADataSource.   When using HAFileAdapter in OSB this jdbc/SOADataSource should also target the OSB server nodes as well.
This also invovles some configuration changes for File Adapter.  You need to set Deployments->File Adapter->Configuration->Outbound Connection Pools->javax.resource.cci.ConnectionFactory->eisHAFileAdapter->controlDir to some shared localtion.

To my understanding the first way is to force to seralize the inbound file processing, which means only one File Adapter is processing a file at one time.   HAFileAdapter is using some mutex to ensure one file is only processed by one FileAdapter instance.  But the multiple HAFileAdapter can process the different file at the same time.  So this is the real solution for high availability environment.

Monday, July 15, 2013

Comparison of XSLT and XQuery

Recently I am working on one project which gets involved in transforming a large XML document in Oracle SOA Suite 11g.  Initially this transformation is done using XSLT.   We did the end-to-end testing with a large payload and noticed that the XSLT transformation took the most of the message processing time.  Later someone suggests that with large payload XQuery is more efficient than XSLT.   So we decided to implement the same transformation using XQuery.   The comparison result is a bit surprise to me.  
  
<ein:ProcessRequest>
 <ein:DocumentID>4.IPM_013407</ein:DocumentID>
 <ein:InvoiceNumber>12345</ein:InvoiceNumber>
 <ein:InvoiceType>PO</ein:InvoiceType>
 <ein:InvoiceDescription>LYRECO JUN 2013</ein:InvoiceDescription>
 <ein:SupplierName>LYRECO PTY LTD</ein:SupplierName>
 <ein:SupplierSiteName>E-INVOICE</ein:SupplierSiteName>
 <ein:POInvoice>
  <ein:POInvoiceItems>
  <ein:InvoiceNo>2331940908</ein:InvoiceNo>
  <ein:Amount>195.42</ein:Amount>
  <ein:GSTAmount>17.77</ein:GSTAmount>
  <ein:InvoiceDate>2013-05-01</ein:InvoiceDate>
  <ein:Description>Some description text</ein:Description>
  <ein:Quantity>1</ein:Quantity>
  <ein:UnitPrice>195.42</ein:UnitPrice>
  <ein:ExpenseType>STATIONERY</ein:ExpenseType>
  <ein:ProjectNumber>200363</ein:ProjectNumber>
  <ein:TaskNumber>11040</ein:TaskNumber>
  <ein:ExpenditureType>Office Supplies</ein:ExpenditureType>
  </ein:POInvoiceItems>
  
  ............
  
 </ein:POInvoice> 
<ein:ProcessRequest> 

Firstly I tried the transformation of a XML message like the above but with over 2700 <POInvoiceItems> elements using XMLSpy.  The result shows XQuery is much faster than XSLT when transforming this message.   Roughly XQuery is 3~4 times faster. 

Then I put these two transformations into one Oracle SOA application respectively and invoke the application with the same large message payload.   The comparison show that under Oracle Weblogic environment there is no obvious difference between XQuery and XSLT and XSLT is even faster than XQuery.   I am not quite sure what cause the different results using XMLSpy and Oracle Weblogic.  Maybe it is related to the implementation of XQuery and XSLT enegines within XMLSpy and Oracle Weblogic.

BigNumber vs Double

Recently I worked on one project which involved using JAXB to generate XML message fro the excel file.   Some data in the file are financial amount and tax amount.  When it is read from the excel it is represented as the floating number.  However in the generated XML message these data occurs to have something like the below:


       <GSTAmount>26.789999999999999999999999999967899</GSTAmount>


In schema GSTAmount is defined as xsd:decimal and the rounding is done before marshaling by JAXB.  I did some serach using Google and learned some tips when dealing with financial amount in Java.


  1. Use BigDecimal rather than double when defining the financial amount.
  2. When using BigDecimal use its string conductor.
Here is the excellent link which explains this issue very clearly. How to Use Java BigDecimal: A Tutorial

Tuesday, June 18, 2013

Use ROWNUM in PL/SQL


  1. ROWNUM is a pseudo column. It acts like a column but it doesn’t exist in a real table. It only exists in the result set returned from a query. 
  2.  ROWNUM numbers the records in a result set. The first record is assigned 1 to ROWNUM and it always starts from 1. Each subsequent record is assigned incrementally. 
  3.  ROWNUM assignment is done after the select statement returns the result set and before the result set is ordered.
Here are some examples that demonstrate how to use ROWNUM correctly.


Example 1: 


select * from pa_tasks where task_name = 'ICT Costs'



This is a normal query which returns the row without order.

Example 2: 

select rownum, TASK_ID, PROJECT_ID, TASK_NUMBER, CREATION_DATE from pa_tasks where task_name = 'ICT Costs'



This is a normal query but with rownum displayed as the part of the result set.
Example 3:
select * from pa_tasks where task_name = 'ICT Costs'   order by task_id;



This is a normal query with ordering by TASK_ID.

Example 4:

select * from pa_tasks where task_name = 'ICT Costs' and rownum <= 3  order by task_id;



This query tries to select the first 3 rows of the result set ordered by TASK_ID.   From the result shown above it doesn’t do what is expected to do.  Because ordering happens after the ROWNUM is assigned.

The correct way is using subquery as shown in example 5.

Example 5:

select * from (select * from pa_tasks where task_name='ICT Costs' order by task_id) where rownum <= 3;


Example 6:

select * from pa_tasks where task_name = 'ICT Costs' and rownum > 3



This query tries to select rows starts from 4.   But unfortunately no records will be selected from the query because rownum > 3 contradicts with rownum must start with 1.   So when using rownum in where clause always use it with “<” or “<=”.

In order to achieve what is expected the correct way to do is use the subquery where rownum is assigned and displayed as the field value.

Example 7:

select * from (select rownum r, TASK_ID, PROJECT_ID, TASK_NUMBER, CREATION_DATE from pa_tasks where task_name = 'ICT Costs') where r > 3



Monday, April 8, 2013

Use preceding-sibling to find all unique elements

Recently I need to write a xpath expression to find all unique elements from one XML message.  The below is the simplified XML document that demonstrate the problem to be solved.  Here I want to get a list of all unique of all a elements.  The of values in the result list should be 123, 120, 129,345 and 340.

<?xml version="1.0" encoding="UTF-8"?>

<!--Sample XML file generated by XMLSpy v2008 sp1 (http://www.altova.com)-->

<db:p>

 <db:ss>

  <db:tt>

   <db:a>123</db:a>

   <db:a>120</db:a>

  </db:tt>

  <db:tt>

   <db:a>123</db:a>

   <db:a>129</db:a>

  </db:tt>

 </db:ss>

 <db:ss>

  <db:tt>

   <db:a>345</db:a>

   <db:a>120</db:a>

   <db:a>123</db:a>

   <db:a>340</db:a>

  </db:tt>

 </db:ss>

</db:p>


After some tries I come out with the following xpath expression.

/*:p/*:ss/*:tt/*:a[ not(. = ../preceding-sibling::*/*:a)  and not(. =  ../../preceding-sibling::*/*:tt/*:a)]

Here I use two preceding-sibling because <a> element is under <ss> and <tt> elements.