Sunday, April 11, 2010

BizTalk Adapter Pack 2.0 – Part 3 Receiving multiple Flat File IDocs using SAP Adapter

In Part 2 of this series we discussed how you can receive IDocs from SAP in flat file format in order to avoid tight coupling with the version of SAP you are running as discussed in Post 1.

As I alluded to in the end of the Part 2 post, there is an issue when you include more than 1 IDoc schema in a Receive Pipeline that will be use the same Program ID and Receive location.

The behavior that I experienced when working through this scenario is the first message in my pipeline would be processed successfully but the second type(Vacations) would not.

 

 image

 

When I tried to process my 2nd type of IDoc (Employee Vacations) I would get the following error:

 

Event Type:    Error
Event Source:    BizTalk Server 2009
Event Category:    (1)
Event ID:    5719
Date:        4/11/2010
Time:        10:10:49 AM
User:        N/A
Computer:    *BizTalk Server*

Description:
There was a failure executing the receive pipeline: "SAPVersions.ReceiveSAPIDocs, SAPVersions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=147585b889447deb" Source: "Flat file disassembler" Receive Port: "ReceiveIDocsFromSAP" URI: "sap://CLIENT=XX;LANG=EN;@a/SAPSERVER/XX?ListenerGwServ=sapgwXX&ListenerGwHost=SAPSERVERci&ListenerProgramId=*ProgramID*&RfcSdkTrace=False&AbapDebug=False" Reason: Unexpected data found while looking for:
'Z2HR_WS_SEG000'
The current definition being parsed is idocData. The stream offset where the error occured is 520. The line number where the error occurred is 2. The column where the error occured is 0.

For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.

 

In the rest of the post I will discuss how you can fix this problem manually and then discuss the Hot Fix from Microsoft that addresses this situation.  I recommend proceeding with the Hot Fix route as it is a more sustainable solution.  The manual steps include modifying a schema that was generated by the Consume Adapter Service Wizard.  The risk is you can manually modify one of these schemas only to have a colleague regenerate the schema and overwrite your manual change.  If you do proceed with the Hot Fix route you will want to ensure any other developers that will be generating IDoc schemas are also using this Hot Fix.  I also want to highlight that this Hot Fix should be applied to developer’s workstations as this fix addresses a design time issue.

 

Fixing issue manually

  • Open up your schema that contains the “meat” of your IDoc information in an XML Editor view.  Whenever you generate  SAP IDoc schemas you are bound to have multiple XSD schemas created.  You can expect 1 IDoc that includes the various complex types, another that acts as the “Request” container IDoc, a Response xsd and the “meat” xsd which will include most of the “core” details of the schema.
  • Scroll down until you find a section that includes tag_name=”EDI_DC40” tag_offset="0" and replace it with tag_name="ZHR_VAC" tag_offset="39" where “ZHR_WS” is the name of your IDoc type.

image

 

image

 

  • What you will find as you open your schemas is that all of them will have this tag_name="EDI_DC40" tag_offset="0" string included in the IDoc which prevents BizTalk from distinguishing one IDoc from another.
  • Once you have modified all IDocs in this fashion, redeploy and you should find that both(in my case) IDocs were processed successfully.

image

Fixing issue with HotFix

  • In KB977528 Microsoft describes the issue as “This problem occurs because the first Flat file disassembler pipeline component in the custom pipeline tries to disassemble all the IDOCs that are received. However, the IDOCs should be processed by different Flat file disassembler components that have different schemas”.

  • When using the HotFix, you download schemas the same way as you previously did

image

  • Note when you open up the schema, you will now notice that the same change that we applied manually has now been incorporated into the schema definition automatically.

image

  • If you have changed the name of you XSD files, make sure you update your receive pipeline, deploy and restart your host instance(s).  You should now be able to receive both types of flat file IDocs without issue

image

 

Note:

My developer workstation is a 64 bit machine so when I navigated to the Hot Fix Web site it detected that my system was a 64 bit system and provided me with a 64 bit patch.  The problem is that Visual Studio runs in 32 bit mode and since this fix is a design time issue my issue was not resolved until I downloaded the 32 bit version of this KB.  I logged onto a 32 bit machine and navigate to the same site in order to get the 32 bit fix.

 

image

 

Thus far we have been  focusing on receiving IDocs.  A reader has asked if I can demonstrate how to sent a flat file schema to SAP using the BizTalk Adapter Pack so that will be the next post in this series.

Sunday, March 14, 2010

BizTalk Adapter Pack – SAP Binding ReceiveTimeout

 

