FILE & FTP adapter: Manipulating File Names

Published 18 June 04 06:58 PM | christof claessens

Very frequently, in the BizTalk Server newsgroups, I answer questions related to filenames used by the BizTalk Server FTP and FILE adapter. More in particular it seems that for many people it is hard to figure out:
- how to change the FILE/FTP adapter's output file name
- how to acces the FILE/FTP adapter's input file name

Let's change this and dive into the subject a little deeper:
...starting with the more easy thing: the FILE adapter's input and output filename.

When the FILE adapter receives a message, it promotes context on the message that contains information about the orginal filename. That context is accessible in:
  • a custom pipeline (where you'll have to program)
    • use the IBaseMessage you get passed by the pipeline framework
    • that interface provides you with a context property, which you can use to read promoted properties from
    • to give you a feeling, here's a (non-tested!) example:

      public IBaseMessage Execute(IPipelineContext pc, IBaseMessage inmsg)
      {
      //following namespace contains the FILE adapter properties:
      const string FILEadapterTargetNamespace = "http://schemas.microsoft.com/BizTalk/2003/file-properties";

      // retrieve the inbound file name that was promoted by the FILE adapter:
      string sourcePath = inmsg.Context.Read("ReceivedFileName", FILEadapterTargetNamespace ) as string;

      return inmsg;
      }
  • an orchestration (here you have intellisense)
    • drop in there an expression shape
    • you can access the context of you inbound message, using the context syntax (regular brackets after the messagename with in between the propertyname)


The FTP adapter does same thing upon receival of messages but obviously uses another context property to promote that information on.
It's namespace: http://schemas.microsoft.com/BizTalk/2003/ftp-properties
It's file name context property: ReceivedFileName

So far on the receival side of things, but what about sending? When sending files, the FILE and FTP differ somewhat in their approach...
Let's start again with the FILE adapter, where you basically have two options when you want to specify the outbound file name:
  • Using a static port: specify the outbound file name using one of the supported macro's

    This one's easy: the FILE adapter offers you some macros that you can use when binding the BizTalk Server messaging port.
    MSDN explains this very well, so I will not go into any details further here... (In addition I remember Jan already posted on this subject as well!)
  • Using a dynamic port: specify the outbound file name by setting context on the outbound message

    Setting context can be done both in a custom pipeline component as well as in an orchestrations expression shape. In any case, when using a dynamic send port in an orchestration, you should set the outbound URL. This can be done in any expression shape (you have intellisense for this). The engine will parse the URL and based upon the prefix (file:// or ftp://) it will use the correct adapter. In addition you may add other context as well (for example specifying the message's retry count).

    Setting context using a custom pipeline component is perhaps less straight forward, so let's look into this using a little sample:

    IBaseMessage Execute(IPipelineContext pc, IBaseMessage inmsg)
    {

    //following namespace contains the FILE adapter properties:
    const string FILEadapterTargetNamespace = "http://schemas.microsoft.com/BizTalk/2003/file-properties";

    // set the the outbound file name for the FILE adapter:
    inmsg.Context.Write("ReceivedFileName", FILEadapterTargetNamespace , "myOwnNewFileName.xml");

    return inmsg;
    }


So... that's it :-) Easy huh! The previous method can as well be used when having a static send port! If you explicitly set the filename in the context the FILE adapter will take this into account and won't use the "default" values specified for that BizTalk Server messaging port.

Now how does this work with the FTP adapter you might wonder? Unfortunately the FTP adapter does not have any macros you can use to set the outbound file name. However both the approach using the dynamic port as well as setting context manually works very well.

For example, inside an orchestration, I might set the location of a dynamic send port like this:

//Set dynamic ports location:
orchprtSndMyMessagePort(Microsoft.XLANGs.BaseTypes.Address) = "ftp://myserver/mydirectory/myfilename.xml";

//Set context on the message you want to send:
msgMyMessage(FTP.UserName) = "myFTPUsername";
msgMyMessage(FTP.Password) = "myFTPPassword";
msgMyMessage(BTS.RetryCount) = 20;
msgMyMessage(BTS.RetryInterval) = 2;


As illustrated, you'll need to specify the username and password for the connection as well. All together I guess this is not a bad approach at all. (Could be more user friendly but once you know, it dóes makes sense, right? In the end, évery adapter gets it's configuration from the message context!)

Very nice, very nice... but, what if you want to be able to transmit files in a particular order, or what if I want to grasp the return value from the FTP adapter's send operation?

There's no way you can grasp the return value of the FTP operation directly. Such kind of things is completely hidden by the adapter itself. BUT there's a way that allows you to know inside your orchestration wether the transmit operation succeeded. This is implemented using a switch on the level of your orchestration's send port, called: "DeliveryNotification". If set to "Transmitted", this will ensure that your orchestration stops working, until the adapter has succesfully transmitted the message. It's the same switch that allows you to send your messages in-order. In addition: if the message fails, an exception will be thrown of type: "XLang.DeliveryFailureException".

So far for files :-) If you have any further questions related to custom pipeline components... watch this blog! I will come back on this subject, showing you some very cool things!! (Obviously the newsgroups are still there as well.)

