This solution has been achieved on a BizTalk Server 2013 R2 and requires the installation of NSoftware adapters v4.
Further details:https://www.nsoftware.com/adapters/biztalk/
As part of a recent client’s project, we encounter an unusual issue.
Here is a brief presentation:
The partner company of our client (called here “Y”) provides on scheduled time a batch of files to our client (called here “X”) on a FTP server. The main problem lies in the fact that X must get ALL the files present on the FTP folder at a specific moment AND add them in an Oracle database in a specific order. In our case, the messages sequencing is based on a date included in the body of the message itself. In a perfect world, this kind of scenario should be thought of in advance: for instance by sending the messages already in order and through a protocol able to ensure order (ex: Microsoft ServiceBus, MSMQ, IBM MQSeries…).
But thanks to the FTP adapter provided by NSoftware (https://www.nsoftware.com/adapters/biztalk/), this scenario can be completely managed with BizTalk.
Here are the details:
Here we will use a fairly unknown feature of FTP NSoftware adapter: option “DownloadSingleFile” (property ‘Other settings’ of the adapter). I invite you to browse through the documentation of the adapter (this one is rather well supplied and full of examples): https://cdn.nsoftware.com/help/EAB/bt/FTPConfig.htm
As said in the documentation, this option used on a send port allows to download a file instead of upload. What is quite unusual is to use a send port to receive messages and not a receive port. To do this, the send port must be used in “solicit-response”. We will use first a DIR that will return the list of files on the FTP then a loop which will get files 1 by 1.
Here are the steps of our flow:
In this situation, we need to plan the trigger of the recovering file process.
Here’s how, in our case, we manage this planning with the ‘Task Scheduler Windows’.
There are several ways to trigger an orchestration but in our case, the orchestration is activated in the following way:
set FilePath=D:\Data\EAI\…\Scheduler echo ^<Trigger xmlns^=”https://Monnamespace.Trigger”^> ^<Value^>1^</Value^> ^</Trigger^>>%FilePath%\triggerOrc.xml
*Beginning of orchestration:
intFilesNumber = xpath(msgDirResponse,”count(Directory/File)”);
*The send port configuration:
As mentioned previously, the send port adapter must be “nsoftware. FTP v4”. No special configuration for the 2 pipelines (PassThru), no maps and no filters (as binded to the orchestration).
Below the configuration of the adapter:
The most important element here is of course: ListDirectory=true to put in “Other”. This property tells the adapter we want to trigger a “DIR” in the remote FTP directory. In this way, the adapter knows that it must not return files but a list of the files in the directory.
*Loop to retrieve messages 1 by 1:
– Continuation of the orchestration
Note: this is not necessary in our case but we could quite “stamp” messages from the same batch by creating a custom promoted property that contains the number of the batch for example. Just as the InterchangeId does during a debatching.
– The send port configuration
Same principle as the previous one, the adapter must be “nsoftware FTP v4”. No special configuration for the 2 pipelines (PassThru for the send pipeline and XMLReceive in reception, no maps and no filters (as binded to the orchestration).
Below the configuration of the adapter:
As a bit earlier, the most important element here is in “Other”:
DownloadSingleFile=true
DeleteAfterDownload=true
The property DownloadSingleFile=true tells the adapter you want to retrieve a file whose name is specified in the nsoftware.BizTalk.FTP.RemoteFile context property.
The property DeleteAfterDownload=true indicates you want to delete the file after you download it.
*Optional: our issue-specific treatment:
– Sort messages
Reminder, the client requires the integration of the batch in a specific order (based on a functional date contained in the message).
To do this, we simply use a map with as source, our msgListeItemsTemp message and as destination a msgListeItemsOrdered, both of them of ListeItems type.
This map in full xslt looks something like this:
<s0:ListeItemsEnvelope>
<xsl:for-each select=”s0:Item”>
<xsl:sort select=”MyFunctionalDate data-type=”number” order=”ascending”/>
<xsl:element name=”s0:Item”>
<xsl:copy-of select=”./*” />
</xsl:element>
</xsl:for-each>
</s0:ListeItemsEnvelope>
– Messages debatching
Here, the choice was made of debatching messages by calling a pipeline directly in the orchestration.
I won’t well here on the use of a pipeline in an orchestration, as this could be the subject of another article.
Here is still the screenshot:
The result at the end of the Construct message shape a single message of type Item.
*Specific treatment and sending messages 1 by 1:
From there on, we are free to perform any processing / transformation on our message Item.
In our case, as you can see from the screenshot below, we simply apply a map (2) according to a certain status (1) recovered beforehand.
Then, as we are always in the loop that debatches our message of type msgListeItems, we will send messages 1 by 1 (3) on a send port (4). In our case, the binding is “Specify later” and the physical send port type is WCF-OracleDB.
With this solution, we can, therefore, guarantee to our client that at the time when the orchestration will be triggered, all the files on the FTP location will be listed, taken together and subsequently treated in the way of our choice.