...by Daniel Szego
"On a long enough timeline we will all become Satoshi Nakamoto.."
Daniel Szego

Sunday, November 1, 2015

Integrating MatchPoint with SAP (a step by step initial approach)

Integrating MatchPoint with SAP is pretty easy as a first approach. You have to do two things: 
- get an SAP connector to read out some information from SAP
- implement a data provider in MatchPoint with the SAP adapter to use the imported data.

So let we have the steps in details:
STEP 1. Let we assume that we want to see the controlling area names from SAP controlling:

Figure 1. List of controlling areas in SAP.

STEP 2. Let we create some integration with SAP, there are many ways of doing that ranging from BAPI calls to web service integration through Netweaver. I m choosing the most simple SAP .NET connector
STEP 3. Let we create a Visual Studio project console application and reference the SAP.NET connecor dlls: sapnco.dll and sapnco_utils.dll. I am probably using a little bit old version, because for me it was working only with .NET framework 4.0 and not with 4.5 or higher. 
STEP 4. Let we create a basic connection class named SAPSystemConnectMP to store the SAP connection information, like port, system number, access information...:

    public class SAPSystemConnectMP : IDestinationConfiguration
        bool IDestinationConfiguration.ChangeEventsSupported()
            return true;
        public event RfcDestinationManager.ConfigurationChangeHandler ConfigurationChanged;
        RfcConfigParameters IDestinationConfiguration.GetParameters(string destinationName)
            if ("K47".Equals(destinationName))
                RfcConfigParameters parms = new RfcConfigParameters();
                parms.Add(RfcConfigParameters.AppServerHost, "");
                parms.Add(RfcConfigParameters.SystemNumber, "00");
                parms.Add(RfcConfigParameters.User, "root");
                parms.Add(RfcConfigParameters.Password, "***");
                parms.Add(RfcConfigParameters.Client, "800");
                parms.Add(RfcConfigParameters.Language, "DE");
                parms.Add(RfcConfigParameters.PoolSize, "50");
                parms.Add(RfcConfigParameters.MaxPoolSize, "100");
                parms.Add(RfcConfigParameters.IdleTimeout, "6000");

                return parms;
            return null;

STEP 5. Let we create a wrapper class for the ControllingArea, with the static setup procedure that calls the BAPI_CONTROLLINGAREA_GETLIST Bapi and from the result takes the CONTROLLINGAREA_LIST table and lists all controlling area name and code.

   public class ControllingArea
        public string ControllingAreaCode;
        public string ControllingAreaName;

        public static List<ControllingArea> getAllControllingAreas(RfcDestination destination)
            List<ControllingArea> ret = new List<ControllingArea>();

            RfcRepository repo = destination.Repository;
            IRfcFunction controllingAreaList = repo.CreateFunction("BAPI_CONTROLLINGAREA_GETLIST");

            IRfcTable controllingAreas = controllingAreaList.GetTable("CONTROLLINGAREA_LIST");

            for (int cuIndex = 0; cuIndex < controllingAreas.RowCount; cuIndex++)
                controllingAreas.CurrentIndex = cuIndex;
                ControllingArea area = new ControllingArea();
                area.ControllingAreaCode = controllingAreas.GetString("CO_AREA");
                area.ControllingAreaName = controllingAreas.GetString("Name");
            return ret;

STEP 6. Let we implement a MatchPoint Data Provider, of course after referencing the MathcPoint dlls, possibly from the development kit : Colygon.MatchPoint, Colygon.MatchPoint.Server and Colygon.MatchPoint.Snow.

    public class SAPDataProvider : BaseDataProvider
        public string[] List;

        public override BaseDataProviderInstance CreateInstance(string cacheKey, IEnumerable<string> columnNames)
            return new SAPDataProviderInstance(cacheKey, this, columnNames);

STEP 7. Last but not least let we implement a data provider instance. Perhaps the most important part of the instance is the GetInternalData function. It opens an SAP connection through the configured connection class, queries all the controlling areas and transforms the names to a simple string list.

   public class SAPDataProviderInstance : BaseDataProviderInstance
 private readonly SAPDataProvider provider;

 public SAPDataProviderInstance(string cacheKey, SAPDataProvider provider, IEnumerable<string> columnNames) : base(cacheKey, columnNames)
  this.provider = provider;

 protected override CachePolicy CachePolicy
  get { return new CachePolicy(CacheGranularity.NoCache, 0); }

 protected override IEnumerable<object> GetInternalData()
            SAPSystemConnectMP sapCfg = new SAPSystemConnectMP();
            catch(Exception ex){}
            RfcDestination rfcDest = RfcDestinationManager.GetDestination("K47");
            List<ControllingArea> cAreas = ControllingArea.getAllControllingAreas(rfcDest);
            List<string> res = new List<string>();
            foreach (ControllingArea area in cAreas)

            provider.List = res.ToArray<string>();
            return provider.List;

 public override string GetCacheToken()
  return null;

STEP 8. Having compiled,we have to registrate everything in GAC (the SAP connector DLLs as well) and we have to registrate the DataProvider in the matchpoint configuration as an external assembly and of course IISreset at the end.

Figure 2. MatchPoint Configuration.

STEP 9. If everything went well, you have to see the new dataprovider in your system. So as an test we can create a composite WebPart setting the SAPDataProvier and showing with a pattern transformer the DataItem.

Figure 3. Composite WebPart configuration.

STEP 10. If everything wen well, you should see the list of Controlling Areas directly from SAP.

Figure 4. Controlling area information in MatchPoint from SAP.