Saturday, December 17, 2011

Schematron validation


Schematron is rule-based validation language.  It is different from XML schema validation and it is supplement to XML schema validation.  If required you can apply both of them to the validation of the XML document.

Schematron defines a set of assertions that are to be enforced. If all these assertions are met, the document is seen as valid.

The assertion is specified using XPath.

Schematron has 4 key elements: pattern, assert, rule and ns.

The assert element has an attribute of test whose value is defined as XPath expression. This expression should return a Boolean value. If the test expression evaluates to true, then assertion has been met.

The assert is defined within a rule element.

Multiple asserts may be defined in a rule element. Each rule has a context attribute, which also contains an XPath expression used to specify the nodes to which the asserts will be tested.

The context may return zero, one or more nodes from XML document instance. Each node will be tested against all asserts within this rule.


Here is one example:  We need to validate that the MSISDN should start with 04 and totally has 10 digits and CAC should be numeric.

What we do here is to define one patter in which there are two contexts defined.   The context is using XPath to get the right element in XML document.  One context is for MSISDN element and another for CAC element.  In each element there is one assertion.  The assertion contains the test statement which uses the Regular expression to validate the element value.

<sch:schema xmlns:sch="http://www.ascc.net/xml/schematron">
                <!-- define the process namespace for finding the elements in the rule-->
                <sch:ns uri="http://toic.com/orderManagement/messages/v1" prefix="tns"/>
                <sch:ns uri="http://www.oracle.com/XSL/Transform/java/oracle.tip.pc.services.functions.Xpath20" prefix="xp20"/>
 
                <sch:pattern name="Check the parameters in ExecuteOrdre request">
                                <!-- context is the super variable that can be queried for validation-->
      
                              <!-- Check MSISDN as Identification has validate value -->   
                                <sch:rule context="tns:ExecuteOrderRequest[ xp20:ends-with(@*[local-name()='type'], 'CustomerOrder') ]/tns:Party/tns:PartyRole/tns:Identification[xp20:ends-with(./*[local-name()='Type'], 'MSISDN')] ">
                                                <sch:assert test="xp20:matches( string(tns:Value), '\b04\d{8}\b')">MSISDN should be 10 digit numeric starting with 04</sch:assert>
                                </sch:rule>

                              <!-- Check CAC as Identification has validate value -->   
                                <sch:rule context="tns:ExecuteOrderRequest[ xp20:ends-with(@*[local-name()='type'], 'CustomerOrder') ]/tns:Party/tns:PartyRole/tns:Identification[xp20:ends-with(./*[local-name()='Type'], 'CAC')] ">
                                                <sch:assert test="xp20:matches( string(tns:Value), '\b\d{1,}$')">CAC should be numeric</sch:assert>
                                </sch:rule>

                </sch:pattern>
</sch:schema>



 

Thursday, December 1, 2011

Validate the variable in Oracle BPEL

You can validate one variable against the schema in Oracle BPEL.   

It is done through validate activity from Oracle Extensions.   The BPEL codes will look like the below:




        <validate name="ValidateRequest"
                  variables="RetrieveResourceDetailsRequest"/>


When validation fails the standard fault bpel:invalidVaraible is thrown.   So you need to catch this fault using the following codes:


        <catch faultName="bpel:invalidVariables"> 
                   .... Some activities here
        </catch>

Sunday, November 27, 2011

Deployment issue with Oracle SOA 11g


I found this issue recently when I deployed one SOA application to my local server.   It doesn’t seem to happen all the time but when it happens it causes the deployment error:  Unable to register service.   I don’t know the reason for this problem but I find one way to avoid this problem.
The below example shows when the problem will appear and how the problem can be fixed.   We have one BPEL application which will be exposed as the service: OrderService which is defined in OrderService.wsdl.   This WSDL is not abstract WSDL since it includes the binding and service part.
After creating the service using JDeveloper, JDevloper will create composite.xml and OrderServiceWrapper.wsdl. 
Composite.xml is like the below.   It just shows some key parts for the brevity.  Please note that there are two import statements: one for original OrderService.wsdl and another for OrderServiceWrapper.wsdl.

