RSS

Tag Archives: XQuery

Grouping elements using XQuery distinct function in Oracle Service Bus

Example how to use XQuery in the Oracle Service Bus to perform a for-each-group function to change a flat dataset of records in a grouped recordset sorted on a unqiue value using the XQuery distinct-values function.

Source XML message:

<ns0:dir-response xmlns:ns0="http://www.rubix.nl/someNamespace">
 <ns0:file>
 <ns0:dataset>dataset_1</ns0:dataset>
 <ns0:name>name_11</ns0:name>
 </ns0:file>
 <ns0:file>
 <ns0:dataset>dataset_1</ns0:dataset>
 <ns0:name>name_12</ns0:name>
 </ns0:file>
 <ns0:file>
 <ns0:dataset>dataset_2</ns0:dataset>
 <ns0:name>name_21</ns0:name>
 </ns0:file>
 <ns0:file>
 <ns0:dataset>dataset_1</ns0:dataset>
 <ns0:name>name_13</ns0:name>
 </ns0:file>
</ns0:dir-response>

Wanted target XML message where output is grouped on value of element dataset:

<ns0:filelist xmlns:ns0="http://www.rubix.nl/someNamespace">
 <ns0:set>
 <ns0:setname>dataset_1</ns0:setname>
 <ns0:files>
 <ns0:filename>name_11</ns0:filename>
 </ns0:files>
 <ns0:files>
 <ns0:filename>name_12</ns0:filename>
 </ns0:files>
 <ns0:files>
 <ns0:filename>name_13</ns0:filename>
 </ns0:files>
 </ns0:set>
 <ns0:set>
 <ns0:setname>dataset_2</ns0:setname>
 <ns0:files>
 <ns0:filename>name_21</ns0:filename>
 </ns0:files>
 </ns0:set>
</ns0:filelist>

The required XQuery code:

(:: pragma bea:global-element-parameter parameter="$dir_response" element="ns0:dir-response" location="../schemas/someSource.xsd" ::)
(:: pragma bea:global-element-return element="ns0:filelist" location="../schemas/someTarget.xsd" ::)

declare namespace ns0 = "http://www.rubix.nl/someNamespace";
declare namespace xf = "http://tempuri.org/someProject/resources/xqueries/XQ_test/";

declare function xf:XQ_test($dir_response as element(ns0:dir-response))
 as element(ns0:filelist) {

 if ($dir_response/ns0:file)
 then
 <ns0:filelist>
 {
 for $setname in distinct-values($dir_response/ns0:file/ns0:dataset)
 let $file-in-set := $dir_response/ns0:file[ns0:dataset=$setname]
 return
 <ns0:set>
 <ns0:setname>{ data($setname) }</ns0:setname>
 {
 for $file in $file-in-set
 return
 <ns0:files>
 <ns0:filename>{$file/ns0:name/text()}</ns0:filename>
 </ns0:files>
 }
 </ns0:set>
 }
 </ns0:filelist>
 else <ns0:filelist/>
};

declare variable $dir_response as element(ns0:dir-response) external;

xf:XQ_test($dir_response)
 
1 Comment

Posted by on 02-11-2012 in Oracle, OSB

 

Tags: , ,

Using execute-sql for Name-Value Pair lookup in Oracle Service Bus

For multiple services in our OSB landscape we needed some sort of name-value pair lookup mechanism. What we didn’t want is excessive IF-THEN-ELSE statements in our OSB services, so in the end we decided to create:

  • a function (local type Oracle Service Bus proxy service)
  • use a simple database table from where we could externally retrieve the data
  • access the database through the fn-bea:execute-sql() function.

So first things first:

Creating the table with SQL where we use (parent proxy) SERVICE and NAME as input to retrieve the required VALUE:

CREATE TABLE NVPTABLE
(
 "SERVICE" VARCHAR2(256 BYTE),
 "NAME" VARCHAR2(256 BYTE),
 "VALUE" VARCHAR2(256 BYTE)
)

REM INSERTING into NVPTABLE
Insert into NVPTABLE (SERVICE,NAME,VALUE) values ('myParentService','010','Rotterdam');
Insert into NVPTABLE (SERVICE,NAME,VALUE) values ('myParentService','020','Amsterdam');
Insert into NVPTABLE (SERVICE,NAME,VALUE) values ('myParentService','030','Utrecht');
Insert into NVPTABLE (SERVICE,NAME,VALUE) values ('myParentService','040','Eindhoven');
Insert into NVPTABLE (SERVICE,NAME,VALUE) values ('myParentService','073','Den Bosch');

