Sep 302008
 

This seems to be a big complaint, there are many companies that would like to have access to the envelope information in the map. There are a few VERY KLUDGY ways of getting data from the message into the map. All of them are VERY BRITTLE. The EDI logger now will create an additional message part called ‘envelope’ and send it to the message box.

If you are familiar with the multi part message that the BTAHL7 accelerator creates, this will be a breeze. For those of you not in the provider world, I will walk through the instructions on how to create a process to access the envelope information (you will see that there is a LOT more than just the envelope information).

To start off with, there are now two message parts to the message that shows up in the message box. The body part is the transaction itself (so you can still use the message in a send port map if necessary).

Here is a screen shot of the multi part message:

MultiPartEnvelope

The schema that is deployed to the GAC that you can reference (C:\WINDOWS\assembly\GAC_MSIL\EDIArchiveProperties\1.0.0.0__e7dd178931a8d66e\EDIArchiveProperties.dll) in your project that will host your orchestration has this structure (click to enlarge):

ContextDataSchema

I normally create at least two different projects for each solution. One that represents the schemas, and the other that represents the mapping/orchestrations. For simplicities sake, I have called the schema project Schemas, and the location that I am going to put my maps and orchestrations will be called Logic. Here is a snapshot of the Solution Explorer:

SolutionExplorer1

I added the reference to the EDIArchiveProperties by adding a reference and pasting the dll mentioned above:

AddReference

 

Let’s create an orchestration, here you will want to create a multi-part message, making sure you define the body segment first and then the envelope segment second (click to enlarge):

MultiPartMessage

Next you will create the necessary port and message from this multi-part message. I will jump to the creation of the map. You have a message defined from this multi-part type and you are mapping it to an output. You open up the map configuration dialog window and you fill in two lines, one that represents the envelope and the other that represents the EDI transaction on the input and the output message on the destination window.

MapDialog1

MapDialog2

And when pressing <OK>, this is the map that is created (click to enlarge), notice that the transaction is at the bottom of the source:

Map

 

This allows you to access both the envelope and context data for that transaction, giving you the ability to map everything that would need to without going through a unnecessary hoops to get data injected into the message.

For pricing on this component, please refer to our services page.

Sep 302008
 

By popular demand I have made some significant changes to the EDI logger. None I don’t think are more important than the rest, but some do address a REAL thorn in a lot of peoples sides. I will get to that in the next entry about the change to the message. This one deals with the pipeline itself. Below is a picture of the receive pipeline configuration:

Receive Pipeline Configuration

The send pipeline configuration:

Send Pipeline Configuration

And the following table on how to configure the values:

Row Type Meaning
Database string BAM Database to store data
Server string BAM Server to store data
Active boolean Activates the logging mechanism, if not, it is simply a pass thru pipeline component
Count1 string Either XPath or Regex.Match (string count)
Count2 string Either XPath or Regex.Match (string count)
Count3 string Either XPath or Regex.Match (string count)
FromAddress string email address representing BizTalk as source
FromName string Friendly Name representing FromAddress (ex: BizTalk Prod biztalkprod@company.com)
Notify boolean Activate flag for email notification
NotifyOnlyOnError boolean Only send out email if there are validation errors
SMTPHost string SMTP Host address
Secure boolean True: Do not include ISA01/02/03/04 as components to be used
False: Include ISA01/02/03/04 as components to be used
SubjectLine string Macros and regular text to create customized email subject line
ToAddress string Allows multiple email addresses to be included in email notification (semicolon separates email addresses)
Sep 272008
 

I have come across this a lot and finally was sick of it enough to write about it.

The situation is I have an input that has a bunch of optional fields, and the output is normally a fixed length record file. In my case it is normally an EDI file of some kind that I am mapping to a flat file layout. When I start testing the map, I get the following error produced by the flat file assembler:

Error details: Unable to read the stream produced by the pipeline. Details: Cannot find definition for the input: Address