One of the most important configurations to make inside a SAP Receive location is the “receiveTimeout” property.  The documentation describes this property as:

“Specifies the WCF message receive timeout. Essentially, this means the maximum amount of time the adapter waits for an inbound message. The default is 10 minutes.

Cc185372.Important(en-US,BTS.10).gifImportant

For inbound operations such as receiving IDOCs, we recommend setting the timeout to the maximum possible value, which is 24.20:31:23.6470000 (24 days). When using the adapter with BizTalk Server, setting the timeout to a large value does not impact the functionality of the adapter.”

The default value(10 minutes), is too short of a period for BizTalk to stop listening for messages from SAP.  For instance, if your organization has a weekly back up scheduled for SAP, it will likely take longer than 10 minutes.  The documentation indicates that there is no impact to using a large number so I am not sure why the default is only 10 minutes.

 

image

 

Just to give a practical example of what you can expect when SAP goes down (either planned or unplanned) from a BizTalk perspective.

SAP going down

Event Type:        Warning

Event Source:    BizTalk Server 2009

Event Category:                (1)

Event ID:              5740

Date:                     3/13/2XXX

Time:                     10:01:31 PM

User:                     N/A

Computer:          SERVER

Description:

The adapter "WCF-Custom" raised an error message. Details "The WCF service host at address sap://CLIENT=XXX;LANG=EN;@a/SAPServer/00?ListenerGwServ=SAPGateWay00&ListenerGwHost=SAPServer&ListenerProgramId=IDOC&RfcSdkTrace=False&AbapDebug=False has faulted and as a result no more messages can be received on the corresponding receive location. To fix the issue, BizTalk Server will automatically attempt to restart the service host.".

For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.

Event Type:        Warning

Event Source:    BizTalk Server 2009

Event Category:                (1)

Event ID:              5740

Date:                     3/13/2XXX

Time:                     10:01:31 PM

User:                     N/A

Computer:          SERVER

Description:

