May 2008 - posts - Marcel's SOA & BPM blog

May 2008 - posts

Writing Customer data from BizTalk 2006 R2 to SAP
Wednesday, May 07, 2008 11:37 AM

Writing data to SAP consists of 2 difficult steps. The first step is to get all the prerequisites from SAP installed on your BizTalk development machine. And the second is to understand the SAP data structures. You absolutely need a local SAP expert for this. For our proof of concept we were lucky. We were allowed to ignore SAP errors about missing underlying data structures. It was enough proof that we could receive the SAP customer ID and client ID, even though SAP did not accept our customer record.

You can choose to install the WCF LOB adapter for SAP before you install the actual prerequisites from SAP. When you do, it installs without problems. But when you start Visual Studio and start “Add Generated Items – Consume Adapter Service” you won’t see the sapBinding. You will only see the siebelBinding and the oracleBinding. You may also get a different error: if you see the sapBinding and fill in the required data, you press ‘Connect’ and poof: Visual Studio is gone. In order to get the sapBinding working you need to obtain the RFC SDK Unicode libraries from SAP and put them in your windows\system32 directory. For a detailed description refer to the installation manual “InstallationGuide.htm” included in the AdapterPack.

Once we got everything correctly installed, we could finally begin with the real interface to SAP.

1. First create a new BizTalk project in Visual Studio. Then right click on the project and select “Add Generated Items” -> “Consume Adapter Service”.

2. Then the LOB Adapter configuration dialog shows up.

- Select “sapBinding”from the “Select a binding”

- Bring up the SAP Adapter configuration by pressing the button “Configure”. At first the username and password for SAP are set.

Then at the URI properties the SAP connection properties are set.

In our case the following were set:

Application Server
System number
Client
Language

Then at the Binding properties ensure that the EnableBusinessObjects for Bapi is set to “True”. After clicking “Connect” on the “Consume Adapter Service” the adapter connects to SAP and gets all its metadata which is available. This includes BAPIs, IDOCs and RFCs.

3. Select BAPI and search in category using “Customer”, select the search result “http://Microsoft.LobServices.Sap/2007/03/BAPIOBJ/KNA1”.

After pressing the OK button BizTalk extracts some metadata from SAP and creates a schema for the BAPI and a BizTalk binding file for creating the messaging port for the BizTalk solution.
4. Create a simple BizTalk Orchestration which gets the xml message of the new Account to be created. The received message is sent to SAP and the response from SAP is used in updating CRM (MS Customer Dynamics). Note that the message context properties (OPEN, REUSE, CLOSE, and ABORT) should be used to enable transaction on a SAP system. For detail explanation see reference “Performing BAPI transactions by using BizTalk server”.

Example:

The following example shows that the “BAPICommitMessage” corresponding to BAPI_TRANSACTION_COMMIT for committing the transaction on the SAP system uses the context property “CLOSE”

BAPICommitMessage(Microsoft.Adapters.SAP.BiztalkPropertySchema.ConnectionState) = "CLOSE";

5. Ensure that the assembly is strong-named, in the solution explorer right-click the solution and then click Build Solution, after the solution successfully builds right-click the solution and then click “Deploy Solution”.

6. In the BizTalk Server Administration console, right-click the deployed application and then select Import àBindings. In the dialog box that opens navigate to the folder that contains the binding file created (Refer to step 3) and then click “Open”. This creates a preconfigured WCF Solicit-Response Send port with a WCF custom binding (sapBinding).

7. Modify some of the settings by right-clicking the WCF-Custom send port and selecting “Properties”. In the port properties dialog box do the following:

a. Click configure

b. Specify the connection URI (client number, language, server name, system number)

c. Click the “Credentials” tab and specify a user name and password to connect to the SAP system. Click “Ok”

d. Click the “General” tab; modify the action mapping of the SOAP action header to map an operation in the BizTalk Orchestration to an action in the LOB adapter (the selected BAPI call in the SAP adapter)

<BtsActionMapping>  <Operation Name="BAPIMessage" Action="http://Microsoft.LobServices.Sap/2007/03/Rfc/BAPI_CUSTOMER_CREATEFROMDAT1" />  <Operation Name="BAPICommitMessage" Action="http://Microsoft.LobServices.Sap/2007/03/Rfc/BAPI_TRANSACTION_COMMIT" /></BtsActionMapping>