In Weblogic we create a datasource, use jdbc/nvp_ds as JNDI name and  target it to the correct OSB managed servers.

Then in our OEPE (or Notepad++) we create the following XML schema and use it in a WSDL as a nice datamodel for our soon-to-be function. As you can see the 2 elements for request and response are simple and logically match the database columns.

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:us01="http://rubix.nl/schemas/cdm/utility01"
 elementFormDefault="qualified" targetNamespace="http://rubix.nl/schemas/cdm/utility01">
 <xs:element name="GetNameValuePairRequest">
 <xs:complexType>
 <xs:sequence>
 <xs:element name="serviceName" type="xs:string"/>
 <xs:element name="inputName" type="xs:string"/>
 </xs:sequence>
 </xs:complexType>
 </xs:element>
 <xs:element name="GetNameValuePairResponse">
 <xs:complexType>
 <xs:sequence>
 <xs:element name="resultValue" type="xs:string"/>
 </xs:sequence>
 </xs:complexType>
 </xs:element>
</xs:schema>

Then create a local proxy service which uses the SOAP/WSDL. The message flow of our function (local proxy) can be simple and just use 1 XQuery transformation to do all the magic stuff:


And this is how the magic really looks like under the hood:

(:: pragma bea:global-element-parameter parameter="$getNameValuePairRequest1" element="ns0:GetNameValuePairRequest" location="../interfaces/util01.GetNameValuePair.xsd" ::)
(:: pragma bea:global-element-return element="ns0:GetNameValuePairResponse" location="../interfaces/util01.GetNameValuePair.xsd" ::)

declare namespace ns0 = "http://rubix.nl/schemas/cdm/utility01";
declare namespace xf = "http://tempuri.org/Local.GetNameValue/transformation/resultXQ/";
declare namespace funcRBX = "http://www.rubix.nl/local";