The reason is that there was no Address in the source data, but the output required it to be there to conform to the flat file layout. If you look at this page from msdn on how to force the creation of elements that are optional. Yes, this is possible, but in my case, I would be creating a script for every element I am creating, which would amount to hundreds of scripting functiods.

Underlying logic: The mapper when dragging optional source items to a required destination item creates the following logic in XSLT:

<xsl:template match="/s0:File"> <ns0:File> <xsl:if test="@Name"> <Name> <xsl:value-of select="@Name" /> </Name> </xsl:if> <xsl:if test="@Address"> <Address> <xsl:value-of select="@Address" /> </Address> </xsl:if> <xsl:if test="@City"> <City> <xsl:value-of select="@City" /> </City> </xsl:if> <xsl:if test="@State"> <State> <xsl:value-of select="@State" /> </State> </xsl:if> <xsl:if test="@Zip"> <Zip> <xsl:value-of select="@Zip" /> </Zip> </xsl:if> <xsl:value-of select="./text()" /> </ns0:File> </xsl:template>

The easy solution, create a second map that maps the destination input to the destination output (and easy way to do this is by following these autolink directions). This creates the following XSLT:

<xsl:template match="/ns0:File"> <ns0:File> <Name> <xsl:value-of select="Name/text()" /> </Name> <Address> <xsl:value-of select="Address/text()" /> </Address> <City> <xsl:value-of select="City/text()" /> </City> <State> <xsl:value-of select="State/text()" /> </State> <Zip> <xsl:value-of select="Zip/text()" /> </Zip> <xsl:value-of select="./text()" /> </ns0:File> </xsl:template>

Notice that there are not any if tests.

You can chain the maps together in an orchestration, or you can place the map in the receive port and the straight thru map in the send port.

What would be nice is to have a map setting called Force Optional Creation Mapping set default to No to leave the behavior as currently is, but if set to Yes, the underlying logic would remove the xsl:if from the map an force the creation of the destination elements regardless of the presence of the input.

Sep 242008
 

To give the ability to customize the subject line in the new email component of the EDI logger, you can use following macros:

Macro Description
%ISA01% ISA01 Value
%ISA02% ISA02 Value
%ISA03% ISA03 Value
%ISA04% ISA04 Value
%ISA05% ISA05 Value
%ISA06% ISA06 Value
%ISA07% ISA07 Value
%ISA08% ISA08 Value
%ISA09% ISA09 Value
%ISA10% ISA10 Value
%ISA11% ISA11 Value
%ISA12% ISA12 Value
%ISA13% ISA13 Value
%ISA14% ISA14 Value
%ISA15% ISA15 Value
%GS01% GS01 Value
%GS02% GS02 Value
%GS03% GS03 Value
%GS04% GS04 Value
%GS05% GS05 Value
%GS06% GS06 Value
%GS07% GS07 Value
%GS08% GS08 Value
Other Values Description
%Adapter Type% Adapter Type of receive transmission
%Received Filename% Received ftp or file name
%AdapterReceive Completed Time% When file was picked up
%Port Name% Port Name of receive location
%Inbound Transport Type% Inbound Transport Type
%Receive Location Name% Receive Location Name
%Message Type% Message Type (http://namspace#rootelement)
%ISA Segment% Entire ISA Segment (beware that private information might be displayed)
%GS Segment% Entire GS segment
%Party Name% Party Name
%Transaction% Transaction
%Transmission ID% ID that represents entire transmission
%Error Flag% ‘Yes’ or ‘No’ – if there were validation errors or not
%Count 1 Query% Entire text contained in the Count 1 pipeline field
%Count 1% Actual value of query 1
%Count 2 Query% Entire text contained in the Count 2 pipeline field
%Count 2% Actual value of query 2
%Count 3 Query% Entire text contained in the Count 3 pipeline field
%Count 3% Actual value of query 3
%Error Description% Entire error description
%FileGUID% Unique ID representing this transaction
%Inbound Transport Location% Pickup Location

Which will create an email that looks like this:

EDILoggerSampleEmail

Sep 232008
 

An issue that I recently came across was when we upgraded our servers from BizTalk 2006 to BizTalk 2006 R2 is that we were unable to see the new EDI features. This is the context menu I saw when right clicking the parties:

firstContextMenu

Which is incorrect, try I should be seeing this context menu:

secondContextMenu

The resolution is that after you upgrade the server, you need to need to modify the installation in the add/remove programs and choose Modify:

addRemove1

Check the BizTalk EDI/AS2 Runtime:

addRemove2

Afterwards, you need to go into the BizTalk Configuration and configure the new EDI components (I already did this):

addRemove3

Then you get all of the components you are looking for.

Sep 122008
 

I have come across this issue eleventeen million times, so I figure I would write about it (finally).

The issue: I want to extract data from a repeating record, but I need the output records based on something that is higher up the food chain. If I simply use the logical equals and value mapping or value mapping (flattening) funtiods, if the qualifier is the first occurrence it will successfully extract the data, otherwise it will not pull the data out.

Here is a screen shot of an 837 map that shows the issue in the 2000 REF segment:

innerlooping

 

For simplicity’s sake, I have created a smaller map:

smallInnerloop

Here is the input:

<ns0:Root xmlns:ns0="http://Schemas.Input"> <Record> <SubRecord Qualifier="AA"> <Data>Here is AA Data</Data> </SubRecord> <SubRecord Qualifier="ZZ"> <Data>Here is ZZ Data</Data> </SubRecord> </Record> </ns0:Root>

I want to extract the /Root/Record/SubRecord/Data where the Qualifier is ZZ, but I want to create it driven on the /Root/Record

By using the out of the box functiods, I get the following output:

<ns0:Root xmlns:ns0="http://Schemas.Output"> <Record> </Record> </ns0:Root>

Which is not what I wanted.

There are two ways to extract the data. The first is to use three functiods, a string concatenate functiod to a cumulative concatenate functiod, to a script functiod like this:

  innerloopinganswer1

The string concatenate functiod’s arguments are the following:

concatonatearguments

The cumulative concatenate functiod:

cumulativeconcatonate

And the arguments to the script functiod:

scriptarguments

And the C# script inside the script functiod:

public static string extractFromInnerLoop(string qualifier, string segmentTerminator, string data) { string actualdata=""; int posOfDelimiter = qualifier.Length; if(posOfDelimiter>data.Length) goto end; string delimiterValue = data.Substring(posOfDelimiter, 1); string fullQualifier = qualifier + delimiterValue; int locOfFullQualifier = data.IndexOf(fullQualifier); if (locOfFullQualifier < 0) { actualdata = ""; goto end; } int posOfSegment = data.IndexOf(fullQualifier); int segmentEnd = data.IndexOf(segmentTerminator, posOfSegment); int elementLength = segmentEnd-posOfSegment-fullQualifier.Length; actualdata = data.Substring(posOfSegment+fullQualifier.Length,elementLength); end: return actualdata; }

It works, but I thought that there must be a better approach. A second approach is to use Inline XSLT Call Template:

xsltscript

The arguments to the script:

xsltarguments

and the Inline XSLT Call Template script:

<xsl:template name="SubLoopExtract"> <xsl:param name="qual" /> <xsl:element name="Data"> <xsl:value-of select="SubRecord[@Qualifier = $qual]/Data/text()" /> </xsl:element> </xsl:template>

Both of them create the following output:

<ns0:Root xmlns:ns0="http://Schemas.Output"> <Record> <Data>Here is ZZ Data</Data> </Record> </ns0:Root>

Sep 102008
 

I’ve used this quite a bit on BTS 2004.  Instead of deploying projects through Visual Studio, sometimes I want to just overwrite the DLL in the GAC, restart BizTalk, and start using it.

Here’s one of the easier ways to do this:

Create a .reg file with the following text.

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\dllfile\shell\gacutil\command]

@=”c:\\WINDOWS\\Microsoft.NET\\Frame­work\\v1.1.4322\\gacutil.exe /i \”%1\” “

Double click the .reg file and right click on the strongly named .DLL to see the new menu item.