The above is an example of how operations “BAPIMessage” and “BAPICommitMessage” are mapped to actions “http://Microsoft.LobServices.Sap/2007/03/Rfc/BAPI_CUSTOMER_CREATEFROMDAT1” and "http://Microsoft.LobServices.Sap/2007/03/Rfc/BAPI_TRANSACTION_COMMIT" in the LOB adapter.

The name of the operations “BAPIMessage” and “BAPICommitMessage” should correspond with the names of operations in the BizTalk Orchestration.
For detail explanation see reference “Specifying SOAP action”.

e. Create the remaining Receive and send-Ports and bind the Orchestration.

Authors

Marcel Fernee: marcel.fernee@microsoft.com
Henry Osagiede: henry.osagiede@atosorigin.com
Mark Wijngaarden: mark.wijngaarden@atosorigin.com
Mariёtte Mak: mariette.mak@atosorigin.com

Resources

BizTalk WCF LOB adapters

Obtaining the RFC SDK Unicode Libraries from SAP Service Marketplace
http://blogs.msdn.com/adapters/archive/2007/10/07/obtaining-the-rfc-sdk-unicode-libraries-from-sap-service-marketplace.aspx

Performing BAPI Transactions by Using BizTalk Server
http://msdn2.microsoft.com/en-us/library/cc185462.aspx

Specifying SOAP action
http://msdn2.microsoft.com/en-us/library/cc185151.aspx

Using the new BizTalk 2006 R2 SAP LOB Adapter
http://www.cubido.at/Blog/tabid/176/EntryID/128/Default.aspx

SAP Transaction
http://msdn2.microsoft.com/en-us/cc196386.aspx#sap

door Marcel Fernee | met no comments
Opgeslagen onder: ,
Creating a CallOut for MS CRM 3.0
Thursday, May 01, 2008 2:16 PM

A couple of weeks ago we had to do a proof of concept with BizTalk Server, Microsoft CRM and SAP. The proof of concept consisted of several parts. This blog entry will focus on the part where data has to be read from MS CRM.

The scenario we needed to implement was a follows:

1. Create account in MS CRM

2. Write account in SAP

3. Send e-mail to creator

In order to get account data out of MS CRM 3.0 and into BizTalk Server we used the CallOut mechanism. We first tried to use the BizTalk adapter for CRM, but it seems that this adapter only supports write (create, update, delete) actions. We haven’t found read actions in this adapter.

So CallOuts. As a BizTalk designer I was not too happy about the prospect of creating CallOut code. But it turned out quite simple. I found several pieces of sample code which I combined. And then with a little code of my own, it did everything we needed it to do. Plus it is event based, which is doesn’t have the timing or performance problems of polling.

At first we had to install Visual Studio 2003 on a machine that could connect to the CRM server. Visual Studio 2003 was needed to create .Net 1.1 assemblies. And the connection to the CRM server was needed to set the correct web reference. The code we started with was the calloutsample2 from the Microsoft CRM 3.0 SDK.

In order to get the e-mail of the person who created or modified the CRM record, we needed more data than that was available in the PostCreate account entity. We got a GUID of the person, but in order to get the e-mail address, we had to add a call to the CRM web service. The code to retrieve the e-mail (internalemailaddress) is listed in code snippit 1.

Bottom-line, to create a CallOut in CRM 3.0 for BizTalk to use you need to do the following.

1. Install Visual Studio 2003 on a PC with a network connection to the CRM Server.

2. Install the Microsoft CRM 3.0 SDK

3. Open the calloutsample2 project from the sdk

4. Paste the code snippits below in the calloutassembly.cs file

5. Set a reference to Microsoft.Crm.Platform.Callout.Base.dll
(Browse to the dll file)