Have a nice day!
Filed under:

Comments

# Martijn said on June 21, 2004 06:01 AM:

I might ofcourse be mistakne, but my experiences is that orchestrations don't stop working if you just set the sendport delivery notification to "Transmitted", any logic you would have the orchestration doing only if your intermediate send completed successfully should be in a branch of a decide shape, where the decide expression uses XLANG/s "succeeded" operator, e.g.: !succeeded(Transaction_1). For an article about the succeeded operator, see Scott Colestock's blog entry at http://www.traceofthought.net/PermaLink,guid,abdd6ca2-e964-437d-8bee-0188ec5b5afa.aspx

# Christof Claessens said on June 21, 2004 07:02 PM:

Hi Martijn,

Your orchestration should STOP at the point of your send shape if the deliveryNotification was set to "transmitted". If not, please send me your scenario and I'll validate upon that.

(This does not mean that your orchestration stops working entirely of course!! If you have several branches running, these will stil be running in parallel.)

I know about the succeeded operator, which has a slightly other purpose...

Best regards!
Christof

# Patrick Wellink said on June 25, 2004 03:18 AM:

Hi Martijn,

See this Blog from Scto how to set up a scenario:

http://blogs.msdn.com/scottwoo/archive/2004/02/25/80037.aspx

The clou is I think the scope....


# Girija said on June 25, 2004 03:36 AM:

Hi,
Our client wants our xml to have
<element/> instead of
<element></element>,
when the lement in our output file is empty.
How do I do it in Biztalk?

Biztalk seems to put both the tags when the elements are empty, by default.

thanks,
Girija.

# Christof said on July 5, 2004 01:48 PM:

Hi Girija,

actually, the real "meaning" of those two constructs is exactly the same. The first one is just an XML shortcut for the second one. If they require you to send tags like the first, they do not comply with the XML standard. However, that still doesn't solve your problem. As for now, I'm not aware of any "switch" that allows to do this out of the box. (And to be honest: they should not provide this!) A custom pipeline component working with some XMLReaders and writers should do the job :-)

best regards,
christof

# Bovey King said on July 16, 2004 12:12 PM:

It does really help. I tried to figure out how to get ftp file name for a couple of days.

# José Ignacio said on August 3, 2004 02:14 PM:

Hi,

i'm trying to configure a ftp dynamic port and in my custom pipeline component i want to modify the context's properties of the user and password but I always receive this error

"The Messaging engine failed to process a message submitted by adapter:BizTalk HTTP Receiver Source URL:/httpReceive/BTSHTTPReceive.dll. Details:Could not find a matching subscription for the message. . This error occurs if the subscribed orchestration schedule or send port has not been started, or if some of the message properties necessary for subscription evaluation have not been promoted. Please refer to Health and Activity Tracking tool for more detailed information on this failure
"

i can't debug my custom component when the send port is dynamic, when the send port is static everything is okay. any idea?...

thank for your help

JI

Biztalk's fan club





# Christof Claessens said on August 3, 2004 04:27 PM:

Hi José,

I'm not sure about your story... Why can't you debug your custom pipeline component if the send port is dynamic? Just attach your debugger (VS.NET) to the BTSNTSvc.exe process. You should be able to attach without too much trouble. The error you receive is because the pub/sub engine is not able to match your message with any active subscription. What does your send port exactly do please?

I would strongly advise you to post technical issues to the BizTalk Server public newsgroups, where a lot of people will be happy to assist you.

Best regards,
Christof

# rajesh said on February 24, 2008 10:41 PM:

In the FTP adapter case, with out using orchestrations  how it is possible to set the outbound filename.

Leave a Comment

(required) 
(required) 
(optional)
(required)