tags:

views:

546

answers:

3

There are several application systems that pass messages to each other as part of their work process. Due to technical constraints revolving transactional integrity, the application data and message delivery are all committed into a single mainframe DB2 database. The messages are not directly passed to BizTalk server (2006 R2); it is up to BTS to pull the message out from the DB2 database later.

The message-queue table in the DB2 database has several fields. The key field is the MESSAGE_DATA column - the actual message; it is XML content itself. When one uses the DB2 adapter to query out records from the table the incoming schema would be like

CORRECTION UPDATE: the DB2Message schema is attribute based; I mistook it previously to be element based.

<DB2Message MESSAGE_DATA="&lt;InternalXML&gt; ........ &lt;/InternalXML&gt;"
 MESSAGE_DATE="2008-1-1 00:00:00" MESSAGE_ID="GUID" TXN_ID="GUID" .... other attrib />

The orchestration consumes the schema

<EAIMessage>
 <Header>
  <ServiceID>
  <MessageID>
  ....
  <Mode>
 </Header>
 <Body>
  <RawXML>
 </Body>
</EAIMessage>

The orchestration will use several promoted fields in the Header to make routing and processing decisions. The thing is, those header fields are actually coming from the inner-XML content stored into DB2Message's MESSAGE_DATA.

At this single level, the Mapper has no knowledge of this underyling XML schema inside MESSAGE_DATA when pitting the two schemas together. There should probably be some XPath functoid that can further drill down the MESSAGET_DATA element to conduct the proper mapping of values, but having not dealt with extensive XML and XSLT applications before, I am unable to see the features available that can help me perform this task.

Has anybody done such data extraction and mapping before?

UPDATE. As requested, in the MESSAGE_DATA inner XML may look like

<Message>
    <Id>e86970f4-0455-4535-8e65-a06eb7aaef8a</Id>
    <SenderApp>999</SenderApp>
    <ReceiverApp>2000</ReceiverApp>
    <ServiceId>8798973454</ServiceId>
    <Mode>P</Mode>
    <MuxId></MuxId>
    <ExceptionCode></ExceptionCode>
    <ExceptionMessage></ExceptionMessage>
    <Body>
     <WorkItem xmlns="http://tempuri.org/WorkItem.xsd"&gt;
      <ServiceHeader xmlns="http://tempuri.org/Service.xsd"&gt;
       <ID_UPDATED_BY>username</ID_UPDATED_BY>
       <ID_HISTORY_REF>xxxxxxx</ID_HISTORY_REF>
       <SESSION_ID>sessionID</SESSION_ID>
       <DT_LAST_UPDATE>timestamp</DT_LAST_UPDATE>
       <TM_LAST_UPDATE>time</TM_LAST_UPDATE>
      </ServiceHeader>
     </WorkItem>
    </Body>
</Message>
A: 

Hi, I have some questions, am I correct that the actual xml you are extracting from the DB2 database will be something like:

<DB2Message>   
  <MESSAGE_DATA>   
    <EAIMessage>  
    <Header>  
    <ServiceID>  
    <MessageID>  
    ....  
    <Mode>   
    <Header>   
    <Body>    
    <RawXML>   
    <Body>  
    </EAIMessage>  
  </MESSAGE_DATA>   
  <MESSAGE_DATE>   
  <MESSAGE_ID>   
  <TXN_ID> ....  
<DB2Message>

What is meant to be in the RawXML element?
What does the schema you use to parse this into BizTalk look like - do you use CDATA to escape the contained XML?
Will the XML within the Message_Data element always match a known schema?

David Hall
The XML inside MESSAGE_DATA is not 100% matching the EAIMessage schema that the orchestration expects. But in general principle is somewhat like what you listed. So there has to be some mapping involving to place the fields correctly into an EAIMessage. RawXML is to take in MESSAGE_DATA as is.
icelava
So, in the schema that you use to extract data from Oracle, you have as xn:Any element (MESSAGE_DATA) that contains something like the EDIMessage? And Raw XML is just mapped as is?Does the xml fragment in MESSAGE_DATA match any schema, or can it change beyond a schema definition?
David Hall
Sorry, I found out in the actual project implementation, the DB2Message schema is _attribute_ based, not element based. I am updating my post above.
icelava
A: 

I would suggest looking into envelope schemas to 'unwrap' the interior message from the outer message. I believe the envelope can promote properties from the envelope into the inner message's context as it moves through the receive pipeline. The inner message will then have to map to a schema of its own type. You will then be able to route or make decisions based on the schema type and use XPath to pick out whatever you need. Have not tried all of these things, but I am certain the functionality exists to do do this.

ChrisLoris
A: 

Chris is correct - it seems it's only the inner part of the message you actually care about, the outer part is just an envelope.

As such I would suggest you create a disassembler which, in the receive pipeline, will strip out the envelope (you can keep it in it's entirety as a context property and/or extract some bits from it as individual properties, if you need to act on them), and extract the inner part which would become the message published into the Message Box.

Now the real message is the one get's processed, but the rest of the send port and any subscriber, and whatever information you require from the envelope flows with it through its context.

Now you have full access to the message and it's properties; if applicable you can deploy a schema for this message, which could have distinguished properties which would give you quick access to some (simple type) nodes. alternatively you can use xlang/s xpath to extract the information.

If your embedded message was inside an element in the envelope you could certainly use the built in XmlDisassembler to do all of this (you would just need to deploy your schemas correctly and configure the component accordingly; I'm not sure how well this works with a message contained within an attribute, but it's probably worth a try.

Worst case you are looking at writing a custom disassembler that would strip the envelope and then call the built-in disassembler to process the internal message, but that should not be too much effort as well.

Yossi Dahan