6. Set a web reference to the CRM web service
(http://CRMSERVER/mscrmservices/2006/crmservice.asmx)

7. Compile

8. Modify the sample callout.config.xml
(remove what you don’t need)

9. Stop the IIS services on the CRM Server

10. Paste the created dll file into the C:\Program Files\CRM Server\server\assembly directory.

11. Paste the modified callout.config.xml file into the C:\Program Files\CRM Server\server\assembly directory.

12. Start the IIS services on the CRM Server

13. Restart the MS CRM Workflow service on the CRM Server

14. Done.

Start creating accounts and watch them appear in your file share.

There still is room for improvement for this piece of code. J
We now post files on a file share. To guarantee delivery of our messages MSMQ would be better.

 

public override void PostCreate(
   CalloutUserContext   userContext,
   CalloutEntityContext entityContext,
   String         postImageEntityXml
   )
{
   XmlDocument xd = new XmlDocument();
   xd.LoadXml(postImageEntityXml);

   switch(entityContext.EntityTypeCode)
   {
      case (int)EntityName.account:
         foreach(XmlElement element in       
            xd.GetElementsByTagName("Property"))
         {
            if(element.Attributes.GetNamedItem("Name").Value == "modifiedby")
            {
               // Set up the CRM Service.
               CrmService service = new CrmService();
               service.Credentials = System.Net.CredentialCache.DefaultCredentials;

               // Create the column set object that indicates the fields to be retrieved.
               ColumnSet cols = new ColumnSet();

               // Set the properties of the column set.
               cols.Attributes = new string [] {"internalemailaddress"};

               // Create the target object for the request.
               TargetRetrieveSystemUser target = new TargetRetrieveSystemUser();

               // Set the properties of the target object.
               // EntityId is the GUID of the record being retrieved.
               target.EntityId = new Guid(GetID(element.FirstChild.InnerText));
                        
               // Create the request object.
               RetrieveRequest retrieve = new RetrieveRequest();

               // Set the properties of the request object.
               retrieve.Target = target;
               retrieve.ColumnSet = cols;

               // Execute the request.
               RetrieveResponse retrieved = (RetrieveResponse)service.Execute(retrieve);

               CrmSdk.systemuser user = (systemuser) retrieved.BusinessEntity;
               element.FirstChild.InnerText = user.internalemailaddress + element.InnerText;
               WriteToFile(String.Format("\r\nCreate\r\n{0}\r\n\r\n\r\n{1}\r\n\r\n",RemoveNameSpace(postImageEntityXml), user.internalemailaddress));
                                       
            }
         }
         break;      
   }               
}

Code snippit 1: PostCreate()

 

private String RemoveNameSpace(String source)
{
   int i, j;
   String dest = String.Copy(source);
   String temp;

   do 
   {
      // start xsi:
      i = dest.IndexOf("xmlns");

      // end xsi:
      temp = dest.Substring(i+12);
      j = temp.IndexOf("\"");

      if(i != -1)
         dest = String.Concat(dest.Substring(0, i), dest.Substring( i+12+j+1));   
         
   } while(i != -1);
      
   do 
   {
      // start xsi:
      i = dest.IndexOf("xsi: ");

      // end xsi:
      temp = dest.Substring(i+10);
      j = temp.IndexOf("\"");

      if(i != -1)
         dest = String.Concat(dest.Substring(0, i), dest.Substring( i+10+j+1));   
      
   } while(i != -1);

   return dest;
}

Code snippit 2: RemoveNameSpace()

 

private string GetID(string id)
{
   //string adminID = "{56EEDA2E-D27F-DA11-B5D0-0003FF0BBE00}";
   string adminID = id;
   adminID = adminID.Replace("{", "");
   adminID = adminID.Replace("}", "");
   //WriteToFile(adminID);
   return adminID;
}

Code snippit 3: GetID()

The configuration file that we used was as in the sample sdk. We only removed the callout entities that we had not implemented.

CalloutConfig 
C:\Program Files\CRM Server\server\assembly\callout.config.xml

Authors

Marcel Fernee: marcel.fernee@microsoft.com
Henry Osagiede: henry.osagiede@atosorigin.com
Mark Wijngaarden: mark.wijngaarden@atosorigin.com
Mariette Mak: mariette.mak@atosorigin.com

Resources

Information on CallOuts in CRM 3.0
http://msdn2.microsoft.com/en-us/library/aa682477.aspx

Debugging Callouts
http://msdn2.microsoft.com/en-us/library/aa681366.aspx

Microsoft CRM 3.0 SDK
http://www.microsoft.com/downloads/details.aspx?familyid=9C178B68-3A06-4898-BC83-BD14B74308C5&displaylang=en

door Marcel Fernee | 1 comment(s)
Opgeslagen onder: ,
Creating and updating MS CRM data from BizTalk
Thursday, May 01, 2008 2:10 PM

A couple of weeks ago we had to do a proof of concept with BizTalk Server, Microsoft CRM and SAP. The proof of concept consisted of several parts. Mark Wijngaarden has written a blog on the part where we had to write from BizTalk Server to MS CRM.

We used the standard BizTalk MS-CRM adapter for this, also for writing to the custom CRM fields.

His blog is here: http://createupdatebiztalkaccountmscrm.blogspot.com/2008/04/create-update-account-in-ms-crm-30-with.html

My next blog will be about the part in the proof of concept where we had to create a CallOut from Microsoft CRM.

door Marcel Fernee | met no comments
Opgeslagen onder: ,