<?xml version="1.0" encoding="UTF-8" ?>
<!-- Generated by Oracle SOA Modeler version 1.0 at [23/11/11 12:45 PM]. -->
<composite name="CreateOrderService" …>
  <import namespace="http://www.toic.com/esb/wsdl/orderservice"
          location="wsdl/OrderService.wsdl" importType="wsdl"/>
  <import namespace="http://www.toic.com/esb/wsdl/orderservice"
          location="OrderServiceWrapper.wsdl" importType="wsdl"/>
  <service name="CreateOrderService" ui:wsdlLocation="wsdl/OrderService.wsdl">
    <interface.wsdl interface="http://www.toic.com/esb/wsdl/orderservice#wsdl.interface(OrderServicePortType)"/>
    <binding.ws port="http://www.toic.com/esb/wsdl/orderservice#wsdl.endpoint(CreateOrderService/OrderServicePort)">
      <property name="weblogic.wsee.wsat.transaction.flowOption"
                type="xs:string" many="false">NEVER</property>
    </binding.ws>
  </service>
……
</composite>

When it is deployed one deployment error will occur as the following:

[01:16:20 PM] ----  Deployment started.  ----
[01:16:20 PM] Target platform is  (Weblogic 10.3).
[01:16:20 PM] Running dependency analysis...
[01:16:20 PM] Building...
[01:16:23 PM] Deploying profile...
[01:16:23 PM] Updating revision id for the SOA Project 'CreateOrderService.jpr' to '1.0'..
[01:16:23 PM] Wrote Archive Module to D:\JDeveloper\mywork\SOADemo\CreateOrderService\deploy\sca_CreateOrderService_rev1.0.jar
[01:16:23 PM] Deploying sca_CreateOrderService_rev1.0.jar to partition "default" on server AdminServer [http://A00000113011750.wg.dir.telstra.com:7001]
[01:16:23 PM] Processing sar=/D:/JDeveloper/mywork/SOADemo/CreateOrderService/deploy/sca_CreateOrderService_rev1.0.jar
[01:16:23 PM] Adding sar file - D:\JDeveloper\mywork\SOADemo\CreateOrderService\deploy\sca_CreateOrderService_rev1.0.jar
[01:16:23 PM] Preparing to send HTTP request for deployment
[01:16:23 PM] Creating HTTP connection to host:A00000113011750.wg.dir.telstra.com, port:7001
[01:16:23 PM] Sending internal deployment descriptor
[01:16:23 PM] Sending archive - sca_CreateOrderService_rev1.0.jar
[01:16:24 PM] Received HTTP response from the server, response code=500
[01:16:24 PM] Error deploying archive sca_CreateOrderService_rev1.0.jar to partition "default" on server AdminServer [http://A00000113011750.wg.dir.telstra.com:7001]
[01:16:24 PM] HTTP error code returned [500]
[01:16:24 PM] Error message from server:
There was an error deploying the composite on AdminServer: Update Failed: Unable to register service..
 [01:16:24 PM] Check server log for more details.
[01:16:24 PM] Error deploying archive sca_CreateOrderService_rev1.0.jar to partition "default" on server AdminServer [http://A00000113011750.wg.dir.telstra.com:7001]
[01:16:24 PM] ####  Deployment incomplete.  ####
[01:16:24 PM] Error deploying archive file:/D:/JDeveloper/mywork/SOADemo/CreateOrderService/deploy/sca_CreateOrderService_rev1.0.jar
 (oracle.tip.tools.ide.fabric.deploy.common.SOARemoteDeployer)

One way to fix this problem is to remove one import statement from composite.xml.  The import statement that imports the original WSDL will be deleted.   The new composite.xml will be shown as the below:

<?xml version="1.0" encoding="UTF-8" ?>
<!-- Generated by Oracle SOA Modeler version 1.0 at [23/11/11 12:45 PM]. -->
<composite name="CreateOrderService" …>
  <!--import namespace="http://www.toic.com/esb/wsdl/orderservice"
          location="wsdl/OrderService.wsdl" importType="wsdl"/-->
  <import namespace="http://www.toic.com/esb/wsdl/orderservice"
          location="OrderServiceWrapper.wsdl" importType="wsdl"/>
  <service name="CreateOrderService" ui:wsdlLocation="wsdl/OrderService.wsdl">
    <interface.wsdl interface="http://www.toic.com/esb/wsdl/orderservice#wsdl.interface(OrderServicePortType)"/>
    <binding.ws port="http://www.toic.com/esb/wsdl/orderservice#wsdl.endpoint(CreateOrderService/OrderServicePort)">
      <property name="weblogic.wsee.wsat.transaction.flowOption"
                type="xs:string" many="false">NEVER</property>
    </binding.ws>
  </service>
……
</composite>

The issuse with NullPointer in Oracle 11g SOA



In recent couple of days I am working on BPEL project in Oracle SOA 11g and found one thing which took me a while to figure out where the problem is from.   When I deploy the BPEL into development server through JDeveloper directly without using cfgplan.xml BPEL works fine.  But when the application is deployed to testing server by manually deployment with cfgplan.xml, there will be one NullPointer exception when one reference web service is invoked from BPEL.   After some investigation the problem was fixed by changing the port of reference web service.
The below are the reference definition in composite.xml

  <reference name="ISL-FUL-MPSA"
             ui:wsdlLocation="Med_SC_SP_ManageServiceParametersAllocationHttp_Service.wsdl">
    <interface.wsdl interface="http://Med_Lib_Service/ManageServiceParametersAllocationV2#wsdl.interface(ManageServiceParametersAllocation)"/>
    <binding.ws port="http://Med_Lib_Service/ManageServiceParametersAllocationV2/Binding2#wsdl.endpoint(Component1Export_ManageServiceParametersAllocationHttpService/Component1Export_ManageServiceParametersAllocationHttpPort)"
                location="Med_SC_SP_ManageServiceParametersAllocationHttp_Service.wsdl"
                soapVersion="1.1">
      <property name="weblogic.wsee.wsat.transaction.flowOption"
                type="xs:string" many="false">WSDLDriven</property>
    </binding.ws>
  </reference>

In this definition the service and port of the reference web service is:  

Component1Export_ManageServiceParametersAllocationHttpService and Component1Export_ManageServiceParametersAllocationHttpPort.   

They are from Med_SC_SP_ManageServiceParametersAllocationHttp_Service.wsdl.

            <wsdl:service name="Component1Export_ManageServiceParametersAllocationHttpService">
                        <wsdl:port name="Component1Export_ManageServiceParametersAllocationHttpPort" binding="this:Component1Export_ManageServiceParametersAllocationHttpBinding">
                                    <soap:address location="http://xxx.yyy.zzz.com:8001/ISL-FULAdaptor/BS/ISL-FULServiceAdaptor-v1"/>
                        </wsdl:port>
            </wsdl:service>

The actual reference service is deployed on OSB 10g.    For some reason after the deployment the service and port are changed to:
Component1Export_ManageServiceParametersAllocationHttpBindingQSService and Component1Export_ManageServiceParametersAllocationHttpBindingQSPort.

The below is the portion of the published WSDL from the referenced service deployed on OSB10g.

<s0:service name="Component1Export_ManageServiceParametersAllocationHttpBindingQSService">
                        <s0:port binding="s5:Component1Export_ManageServiceParametersAllocationHttpBinding" name="Component1Export_ManageServiceParametersAllocationHttpBindingQSPort">
                                    <s4:address location="http://xxx.yyy.zzz.com:8001/ISL-FULAdaptor/BS/ISL-FULServiceAdaptor-v1"/>
                        </s0:port>
</s0:service>

The original generated cfgplan.xml is like the below:

     <reference name="ISL-FUL-MPSA">
         <!--Add search and replace rules for the binding properties-->
         <binding type="ws">
            <attribute name="port">
               <replace>http://Med_Lib_Service/ManageServiceParametersAllocationV2/Binding2#wsdl.endpoint(Component1Export_ManageServiceParametersAllocationHttpService/Component1Export_ManageServiceParametersAllocationHttpPort)</replace>
            </attribute>
            <attribute name="location">
               <replace> http://xxx.yyy.zzz.com:8001/ISL-FULAdaptor/BS/ISL-FULServiceAdaptor-v1?wsdl </replace>
            </attribute>
            <property name="weblogic.wsee.wsat.transaction.flowOption">
               <replace>WSDLDriven</replace>
            </property>
         </binding>
      </reference>

This  cfgplan.xml will cause NullPointer exception on the testing server since the service and port names do not match actual service deployed on OSB 10g.
After we change the cfgplan.xml to use the matched service name and port like the below:

      <reference name="ISL-FUL-MPSA">
         <!--Add search and replace rules for the binding properties-->
         <binding type="ws">
            <attribute name="port">
               <replace>http://Med_Lib_Service/ManageServiceParametersAllocationV2/Binding2#wsdl.endpoint(Component1Export_ManageServiceParametersAllocationHttpBindingQSService/Component1Export_ManageServiceParametersAllocationHttpBindingQSPort)</replace>
            </attribute>
            <attribute name="location">
               <replace>http://xxx.yyy.zzz.com:8001/ISL-FULAdaptor/BS/ISL-FULServiceAdaptor-v1?wsdl</replace>
            </attribute>
            <property name="weblogic.wsee.wsat.transaction.flowOption">
               <replace>WSDLDriven</replace>
            </property>
         </binding>
      </reference>

The testing shows that NullPointer exception is gone.