Request/Response Example

Imagine we need to process a message requesting information about a specific policy product (message tc=201, as defined by ACORD standards). The ACORD message looks like this:

<tx:TXLife xmlns:tx="http://ACORD.org/Standards/Life/2">
    <tx:UserAuthRequest>
        <tx:UserLoginName>username</tx:UserLoginName>
        <tx:UserPswd>
            <tx:Pswd>password</tx:Pswd>
        </tx:UserPswd>
    </tx:UserAuthRequest>

    <tx:TXLifeRequest>
        <tx:TransRefGUID>2fac30d5-cd66-4eaa-833f-9f4989db796b</tx:TransRefGUID>
        <tx:TransType tc="201">Policy Product Inquiry</tx:TransType>
        <tx:TransExeDate>2007-06-01</tx:TransExeDate>
        <tx:TransExeTime>17:00:13-05:00</tx:TransExeTime>
        <tx:InquiryLevel tc="1">OLI_INQUIRY_OBJ</tx:InquiryLevel>

        <tx:OLifE Version="2.14.00">
            <tx:PolicyProduct id="PolicyProduct_1">
                <tx:CarrierCode>1002</tx:CarrierCode>
                <tx:ProductCode>VWL01</tx:ProductCode>
            </tx:PolicyProduct>
        </tx:OLifE>
    </tx:TXLifeRequest>
</tx:TXLife>

 

You can see how the message is a Policy Product Inquiry concerning the PolicyProduct provided by carrier "1002" using the product code "VWL01."

The XQuery code is as simple as this:

declare namespace tx = "http://ACORD.org/Standards/Life/2";
import module namespace example = "http://www.datadirect.com/xquery/examples" at "acord_verbs.xquery";

<tx:TXLife> {
    for $request in doc("201-1.xml")/tx:TXLife/tx:TXLifeRequest
    return example:reply-201($request)
}
</tx:TXLife>


The exampe:reply-201 function analyzes the TXLifeRequest content and fetches the relevant information from the relational repository:

declare function example:reply-201($request as element(tx:TXLifeRequest)) as element(tx:TXLifeResponse)? {
    let $results :=
        for $policyProduct at $pos in $request/tx:OLifE/tx:PolicyProduct
        let $carrierCode := xs:string($policyProduct/tx:CarrierCode)
        let $productCode := xs:string($policyProduct/tx:ProductCode)
        for $policy in collection("ACORD_POLICY")/ACORD_POLICY
                                  [CarrierCode eq $carrierCode]
                                  [ProductCode eq $productCode]
        return <tx:PolicyProduct> {
                  attribute id {fn:concat("PolicyProduct_", xs:string($pos))},
                  $carrierCode,
                  <tx:PlanName>{xs:string($policy/PlanName)}</tx:PlanName>,
                  $productCode,
                  <tx:MarketingName>{xs:string($policy/MarketingName)}</tx:MarketingName>
               } </tx:PolicyProduct>
    return
        example:create-response(
                $request,
                (<tx:TransResult>
                     <tx:ResultCode tc="1">Success</tx:ResultCode>
                  </tx:TransResult>,
                  <tx:OLifE Version="2.12.00">
                      {$results}
                  </tx:OLifE>
                 )
        )
};

Note how the relational repository is accessed by the XQuery function:

for $policy in collection("ACORD_POLICY")/ACORD_POLICY[CarrierCode eq $carrierCode][ProductCode eq $productCode]

The first "for" instruction iterates over each PolicyProduct element from the request (there could be more than one); then, for each PolicyProduct the carrier and product code are used as keys to retrieve the information from the database.

The response is formatted according to the required ACORD structure:

(: Creates a TXLife message with non-empty TXLifeResponse :)
declare function example:create-response(
                       $request as element(tx:TXLifeRequest),
                       $payLoad as element()*) as element(tx:TXLifeResponse) {

    <tx:TXLifeResponse> {
        $request/tx:TransRefGUID,
        $request/tx:TransType,
        <tx:TransExeDate>{example:formatDate(fn:current-date())}</tx:TransExeDate>,
        <tx:TransExeTime>{example:formatTime(fn:current-time())}</tx:TransExeTime>,
        $payLoad
    }
    </tx:TXLifeResponse>
};

From the XQuery author’s point of view, the relational model is navigated as if it was an XML structure; under the covers, DataDirect XQuery™ will issue the proper SQL statements to fetch the entries in the ACORD_POLICY table that match carrier and product codes.

A similar example is a “party search” (tc=301); in this case the message we receive is this one (click here for the XML document):

<tx:TXLife xmlns:tx="http://ACORD.org/Standards/Life/2">
    <tx:UserAuthRequest>
        <tx:UserLoginName>username</tx:UserLoginName>
        <tx:UserPswd>
            <tx:Pswd>password</tx:Pswd>
        </tx:UserPswd>
    </tx:UserAuthRequest>

    <tx:TXLifeRequest>
        <tx:TransRefGUID>e6c00b0e-94d4-4e48-8857-1690945df1c4</tx:TransRefGUID>
        <tx:TransType tc="301">Party Search</tx:TransType>
        <tx:TransExeDate>2007-06-01</tx:TransExeDate>
        <tx:TransExeTime>17:00:13-05:00</tx:TransExeTime>
        <tx:CriteriaExpression>
            <tx:CriteriaOperator tc="2">AND</tx:CriteriaOperator>
            <tx:Criteria>
                <tx:ObjectType tc="115">Person</tx:ObjectType>
                <tx:PropertyName>LastName</tx:PropertyName>
                <tx:PropertyValue tc="+1">Roberts</tx:PropertyValue>
                <tx:Operation tc="1">Equal</tx:Operation>
            </tx:Criteria>
            <tx:Criteria>
                <tx:ObjectType tc="115">Person</tx:ObjectType>
                <tx:PropertyName>FirstName</tx:PropertyName>
                <tx:PropertyValue>Edward</tx:PropertyValue>
                <tx:Operation tc="1">Equal</tx:Operation>
            </tx:Criteria>
        </tx:CriteriaExpression>

        <tx:OLifE Version="2.14.00">
        </tx:OLifE>
    </tx:TXLifeRequest>
</tx:TXLife>

The search criteria could be more complicated than what illustrated here (see 301-5.xml for example). The XQuery processing this message can be something like this (click here for the XQuery document):

import module namespace example = "http://www.datadirect.com/xquery/examples" at "acord_verbs.xquery";

declare namespace tx="http://ACORD.org/Standards/Life/2";

declare variable $request as document-node(element(*, xs:untyped)) external;

<tx:TXLife> {
    for $r in $request/tx:TXLife/tx:TXLifeRequest
    return example:reply-301($r)
    }
</tx:TXLife>

You can browse acord_verbs.xquery to find details about how the request is processed. Note that in this case, to simulate a more realistic scenario, we are not processing the request message as a file (accessed through the fn:doc() function), but the request is bound externally to the $request variable. This means that the Java code invoking the XQuery is responsible for binding the proper ACORD request message to the variable before executing the XQuery; see Using DataDirect XQuery™ to Bind External Variables to Dynamic Values for details about how that can be done.


What's Next

Go to Performing a Search and Inquiry Using Multiple Joins to see how you can perform complex searches and queries using multiple joins.

DataDirect XQuery FAQ

This informative DataDirect XQuery® FAQ answers frequently-asked questions about DataDirect XQuery® , including questions about performance, scalability, use-cases, resources, and more.

If you're more of a hands-on learner, then download a free copy and start exploring DataDirect XQuery® today!

New Case Study

Gevity produces sales proposals in real time using DataDirect XQuery® . See how Gevity uses DataDirect XQuery® to combine Web service data from SalesForce.com with relational data in Oracle in a pricing engine for HR management.