none
Problems handle SAP-Transaction with WCF-custom adapter RRS feed

  • Question

  • Hello,

    I have a problem while using the new SAP-Adapter (
    Microsoft BizTalk Adapter 3.0 for mySAP Business Suite) in my Biztalk-Orchestration (Biztalk 2006 R2, OS: Windows 2003 server).

    Here comes a short description of my process:
    We get a flatfile with order data from our customer. I'am using a pipeline to disassemble the data, group them to the ordernumber and start one orchestration (A) for each ordernumber. This orchestration A enrich the data with some SAP-masterdata (by calling suborchestrations with BAPI-calls) and mapp the data at the end of the orchestration A to a new message associating the xml-schema "BAPI_SALESORDER_CREATEFROMDAT2". I have swapped out the call of the bapi BAPI_SALESORDER_CREATEFROMDAT2 in a seperate orchestration (B), because I want to reuse it for other customer processes.
    In the suborchestration B I call the BAPI_SALESORDER_CREATEFROMDAT2 with the message property (Microsoft.Adapters.SAP.BiztalkPropertySchema.ConnectionState) = "OPEN" and after a success response I send a BAPI_TRANSACTION_COMMIT (with message property (Microsoft.Adapters.SAP.BiztalkPropertySchema.
    ConnectionState) = "CLOSE")
    or after a failure I send a BAPI_TRANSACTION_ROLLBACK (with message property (Microsoft.Adapters.SAP.BiztalkPropertySchema.ConnectionState) = "ABORT" ). I designed the orchestration B based on the Microsoft-sample "SAPTransaction.sln".

    This is my problem:
    When I run my Biztalk-application the following error occurs for each orchestration I have started:

    System.InvalidOperationException: The Inner Channel to use was not found for the key {AED96A21-6BF5-4655-AEAF-4F565F00A358}_{E66DA192-8BDB-4C04-BEBA-FCBEF575D513};URI=sap://Client=123;lang=DE@a/xxx.xxx.xxx.xxx/xx. Specify a valid key.

    Server stack trace:
       bei System.ServiceModel.AsyncResult.End[TAsyncResult](IAsyncResult result)
       bei System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result)
       bei System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
       bei System.ServiceModel.Channels.ServiceChannel.EndRequest(IAsyncResult result)

    Exception rethrown at [0]:
       bei System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
       bei System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
       bei System.ServiceModel.Channels.IRequestChannel.EndRequest(IAsyncResult result)
       bei Microsoft.BizTalk.Adapter.Wcf.Runtime.WcfClient`2.RequestCallback(IAsyncResult result)
     MessageID: {F0AF4082-8708-43E9-91BC-58BC0335E1B2}
     InstanceID: {562B300A-D39A-4E1C-8A60-737809DF47E3}

    Here are my bindings of the SAP-sendport (WCF-custom adapter): 
    ==> enableBizTalkCompatibilityMode = true
    ==> autoConfirmSentIDocs = false
    ==> enableBusinessObjects = false
    ==> enableConnectionPooling = false
    ==> enablePerformanceCounters = false
    ==> enableSafeTyping = true
    ==> flatFileSegmentIndicator = SegmentDefinition
    ==> generateFlatFileCompatibleIdocSchema = true
    ==> idleConnectionTimeout = 00:15:00
    ==> maxConnectionsPerSystem = 50
    ==> padReceivedIdocWithSpaces = false
    ==> receiveIDocFormat = Typed

    This is very confusing:
    When I start the orchestration B as a stand-alone orchestration (without calling from the orchestration A) then the Salesorder is created successfully at the sap system. But sometimes while the orchestrations are busy (I think when the connection is broken) all of the open orchestrations stop their work and produce the same mistake as written above.

    This is my suspicion:
    I'am not very familiar with WCF, but I think the WCF-client (used by the Biztalk WCF-custom adapter) opens only one channel for all orchestrations and after a network or logon failure to the SAP system the channel stack is corrupt and all of the orchestrations aborts. Unfortunalety I can only configure the WCF-adapter at the context menu in the Admin console.

    I don't find any help in the web (google, msdn, etc.). Has anyone a idea why my orchestration B don't work as suborchestration, respectively what the message
    The Inner Channel to use was not found for the key ... Specify a valid key. means ?

    Thank you very much for your help.
    Alex
    Friday, September 12, 2008 12:43 PM

Answers

  • Hi Alex,

     

    Can you try your scenario with a input containing just one record (order) so that just one instance of orchestration 'A' and one instance of 'B' are started. Let us know if that works fine?

     

    I don't think using sub-orchestrations is the culprit here. What I suspect is this:

     

    Since the individual records belong to the same interchange, all the dissassembled messages have the same interchange-id (and same SPID since it's the same send port). The Adapter uses "Interchange-Id + SPID" combination as the key to route messages to appropriate channels. In this case, after the 'Close' or 'Abort' call is received from one of the orchestrations, the other messages would get the error you are seeing.

     

    If this is indeed the case (that is, if a single record scenario works for you), we can work on alternate design to make the scenario work.

     

     

    Monday, September 15, 2008 6:52 AM

All replies

  • The Adapter opens a WCF-Channel when it receives the OPEN message, reuses that same channel for all subsequent REUSE messages (provided they were all disassembled from the same input compound message), and then finally closes the channel when it sees a CLOSE message (again, provided the message was disassembled from the same input compound message). 

    Also, all messages (OPEN, REUSE, CLOSE, ABORT) must be sent to the same Send Port. You also need to disable retries on the Send Port (set Retry count to 0). If a message fails, you need to retry the entire compound message.

    Is it possible for you to upload your project somewhere and paste a link here, so that we can take a look?

    Mustansir



    Friday, September 12, 2008 1:00 PM
  • Hello Mustansir,

    thank you very much for your fast answer.

    When we retrieve a faltfile with (for example) 5 orders, after the disassembling level I start 5 seperate orchestrations A and they start also 5 seperate orchestrations B to communicate with the SAP system. Inside of each orchestration B I call the bapi BAPI_SALESORDER_CREATEFROMDAT2 with connectionstate OPEN and respecitvely BAPI_TRANSACTION_ROLLBACK with connectionstate ABORT or BAPI_TRANSACTION_COMMIT with connectionstate CLOSE. I don't use the connectionstate REUSE, cause I have only one BAPI SalesOrderCreate to call.
    So, in my opinion, the WCF client opens 5 channels (one for each orchestration B) and handle the SAP transaction for every orchestration within the WCF-channel. Is that wright ? But why this succeeded only, when the orchestration B runs as a stand-alone orchestration and not by calling as a suborchestration from the main orchestration A ?
    And, for whatever reasons, the orchestrations aborts with the WCF failure The Inner Channel to use was not ... specify a valid key. ?

    All of the message use the same sendport and the retry count is set to 0, too.

    Alex
    Friday, September 12, 2008 1:35 PM
  • Hi Alex,

     

    Can you try your scenario with a input containing just one record (order) so that just one instance of orchestration 'A' and one instance of 'B' are started. Let us know if that works fine?

     

    I don't think using sub-orchestrations is the culprit here. What I suspect is this:

     

    Since the individual records belong to the same interchange, all the dissassembled messages have the same interchange-id (and same SPID since it's the same send port). The Adapter uses "Interchange-Id + SPID" combination as the key to route messages to appropriate channels. In this case, after the 'Close' or 'Abort' call is received from one of the orchestrations, the other messages would get the error you are seeing.

     

    If this is indeed the case (that is, if a single record scenario works for you), we can work on alternate design to make the scenario work.

     

     

    Monday, September 15, 2008 6:52 AM
  • Hello Tushar,

    your hint was very helpful. As you accepted, the interchangeID is actually the same for all orchestrations which were started after the order data was disassambled from the reiceive location. The first one or two orchestrations has done there work successfully; all the following orchestrations aborted with the known message above.
    Now the behavior of the wcf client makes definitely sense. All transaction were started with the same interchangeID and sendportID (yes, it's always the same sendport) and the first transaction(s) in orchestrations B were committed positively, until one orchestration B sends a message with the property connectionstate = "close" or "abort". Then the WCF-channel is closed and the other busy orchestrations B abort with the error "The inner channel ... was not found.".

    This means for me, I have to create a unique interchangeID for all orchestrations A which were started after the receiving pipeline work. Are there any possibilities to generate a unique interchangeID for all disassambled messages, or can I change this ID inside the current orchestration A ?

    Tushar, thank you very much for your help.

    Alex
    Monday, September 15, 2008 12:54 PM
  • Hi Alex,

     

    Glad to know that cause of the issue is nailed

     

    As for the alternatives, I think generating unique Interchange-Id's should be doable, for example, by creating a copy of the message inside 'A' before you call 'B'. (I'm not sure though, I'll try to do some investigation and get back to you on whether this is possible / advisable).

     

    However please be aware, that with this approach, you'll lose the benefits that interchange id's provide in the first place - that is, tracking which individual message (order) belonged to which composite message. However, it looks like in your case, you are more interested in tracking what happens to the individual orders rather than to whole interchange, right? 

     

    Is it possible in your scenario to somehow dissassemble the messages before they enter BizTalk? In that case you can simplify the whole design as you'll not need 'A' at all.

     

    Another possibility, if performance is not too much of a concern, is to sequetially process the individual orders instead of doing that in parallel. (That is for each order, Open, 'Do Work' and Close or Abort).

     

    Thanks,

     

    Tushar

    Monday, September 15, 2008 1:44 PM
  • Hi Tushar,

    thanks for your help and the options you are shown.
    - As you assumed, the benefit of the interchangeID is not important for this process.

    - To disassemble the orderfile outside the biztalk-server is not so practicable, cause this is one of the strength of the biztalk-server and so we loose this benefit.

    - To handle the orderfile processing in one orchestration in a loop is also no option, cause every file containes more than hundred orders.

    So my decision was to generate a new GUID for every instance of orchestration B and link this GUID to the BAPI_SALESORDER_CREATE message and the corresponding BAPI_COMMIT or BAPI_ROLLBACK message and it work's fine !!

    If anybody, reading this thread, has any questions to this process or solution, please contact me over this thread.

    Tushar, thank you for help,

    Alex


    Tuesday, September 23, 2008 8:11 AM
  • Hi Alex,

     

    We are experiencing the same problem as you did. Can you please explain further how you solved it?

     

    Thanks in advance!

     

    Regards,

    Jörgen.

    Thursday, December 4, 2008 12:23 PM
  • Hi,


    Having issues with the same symptoms here. The solution described in this thread does not work for our situation, however.

    We are trying to create SAP user accounts by calliing BAPI_USER_CREATE1 through a WCF-custom port. Because we are servicing multiple SAP-systems, and because the set of SAP-systems in which the users have to be created is provided in the message, we decided that we would need a dynamic WCF-Custom port to call the BAPI's.

    Below, a number of scenarios we have tried so far, and the behaviour that was observed. (notes: All consecutive calls aimed at a single SAP system and client going through the same single port. Already the first set of calls results in problems).

    (1) Calling BAPI_USER_CREATE1 and BAPI_USER_COMMIT from their own orchestration (called from a central orchestration). Using connection states OPEN and CLOSE. The inner channel id (interchange id) was checked (instance guid _ send port guid) and equal for both calls. When the process attempts to call the commit-part, this results in a runtime error about the inner channel: "Specify a valid key".

    (2) Setup same as (1) but without setting the connection state. No runtime error this time. The commit-call returns a response-message that has a single instance of the return-structure, with initial values. Note that the commit has been performed, though!

    (3) Using the dynamic port could be part of the problem. So, we switched to a static port with two operations. Both actions (Create and Commit) were called on the same port from a single orchestration. Retry set to 0. Connection states OPEN and CLOSE were used. Result: same as for (2).

    (4) Setup same as (3) but without setting the connection state. Result: same as for (2) and (3).

    Conclusions so far:

    (a) Using a dynamic port seems to be influencing the behaviour of a transaction involving multiple Bapi-calls. This is probably due to the fact that the dynamic port is instantiated during runtime. In a newsgroup posting, somebody suggested that the dynamic ports are created "in process" and can therefore not be "connected" in a transaction-like setting. I have found that both calls use the same identification of the inner channel (instance id combined with send port id).

    (b) Apparently, something causes the commit. Not clear what is causing this. The intentionally called BAPI_TRANSACTION_COMMIT does not show the expected behaviour, that is clear. Case (2) shows this. Looking at the differences between cases (1) and (3), it looks as if (3) might be setting up a valid transaction (because we do not have the runtime error about the inner channel), but when as part of this BAPI_TRANSACTION_COMMIT is called, the commit already has taken place (or: is done at that time without giving the correct response).

    No clues anymore. Thanks to this thread I have developed knowledge about the details of calling BAPI's in a transactional setting. The test cases have not lead to a working solution so far.

    Anybody has an idea what could be causing the commits? Maybe a wrong basic connection setting? Maybe the commit after all? But why no real content in the response in that case?

    Thanks in advance. Erwin

    • Edited by Erwin1103 Wednesday, September 30, 2009 7:12 PM Typo
    Wednesday, September 30, 2009 7:04 PM
  • Hi,

    BAPI transactions are not supported over Dynamic Send Ports.


    We made some design changes in a recent hotfix, as a result of which BAPI transactions are now possible using Dynamic Ports.
    [We are going to officially support the scenario only from the next release , but it should work for you currently.]
    The hotfix is already released for BAP 1.0 and will very soon be released for BAP 2.0.


    You can get in touch with PSS to get the hotfix(internal name RFH3310).

    • Proposed as answer by Erwin1103 Thursday, October 1, 2009 5:33 PM
    Thursday, October 1, 2009 8:08 AM
  • Hi Rohit,

    Thanks for this. I will check what we will do with the advance correction.

    However, this explains only part of our observations. I was already "suspecting" the combination of a dynamic port and a BAPI transaction. For this reason, I changed to a statically bound port. To exclude other possible bias, I also moved the commit into the very same orchestration that performs the actual operation. But still no content in the response from the commit-BAPI.

    Erwin
    Thursday, October 1, 2009 5:33 PM
  •  There are two BAPI transaction models-

    1. BAPI Transaction Model (Without Commit)-

     

    2. Old BAPI Transaction Model (with Commit)

                                                                       

     Can you make sure that you are using BAPI Transaction Model (Without Commit).


    -Rohit

     

    Sunday, October 4, 2009 9:30 AM