The adapter "WCF-Custom" raised an error message. Details "Microsoft.Adapters.SAP.RFCException: Details: ErrorCode=RFC_FAILURE. AdapterErrorMessage=An exception has occurred on the listener while executing RfcWaitForRequest..

   at Microsoft.ServiceModel.Channels.Common.Design.AdapterAsyncResult.End()

   at Microsoft.ServiceModel.Channels.Common.Channels.AdapterReplyChannel.EndTryReceiveRequest(IAsyncResult result, RequestContext& requestContext)

   at Microsoft.Adapters.Internal.LayeredChannelBindingElement.LayeredInboundChannel`1.System.ServiceModel.Channels.IReplyChannel.EndTryReceiveRequest(IAsyncResult result, RequestContext& context)

   at System.ServiceModel.Dispatcher.ReplyChannelBinder.EndTryReceive(IAsyncResult result, RequestContext& requestContext)

   at System.ServiceModel.Dispatcher.ErrorHandlingReceiver.EndTryReceive(IAsyncResult result, RequestContext& requestContext)".

For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.

 

Event Type:        Warning

Event Source:    BizTalk Server 2009

Event Category:                (1)

Event ID:              5740

Date:                     3/13/2XXX

Time:                     10:01:32 PM

User:                     N/A

Computer:          SERVER

Description:

The adapter "WCF-Custom" raised an error message. Details "The faulted WCF service host at address sap://CLIENT=XXX;LANG=EN;@a/SAPServer/00?ListenerGwServ=SAPGateWay00&ListenerGwHost=SAPServer&ListenerProgramId=IDOC&RfcSdkTrace=False&AbapDebug=False could not be restarted, and as a result no messages can be received on the corresponding receive location. BizTalk Server will continue trying to start the service host until it succeeds or the receive location is disabled.

To fix the problem, you may choose to:

1. Use the error information given to fix the problem.

2. Restart the receive location.

3. Keep waiting for BizTalk to recycle the service host. Another event will notify if the service host is successfully started.

SAP coming back up

Event Type:        Information

Event Source:    BizTalk Server 2009

Event Category:                (1)

Event ID:              8112

Date:                     3/13/2XXX

Time:                     11:03:13 PM

User:                     N/A

Computer:          SERVER

Description:

The WCF service host at address sap://CLIENT=XXX;LANG=EN;@a/SAPServer/00?ListenerGwServ=SAPGateWay00&ListenerGwHost=SAPServer&ListenerProgramId=IDOC&RfcSdkTrace=False&AbapDebug=False was successfully restarted, therefore the associated receive location can now receive messages.

For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.

 

You are now able to receive messages from SAP without any intervention.  Had we not set an appropriate ReceiveTimeout, the receive location would have still be down when SAP tried to push this IDoc to our system.

image

 

You never want your middleware to be the cause of an outage so it is important to understand when your dependant servers/services have scheduled maintenance so that you can ensure that your application can sustain this downtime.  Configuring the ReceiveTimeout to an appropriate value will reduce the chance that BizTalk will be down due to someone else's maintenance window.

BizTalk Adapter Pack 2.0 – SAP Adapter IDoc Schema Versioning Part 2

In my first post, I discussed how the BizTalk Adapter pack Consume Adapter Service wizard tightly couples the IDoc schema version with the version of SAP that you used to generate the schema with.  The goal of this post is to discover how you can avoid this tight coupling and hopefully survive an SAP upgrade.  I know the organization that I work for would not be pleased with having to update all of our IDoc schemas when we do our next SAP Upgrade just because the version of SAP has been incremented.

When the BizTalk Adapter Pack came out I was pretty excited that I could throw away my Flat File schemas and pipelines.  While true, it comes at a cost.  When using the XML Receive pipeline with the new Adapter, the Adapter will use data in the SAP Control record to determine what version of the message you retrieving from SAP and will assign a namespace to your message, that contains SAP version information, before depositing it in the message box. If have not changed your SAP version since generating your IDocs you are in business.  If you have upgraded your SAP system or have generated the wrong schemas for your SAP version then you will be in a lot of pain. 

To get around this tight coupling issue, you can revert back to the old style of IDoc processing which involves flat files and pipelines.  Now there is nothing really wrong with this model, but it does require a few extra steps and is not as “clean” a solution as using the XML Receive pipeline.

I will now take you through how you generate a flat file schema that can be used to process different versions of the same IDoc.  When I say different schemas this means that the version, and therefore namespace, are different but structurally the documents are the same.  Note that I will not go through all steps required to generate an IDoc schema, only those that are important to generate a Flat File schema.  To see a more comprehensive walk through of generating an IDoc schema, please see my Webcast.

 

  • When using Consume Adapter Service wizard, ensure that “GenerateFlatFileCompatible” is set to true.

image

When you set the GenerateFlatFileCompatible property to true, you will now see the flat file specific data within the Schema specification.

image

Without setting GenerateFlatFileCompatible ,  the schema will not contain this flat file information.

image

image

  • You also want to indicate the “ReceiveIDocFormat” will be a String.  You will find out why this is important later on in this post.

image

  • Once the schemas have been imported into Visual Studio, enable “Flat File Extensions” to the “core schema”.  When using the BizTalk Adapter Pack Consume Adapter Service wizard you will generate more than 1 schema unlike the old .Net Connector version where you would always only generate 1 schema.  By “core schema” I mean the one that contains the “meat” of your schema, not one that contains the shell(all of the imported schemas) or any of the base type schemas.

image

  • You will now need to create a Receive Pipeline and add a Flat File disassembler

PipelineComponentDesigner

  • Add your “shell” schema to the document schema property

image

  • Build and Deploy your application
  • When configuring your SAP Receive location you will want to specify your Receive Pipeline as opposed to XML Receive

image

  • On the Binding tab, set the “ReceiveIdocFormat” to String

image

  • On the Messages tab, provide an XPath expression that will extract the flat file data so it can be disassembled by the Receive Pipeline.  The XPath expression that I used is:

    /*[local-name()='ReceiveIdoc']/*[local-name()='idocData']

    The adapter is essentially wrapping this flat file in XML tags so that it can make it through the adapter stack as an XML message. 

    Also ensure the “Node encoding” is set to String as the default is “XML”

image

  • Start your application and you are good to go

 

  • Up until this point, I have not modified the namespace of my schema and everything worked well as expected

image 

 

  • However, the purpose of this post is to demonstrate how we can break away from the default namespaces that are generated by the adapter.

image

  • Since I have redeployed the application, the message subscription have also been updated:

 image

  • Start your application up and it should function with this new namespace and therefore subscription.

 

  • The next test is to generate a different version of an SAP IDoc and ensure receiving a different version of the IDoc does not break our application.  If you recall from Post 1 we received an error in this situation.  From the Consume Adapter Service wizard, I am deliberately going to generate a schema that has a DOCREL  greater than my current SAP version.

image

  • My subscription is updated and is looking for a “710” IDoc where as SAP is going to generate a
    “700” IDoc

image

  • I received, processed and delivered the message downstream without issue

image

  • Even though SAP, populated the Control record with DOCREL = 700, I am able to process this message because this DOCREL is not being used to derive the target namespace like it is when you use the XML Receive pipeline.  This is really where the value of the Flat file pipeline comes in as it will use the namespace in the schema that is configured inside the pipeline instead of having the Adapter generate a namespace automatically.   This also works as the structure of the 700 IDoc has not changed in the 710 IDoc.  If the structure of the IDoc changes with the version number then you have no other option than to regenerate your schemas.

image

 Gotcha!

So everything is fine and dandy until you try to deploy another IDoc with the same Program Id/Partner Profile.  There is bug with the BizTalk Adapter Pack that prevents you from deploying multiple IDoc Flat File schemas with the same Program ID.  Look for a workaround with my next post in this series.  I should be able to turn that post around quicker than this one.

Monday, March 1, 2010

Off Topic: Canada Wins....Mikael loses

During this past MVP summit there was an abundance of trash talk regarding Olympic Hockey. Mikael Hakanssons and I made a Blog bet with the loser of the bet dedicating a post to the winning country. As I am sure you have heard, Canada beat USA in overtime 3-2 on Sunday. I will give Mikael credit for being a good sport even though he jumped on the USA bandwagon as soon as Sweden was eliminated. You can find his post here.

Saturday, February 27, 2010

Consuming a BizTalk hosted WCF Service with InfoPath 2007

I recently built a POC that wrapped an SAP RFC call in a WCF Service exposed by BizTalk. I exposed schemas as WCF services instead of opting for exposing the Orchestration as a WCF Service. The purpose of the Service was to validate a utility meter’s status inside of SAP.  Some of the statuses may include active/inactive/meter not found.  The RFC that I used is called RFC_Read_Table.  This is a pretty generic, out of box,  RFC that allows you to query SAP tables.  The RFC is fairly complex due to a lack of good documentation available.  Perhaps I am just not part of the secret SAP consultant’s club where you can actually get useful documentation.  I plan on documenting my findings in an upcoming post so that other people do not have to endure the pain I went through in order to get it working.

 

One of the benefits of InfoPath is the ability to consume a web service (asmx).  I was pleasantly surprised that InfoPath can also consume some  WCF endpoints(.svc).  The endpoint type that I exposed was based on the basicHttpbinding which happens to be one of the more interoperable bindings.  At this point, the SOAP adapter has been identified as an Adapter that will be removed in an upcoming release of BizTalk.  The idea behind this is that people should be moving to the WCF adapter.  There are some gaps between the SOAP and WCF adapter, which is outside the scope of this post, but my advice would be if you can use the WCF Adapter then you should.  If you cannot, due to a limitation, then you should provide this feedback to Microsoft so they can either enhance the WCF adapter or hold off on removing the SOAP adapter.

 

The InfoPath service consumption wizard is fairly straight forward with the exception of  “how the form works with the Web Service”.  The 3 options that you do have include:

  • Receive and submit data
  • Submit data
  • Receive data

 

When I think of a client consuming a Web Service, I think in terms of the client providing a Request message and the Server providing a Response.  With this in mind, I decided to use the “Submit data” option.  What I ran into is that I could submit data to my BizTalk Service, BizTalk would process the request and provide a response but nothing was being updated in my form.  I discovered that I needed to use the “Receive and submit data” option instead.  The description is counter intuitive as it implies I am receiving data first then I am submitting it.  Perhaps if Microsoft would have called this option “Submit and receive data” this would have been a little clearer.

 

I have recently been teased by a few colleagues and friends about the amount of detail and screen shots that I have put in my blog posts.  At the risk of more torture,   here is a step by step guide of how I got this all working.

  • Design a Form Template

image

 

  • Select “Web Service'” and click OK

image

 

  • If you want to submit data to a service and use the response data in your form, select “Receive and submit data'”

image 

 

  • Provide the destination of your WSDL and click “Next”

image

  • The name of my operation is “ValidateMeter”, click “Next”

image

  • Thus far, the information that has been provided is related to the Web Service response so I have provided a name for this data connection that reflects this.

image

  • Since I am submitting data to this same service, I need to provide the WSDL URL again.

image

  • Once again I need to provide the operation that I will be communicating with.

image

  • The “ValidateMeter” operation has a single input parameter.  I need to specify which field from the request schema will be sent to the Web Service.  To do this I want to click on the following button: image 

 

image

  • Select the field from Schema

image

  • Click “Next” to proceed

image

  • I now need to provide a name for this data connection

image

 

  • At this point I have a blank canvas and I also have the ability to start dragging and dropping fields from my Web Service Request and Response schemas onto the canvas.

image

 

  • I have expanded, the “queryFields” node and have dragged the “MeterNumber” element onto the canvas.  If you recall the value that will be populated in this field will be sent as part of the Request message to the ValidateMeter Service.

image

  • When BizTalk provides the response from SAP, I want to display this value on the form.  In order to do this, I need to expand the “dataFields” node and select “MeterStatus” from the Web Service Response schema.

image

 

  • To test my form, I can click on the “Preview” button

image

  • I can now provide a Meter Number and click the “Run Query” button.  Within a couple seconds I will see my Meter Status text get populated.  In this particular instance, the Meter Number 123456 does not exist so the Meter Status text box is updated to reflects this.

image

Friday, February 26, 2010

BizTalk 2009: BizTalk Mapper - get value from last node

I ran into a situation where I needed to get the last value from a re-occurring node that SAP was returning.


In order to extract the last record, I utilized the Record Count functoid and fed that value into the Index functoid. The Index functoid is also fed with the value from the "WA" element that I am really interested in. The result is then passed to a String Concatenate functoid where the data is enriched before being assigned to the destination document.

Tuesday, January 19, 2010

BizTalk Adapter Pack 2.0 – SAP Adapter IDoc Schema Versioning Part 1

A colleague and I have been working through some anomalies when it comes to SAP IDoc schemas that were generated using the BizTalk Adapter Pack 2.0 SAP Adapter. This is the adapter which is based upon WCF and NOT the .Net Connector based adapter.

When you go to generate an IDoc using the Consume Adapter Service wizard in Visual Studio, you will be presented with a screen like this. You will most likely have a few options when selecting an IDoc and version to use. To be sure that you have selected the right version of IDoc, you should contact your BASIS admin.image

As you select different versions of IDocs, notice that the Node ID changes. This Node ID will soon become your Target Namespace in the XSD schema that you are about to generate.

image

This Target Namespace is very important since BizTalk uses the Target Namespace and root node to determine subscriptions.

image

If you have chosen the wrong version of IDoc you will soon know. You will receive a subscription error indicating that you have received a message that BizTalk does not have a Schema for.

Event Type: Error

Event Source: BizTalk Server 2009

Event Category: BizTalk Server 2009

Event ID: 5719

Date: 1/17/2010

Time: 1:54:31 PM

User: N/A

Computer: Server

Description:

There was a failure executing the receive pipeline: "Microsoft.BizTalk.DefaultPipelines.XMLReceive, Microsoft.BizTalk.DefaultPipelines, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" Source: "XML disassembler" Receive Port: "WcfReceivePort_SAPBinding_IdocZHR_KPV3R710_Custom" URI: "sap://CLIENT=XXX;LANG=EN;@a/SAPSERVER/XX?ListenerGwServ=SAPGWXX&ListenerGwHost=SAPSEVER& ListenerProgramId=XXXXXX&RfcSdkTrace=False&AbapDebug=False" Reason: Finding the document specification by message type "http://Microsoft.LobServices.Sap/2007/03/Idoc/3/ZHR_KP//700/Receive#Receive" failed. Verify the schema deployed properly.

If you refer to the first image in this blog post, you will see that the Node Id has a value of http://Microsoft.LobServices.Sap/2007/03/Idoc/3/ZHR_KP//710/Receive#Receive where as BizTalk has received an IDoc with a Namespace of http://Microsoft.LobServices.Sap/2007/03/Idoc/3/ZHR_KP//700/Receive#Receive. So how can this be? SAP by default generates an IDoc based upon the current release version. But you also have the ability to send a specific IDoc version as configured in the SAP Program ID. This provides some flexibility in the event you need to use a legacy IDoc version.

When SAP sends an IDoc out, it will populate this version information in the control record. I have turned on tracking on the receive port and as you can see this information has been populated by SAP.

image

Since I am using an XML Receive pipeline and SAP has no idea what namespace BizTalk is requiring, the SAP Adapter is generating this namespace at run-time based upon the DOCREL and IDOC_VERSION elements.

The lesson here is to make sure you know what version of the IDoc is currently configured with your Program Id within SAP. I must also caution that while this approach does work, it may not live through your next SAP upgrade. At least not without updating your BizTalk projects. With each SAP major release, you can expect this DOCREL value and potentially the IDOC_Version to increase. So the next time you upgrade your SAP environment, you may get into the same situation that I have described(subscription errors) and it may take some significant refactoring to get your BizTalk schemas and maps back in sync with your SAP version.

In the next post of this series, I will discuss how you can use a Receive Pipeline and Flat File Pipeline Disassembler to override this namespace so that it does not become dependant upon the DOCREL and IDOC_VERSION elements…stay tuned.