declare function funcRBX:runSql($inputA as xs:string, $inputB as xs:string) as xs:string
{
 let $sqlstring := concat('SELECT value FROM NVPTABLE where SERVICE=''',$inputA,''' and NAME=''',$inputB,'''')
 let $result := fn-bea:execute-sql('jdbc/nvp_ds','result',$sqlstring)
 return $result
};

declare function xf:resultXQ($getNameValuePairRequest1 as element(ns0:GetNameValuePairRequest))
 as element(ns0:GetNameValuePairResponse) {
 <ns0:GetNameValuePairResponse>
 <ns0:resultValue>{ funcRBX:runSql($getNameValuePairRequest1/ns0:serviceName/text(),$getNameValuePairRequest1/ns0:inputName/text())}</ns0:resultValue>
 </ns0:GetNameValuePairResponse>
};

declare variable $getNameValuePairRequest1 as element(ns0:GetNameValuePairRequest) external;

xf:resultXQ($getNameValuePairRequest1)

The resultXQ function which does the XQuery transformation uses the custom funcRBX:runSql function (don’t forget to declare the namespace). This runSql function performs the following steps.

  • First we concatenate the SQL-statement we want to use to run against the database. We do this to prevent some weird typecasting problems which can occur with the execute-sql function.
  • Second we run the function and return the result. Using the let and return command, we prevent the default behaviour of the execute-sql function to return:
    <result><VALUE>Den Bosch</VALUE><result>

Voila, you are finished and the final result will look like this:

Hope it helps.

References:

 
6 Comments

Posted by on 24-05-2012 in Oracle, OSB

 

Tags: , ,

Use XQuery with fn-bea:lookupBasicCredentials

This is an example XQuery which uses 2 simple custom functions and the fn-bea:lookupBasicCredentials to retreive information from a Service Account in the Oracle Service Bus. This to prevent the usage of cleartext passwords in the Oracle Service Bus.


declare namespace funcRBX = "http://www.rubix.nl/local"

declare function funcRBX:getUsername($inputPath as xs:string) as xs:string
{
  let $data := fn-bea:lookupBasicCredentials($inputPath)
  return
    if (exists($data/con:username/text()))
    then $data/con:username/text()
    else ""
};

declare function funcRBX:getPassword($inputPath as xs:string) as xs:string
{
  let $data := fn-bea:lookupBasicCredentials($inputPath)
  return
    if (exists($data/con:password/text()))
    then $data/con:password/text()
    else ""
};

declare function xf:defineConnection() as element(ns0:ConnectionHeader)
{
  <ns0:Connection>
    <ns0:host>ftp.myserver.locaL</ns0:host>
    <ns0:port>21</ns0:port>
    <ns0:username>{funcRBX:getUsername("MyOSBProject/serviceaccounts/SA_FTP")}</ns0:username>
    <ns0:password>{funcRBX:getPassword("MyOSBProject/serviceaccounts/SA_FTP")}</ns0:password>
    <ns0:protocol>FTP</ns0:protocol>
  </ns0:Connection>
};

hope it helps

 
1 Comment

Posted by on 02-02-2012 in OSB, XQuery

 

Tags: , ,

Using custom SOAP Faults in Oracle Service Bus

To many times in Oracle Service Bus projects the design and creation of a generic soap fault error handling mechanism which is re-usable by all proxy services is forgotten. With this post I  first want to show quickly what can happen without a decent soap fault structure in a project. And then show a basic soap fault mechanism which I often re-use in projects.

First some examples (also explained in more detail by Eric Elzinga here).
A proxy service with this basic Error Handler will log the $fault and reply-with-failure.

This solution however will inform for functional faults returned by the backend system (later on defined as Business Faults):

REQUEST:

   <soapenv:Body>
      <v1:getPersonRequest>
         <v11:Person>
            <v11:ID>2905</v11:ID>
            <v11:Type>Customer</v11:Type>
         </v11:Person>
      </v1:getPersonRequest>
   </soapenv:Body>

RESPONSE (returned by backend system, not Error Handler):

 <soap:Body>
      <soap:Fault>
         <faultcode>soap:Server</faultcode>
         <faultstring>no person found</faultstring>
         <detail>
            <ns2:CRMSystem>
               <ns2:ErrorCode>CRM0012</ns2:ErrorCode>
            </ns2:CRMSystem>
         </detail>
      </soap:Fault>
   </soap:Body>

However for technical (I will define these later on as runtime) faults in the OSB, the Error Handler will not alter the $body content and simply returns the same request message $body content. See below example for a response with a slightly altered and sabotaged request.

RESPONSE (returned by Error Handler due to OSB error):

   <soapenv:Body>
      <v1:getPersonRequest>
         <v11:Person>
            <v11:ID>2905</v11:ID>
            <v11:Type>Customerrrrrrr</v11:Type>
         </v11:Person>
      </v1:getPersonRequest>
   </soapenv:Body>

This means that the service consumer gets no SOAP Fault structure from the OSB and would only be able to determine due to the HTTP 500 transport error that something is wrong. Weblogic logfiles will show the runtime $fault which is logged by the Error Handler, but this usually can only be monitored by Administrators.

Fault in logfile:

<con:fault>
  <con:errorCode>BEA-382505</con:errorCode>
  <con:reason>OSB Validate action failed validation</con:reason>
  <con:details>
    <con1:ValidationFailureDetail>
      <con1:message>string value 'Customerrrrrrr' is not a valid enumeration value .. </con1:message>
    </con1:ValidationFailureDetail>
  </con:details>
  <con:location>
    <con:node>RouteGetPersoon</con:node>
    <con:path>request-pipeline</con:path>
  </con:location>
</con:fault>

Getting started:

So enough with the examples and lets continue with a solution.
In OEPE we need add 3 files in the OSB Project.

  • SOAP 1.1 Envelop schema (download here)
  • MessageContext.xsd (extract from /WLHOME/Oracle_OSB1/lib/sb-schemas.jar)
  • XQuery to construct the soap:Fault (create SoapFault.xq)

Your project should look like this:

The content of the XQuery:

xquery version "1.0" encoding "UTF-8";
(:: pragma bea:global-element-parameter parameter="$soapbody" element="soap-env:Body" location="soap-env.xsd" ::)
(:: pragma bea:global-element-parameter parameter="$osbfault" element="ctx:fault" location="MessageContext.xsd" ::)
(:: pragma bea:global-element-parameter parameter="$osbinbound" element="ctx:endpoint" location="MessageContext.xsd" ::)
(:: pragma bea:global-element-parameter parameter="$osboutbound" element="ctx:endpoint" location="MessageContext.xsd" ::)
(:: pragma bea:global-element-return element="soap-env:Fault" location="soap-env.xsd" ::)

declare namespace xf = "http://rubix.nl/common/Soap11Fault/";
declare namespace soap-env = "http://schemas.xmlsoap.org/soap/envelope/";
declare namespace ctx = "http://www.bea.com/wli/sb/context";
declare namespace tp = "http://www.bea.com/wli/sb/transports";
declare namespace http = "http://www.bea.com/wli/sb/transports/http";

declare function xf:SoapFault($soapbody as element(soap-env:Body),
$osbfault as element(ctx:fault),
$osbinbound as element(ctx:endpoint),
$osboutbound as element(ctx:endpoint))
as element(soap-env:Fault)
{

<soap-env:Fault>
{
if ($osbfault/ctx:errorCode="BEA-382505")
then <faultcode xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">soap-env:Client</faultcode>
else <faultcode xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">soap-env:Server</faultcode>
}
{
if ($soapbody/soap-env:Fault)
then <faultstring>{$soapbody/soap-env:Fault/faultstring/text()}</faultstring>
else <faultstring>Error in operation: {$osbinbound/ctx:service/ctx:operation/text()}</faultstring>
}
{
if ($osboutbound/ctx:transport/ctx:uri)
then <faultactor>{$osboutbound/ctx:transport/ctx:uri/text()}</faultactor>
else <faultactor>{fn:concat($osbinbound/ctx:transport/ctx:request/tp:headers/http:Host,$osbinbound/ctx:transport/ctx:uri)}</faultactor>
}
<detail>
{
if ($soapbody/soap-env:Fault)
then <business>{$soapbody/soap-env:Fault/detail}</business>
else <business/>
}
<runtime>{$osbfault}</runtime>
</detail>
</soap-env:Fault>

};

declare variable $soapbody as element(soap-env:Body) external;
declare variable $osbfault as element(ctx:fault) external;
declare variable $osbinbound as element(ctx:endpoint) external;
declare variable $osboutbound as element(ctx:endpoint) external;

xf:SoapFault($soapbody,
$osbfault,
$osbinbound,
$osboutbound)

As you can see the input variables for the XQuery are:

  • soapbody = $body variable
  • osbfault = $fault variable (remember that the osb $fault is not a valid soap:Fault structure)
  • osbinbound = $inbound variable
  • osboutbound = $outbound variable

The reason the 4 variables are completely send to the XQuery as input is due to the fact that it will be used as a generic component for all our proxy servics. With future enhancements you will have all information available to add more custom logic.

Added 03-FEB-2012:

There is some small remark to the namespace used in the <faultcode> element. If you validate the response you can detect that if your response message uses a <soap-env> namespace and you static use “soap:Server” in your response it will not validate. The prefix should be a valid namespace prefix in the message. For that reason I use a full namespace definitition in the <faultcode> element just to be sure. Another option is the use of this code, but I haven’t tested it yet myself in production.

<faultcode>{fn:concat(fn:substring-before(fn:name($soapbody),':'),':Client')}</faultcode>

/Added 03-FEB-2012:

In our Proxy Service we will add a Replace function in the Error Handler that will execute the SoapFault.xq

Replace Action

And the configuration of the XQuery will look something like this:

mapping the variables

So we deploy/publish the configuration to our OSB server and execute the request again.

RESPONSE (wth Business Fault):

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <soap:Fault>
         <faultcode xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">soap-env:Server</faultcode>
         <faultstring>no person found</faultstring>
         <faultactor>http://mycrmserver:8888/personService/v1</faultactor>
         <detail>
            <business>
              <ns2:CRMSystem>
                <ns2:ErrorCode>CRM0012</ns2:ErrorCode>
              </ns2:CRMSystem>
            </business>
            <runtime>
               <con:fault xmlns:con="http://www.bea.com/wli/sb/context">
                  <con:errorCode>BEA-380001</con:errorCode>
                  <con:reason>Internal Server Error</con:reason>
                  <con:location>
                     <con:node>RouteGetPerson</con:node>
                     <con:path>response-pipeline</con:path>
                  </con:location>
               </con:fault>
            </runtime>
         </detail>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>

Overview Business Fault:

  1. faultcode is from backend system
  2. faultstring is send from backend
  3. faultactor url is retrieved from the outbound variable
  4. <detail> contains a <business> which is the original <detail> from the backend
  5. <detail> contains a <runtime> which holds the OSB $fault
RESPONSE (wth Runtime Fault):
<soapenv:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <soapenv:Fault>
         <faultcode xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">soap-env:Client</faultcode>
         <faultstring>Error in operation: getPerson</faultstring>
         <faultactor>osbserver:8011/getPersonService</faultactor>
         <detail>
            <business/>
            <runtime>
               <con:fault>
                  <con:errorCode>BEA-382505</con:errorCode>
                  <con:reason>OSB Validate action failed validation</con:reason>
                  <con:details>
                     <con1:ValidationFailureDetail>
                        <con1:message>string value 'Customerrrr' is not a valid enumeration .....</con1:message>
                        <con1:xmlLocation>
                           <v11:Type>Customerrrr</v11:Type>
                        </con1:xmlLocation>
                     </con1:ValidationFailureDetail>
                  </con:details>
                  <con:location>
                     <con:node>RouteGetPerson</con:node>
                     <con:path>request-pipeline</con:path>
                  </con:location>
               </con:fault>
            </runtime>
         </detail>
      </soapenv:Fault>
   </soapenv:Body>
</soapenv:Envelope>
Overview Runtime Fault:
  1. faultcode generated in XQuery due to BEA-38205 errorcode (means a Validate error). Check SOAP specifications for reason and other possible codes.
  2. faultstring generated in XQuery
  3. faultactor generated in XQuery and shows OSB hostname and which managed server (port)
  4. <detail> contains no <business/>
  5. <detail> contains a <runtime> which holds the OSB $fault
Summary:
  • According to your needs you can alter the SoapFault XQuery and extend it with all sort of additional logic.
  • You don’t necessary need the MessageContext.xsd, these variables can also be defined as anyXml
  • I’m interested in feedback so leave a comment if you see issues, improvements, etc.
Updates:
  • 2012-02-03: corrected namespaces in response message, see comment DJ Kaiping + new XQuery function used for creating FaultCode (see additional source code under XQuery source code)
 
Reference:
 
13 Comments

Posted by on 28-07-2011 in Oracle, OSB, XQuery

 

Tags: , ,

OSB Xquery function if-absent example

Since I’m on a roll with Xquery functions let’s add an addition. Especially since the earlier example is a bit large for people looking for a simple example.

So maybe this helps better to get an understanding. After working with Tibco BusinessWorks for some years I used a lot off the internal tib:functions supplied out-of-the-box and always found it a disappointment that Oracle (read BEA here) didn’t offer such a nice catalog to help you out. So over time I added a lot off these functions to my own library.

For example the function if-absent helps me to prevent all these “is-value1-there-then-use-it-and-if-not-i-want-you-to-use-value2″ checks.

declare function funcRBX:if-absent($arg as item()* , $value as item()* ) as item()*
{
  if (exists($arg)) then $arg else $value
};

Works like a charm … ;-)

 
Leave a comment

Posted by on 17-03-2011 in Oracle, OSB, XQuery

 

Tags: , ,

OSB Xquery function DateTime conversion

>Yesterday at the Oracle SOA and E2.0 Partner Community Forum in Utrecht I had a good talk with Edwin, Guido and Eric about OSB and one of the topics was our experience with Xquery functions in the OSB. So I mentioned some examples I used in the past and decided to post them on my blog when I had the time.

So here is one to start.

First we declare a nice namespace for our function ‘library’ in the top of our XQuery file.

declare namespace funcRBX = "http://www.rubix.nl";

Then we create our function, the following example is used for altering the format of Date and Time values to the specific format that Siebel expects. The code should be clear enough I hope with the comments in them. This is off course just one of the possible ways to do it and contains some specific environment checks I had to use. For instance this function was also used when the source is not XML but files (the old BEA MFL way of working) where day and month could have a value of 00 and we had to alter this to 01 as a business requirement.

declare function funcRBX:siebelDateTime ( $inputDate as xs:string?, $inputTime as xs:string?) as xs:string
{
 if (($inputDate = "" or empty($inputDate)) and ($inputTime = "" or empty($inputTime)))     (: no input :)
 then ""
 else if ($inputTime = "" or empty($inputTime)) then              (: only inputDate received :)
  concat(
  if (substring(data($inputDate),5,2) = "00") then ("01") else substring(data($inputDate),5,2)  (: check if day is not 00 :)
  ,"/",if (substring(data($inputDate),7,2) = "00") then ("01") else substring(data($inputDate),7,2) (: check if month is not 00 :)
  ,"/",substring(data($inputDate),1,4))
 else if ($inputDate = "" or empty($inputDate)) then              (: only inputTime received :)
  concat(
  substring(data($inputTime),1,2)
        ,":",substring(data($inputTime),3,4)
        ,":00")
 else                          (: both inputDate and inputTime received :)
  concat(
  if (substring(data($inputDate),5,2) = "00") then ("01") else substring(data($inputDate),5,2)  (: check if day is not 00 :)
        ,"/",if (substring(data($inputDate),7,2) = "00") then ("01") else substring(data($inputDate),7,2) (: check if month is not 00 :)
        ,"/",substring(data($inputDate),1,4)
        ," ",substring(data($inputTime),1,2)
        ,":",substring(data($inputTime),3,4)
        ,":00")
 };

And then down in the XQuery mapping you can call your function like this:

{
 funcRBX:siebelDateTime($someInputDate)
}

Due to the the fact that the input parameters are optional (the ? character after the declaration) you can leave the second input for time out or use ” as input.

 
5 Comments

Posted by on 17-03-2011 in Oracle, OSB, Siebel, XQuery

 

Tags: , , ,

using CDATA in the Oracle Service Bus

>In our project when an error occured the following Error structure must be returned to the service consumer.

<ns1:Messages>
  <ns1:Message>
    <ns1:Status>E</ns1:Code>
    <ns1:Code>99999</ns1:Code>
    <ns1:Description>someDescription</ns1:Description>
  </ns1:Message>
<ns1:Messages>

In a case of a validation error the consumer would receive the following message where description is a concat of $fault/ctx:errorCode and $fault/ctx:reason

<ns1:Messages>
  <ns1:Message>
    <ns1:Status>E</ns1:Code>
    <ns1:Code>99999</ns1:Code>
    <ns1:Description>BEA-382505 - OSB Validate action failed validation</ns1:Description>
  </ns1:Message>
<ns1:Messages>

The limitation here is off course that the real description (the $fault variable) is not visible for the service consumer. Since the $fault contains an XML-structure we need a mechanism as CDATA to encapsulate this in the response message.

The following blogpost is a simplified result of the actual project, but should give a general idea:

So we used the above solution with a Replace action in the common Error Handler. In our data model the element is repeating so we made a choice to add a second element.

<ns1:Messages>
  <ns1:Message>
    <ns1:Status>E</ns1:Code>
    <ns1:Code>99999</ns1:Code>
    <ns1:Description>{$fault/ctx:errorCode/text()} - {$fault/ctx:reason/text()}</ns1:Description>
  </ns1:Message>
  <ns1:Message>
    <ns1:Status>E</ns1:Code>
    <ns1:Code>{$fault/ctx:errorCode/text()}</ns1:Code>
    <ns1:Description>{fn-bea:serialize($fault/ctx:details)}</ns1:Description>
  </ns1:Message>
<ns1:Messages>

This will result in a result like:

<ns1:Messages>
  <ns1:Message>
    <ns1:Status>E</ns1:Code>
    <ns1:Code>99999</ns1:Code>
    <ns1:Description>BEA-382505 - OSB Validate action failed validation</ns1:Description>
  </ns1:Message>
  <ns1:Message>
    <ns1:Status>E</ns1:Code>
    <ns1:Code>BEA-382505</ns1:Code>
    <ns1:Description><![CDATA[<ctx:details xmlns:ctx="http://www.bea.com/wli/sb/context"><ns0:ValidationFailureDetail xmlns:ns0="http://www.bea.com/wli/sb/stages/transform/config"><ns0:message>Expected element 'someRequiredElement@http://www.rubix.nl/someNamespace' </ns0:ValidationFailureDetail></ctx:details>]]></ns1:Description>
  </ns1:Message>
<ns1:Messages>

The bea-serialize function helps us to transform an XML input to a string output. Apparently there has been an update to the XPath Expression Editor in the OSB since the editor in 11.1.1.3 now automatically sets the CDATA definition.

In the past (the AquaLogic days) you explicitly had to define this with a function as:

fn-bea:serialize(xs:string(fn:concat("<![CDATA[",fn-bea:serialize($fault),"]]>")))

Anoter solution would be to use XQuery in the error handler and the use of a namespace stripping function (as described here by Marc Keldermann) to clean-up the result of the $fault/details.

 
Leave a comment

Posted by on 17-02-2011 in Oracle, OSB

 

Tags: , ,

 
Follow

Get every new post delivered to your Inbox.

Join 344 other followers