Saturday, August 15, 2009

Dynamically passing the file name to read adapter



Sync Read option in BPEL file adapter allows us to read the file from the middle of the process, this is different from the Read option which polls for the new files and is the start of the BPEL process.

As we design the file adapter for sync read it asks for the file name whcih is static, this means that only file with this given name will be read. Now suppose if we need to read files having same format but different names. How are we going to do that?

I found this question posted on the oracle forums http://forums.oracle.com/forums/thread.jspa?threadID=935976&start=0&tstart=0 that is when I worked on it and found the solution.

There's a simple way to do this. Whenever we create an adapter a fileAadapterOutboundHeader.wsdl file is created. If we open this file we'll find an inline schema having the fileName element. Below is the fileAadapterOutboundHeader.wsdl file:

<definitions
name="fileAdapter"
targetNamespace="http://xmlns.oracle.com/pcbpel/adapter/file/"
xmlns:tns="http://xmlns.oracle.com/pcbpel/adapter/file/"
xmlns="http://schemas.xmlsoap.org/wsdl/" >

<types>
<schema attributeFormDefault="qualified" elementFormDefault="qualified"
targetNamespace="http://xmlns.oracle.com/pcbpel/adapter/file/"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:FILEAPP="http://xmlns.oracle.com/pcbpel/adapter/file/">
<element name="OutboundFileHeaderType">
<complexType>
<sequence>
<element name="fileName" type="string"/>
</sequence>
</complexType>
</element>
</schema>
</types>
<!-- Header Message -->
<message name="OutboundHeader_msg">
<part element="tns:OutboundFileHeaderType" name="outboundHeader"/>
</message>

</definitions>


While invoking the adapter we only need to set this fileName element with some dynamic generated value. Below are the steps to do this:

  1. Double click the invoke activity which invokes the sync read adapter.

  2. Go to adapters tab and click the torch icon.

  3. Click on Variables and create a new variable.

  4. Give some name like OutboundheaderVariable, choose message type and click the torch.

  5. Drill down to fileAadapterOutboundHeader.wsdl > Message Types and select OutboundHeader_msg. Click Ok till you are back in the diagram.

  6. Place an assign activity above this invoke and copy the file name to the OutboundHeaderVariable > fileName variable.

That's it.

Now we can give the name of the file at runtime as the input parameter or we can define deployment descriptor to give the file name.

We can also set the input/output directory at runtime which I'll write in my next post.

20 comments:

  1. hi suryaveer, this topic is extreamely good. thanks a lot for you help.

    ReplyDelete
  2. Hi Suryaveer,

    Can we do batching using the same logic

    ReplyDelete
  3. @ArchitectView
    You do batching when your BPEL is polling for file or while writing but the above example is for passing the file name when you are reading the file in the middle of a running BPEL process. Also you can not pass the file name when you poll for the files.

    ReplyDelete
  4. I am using Oracle SOA Suite 11g and dont see the filename element in the schema. Schema is as follows:


    Please help. Thanks, Prafull

    ReplyDelete
  5. @Prafull

    In 11g you can set the fileName in the invoke activity itself. Go to the invoke activity of the adapter, click the properties tab and find jca.file.Filename property. You can set this property.

    ReplyDelete
  6. Can we do this same way for Outbound file writing process as well? Can we change the file name dynamically?

    ReplyDelete
  7. Yes we can do while writing as well.

    ReplyDelete
  8. Hi Surya..
    Im trying to use a file adapter with synchronous read in my mid process.When I created,two files got generated synchronousreadfile_file.jca and synchronousreadfile.wsdl.I did not find any fileAadapterOutboundHeader.wsdl in my folder as per your explanation whenever a file adapter gets created. Now how should i let my process know to pick the new file and directory info.where can i find this info.what should i mention in jca.file.filename and jca.file.Directory in the invoke option.Im using soa 11g.

    ReplyDelete
  9. @Ritisha
    When I wrote this I was working on 10g. In 11g fileAdapterOutboundHeader.wsdl is not generated. You can set the properties in the invoke activity of the adapter. You'll find a properties tab on double clicking the invoke activity, in that tab you will find several properties. You can set whichever you need either dynamically or hardcode it.

    ReplyDelete
  10. I have an issue that I need to get the filename first so I do a ListFiles call and then SynchRead this works except for files with spaces in it which it seems to take the spaces out and therefore the FTP GET fails. Is there some config for getting round this issue?

    ReplyDelete
  11. Hi Surya

    I have a scenario where you read a file an adapter and write it to another file. Here I want the write file to be dynamically chosen. In this case I think I can't use something like the above mentioned process 'coz i will not use the console to give any input. Can you let me know how I can handle this?

    ReplyDelete
  12. I recently began to study SOA and I have a question. How to use the file adapter and BPEL to determine that the record in the output file is competed and move this file to the other directory?

    ReplyDelete
  13. I recently began to study SOA and I have a question. How to use the file adapter and BPEL to determine that the record in the output file is competed and move this file to the other directory?

    ReplyDelete
    Replies
    1. You can mention an archive directory. All the successfully processed files are placed in the archive directory.

      Delete
  14. This comment has been removed by the author.

    ReplyDelete
  15. Hi Surya,
    Thanks for this post. It is really good.
    I have one question if we want to read the file using the file reader and wants to insert the record in DB. If user put the same file multiple time then how do we stop entring the duplicate record in DB?
    One way that come in my mind, we can use SP and put the logic there like before making insert it checks for the record in DB but is there any way in BPEL process to stop entring duplicate record in DB.

    ReplyDelete
    Replies
    1. BPEL won't be knowing what is already there in the DB so you have to handle that at DB level only.

      Delete

 
Protected by Copyscape DMCA Copyright Detector