Showing posts with label SAP MDM API. Show all posts
Showing posts with label SAP MDM API. Show all posts

Search In a MDM Repository

Following code snippet shows the step to search inside MDM repository. It searches the string inside field Vendors in the table Vendors under repository Vendor1 .

public class Connection {     private SimpleConnection simpleConnection;     private String serverName = " ";     private String repositoryName="Vendor1";     private String dbServerName = " ";     private DBMSType dbmsType = DBMSType.MS_SQL;     private RegionProperties dataRegion = new RegionProperties();     private String userSession;     private String repositorySession;     private String userName="Admin";     private String password="mdm";     private RepositorySchema schema;     private RepositoryIdentifier repositoryID;     public void getConnection() {         try {             if (simpleConnection == null) {                 simpleConnection =                     SimpleConnectionFactory.getInstance(serverName);             }         } catch (Exception e) {             //              }     }         public void closeConnection( )       {         //@@begin closeConnection()         try{             if(simpleConnection!=null){                 DestroySessionCommand destroySessionCommand=new DestroySessionCommand(simpleConnection);                 destroySessionCommand.setSession(userSession);                 destroySessionCommand.execute();                 userSession=null;                 simpleConnection.close();             }         }catch(Exception e){
//                    }         //@@end       }           public void getAuthenticatedUserSession( )       {         //@@begin getAuthenticatedUserSession()         /*             * Create and authenticate a new user session to an MDM repository             */            repositoryID=new RepositoryIdentifier(repositoryName,dbServerName,dbmsType);            CreateUserSessionCommand createUserSessionCommand=new CreateUserSessionCommand(simpleConnection);            createUserSessionCommand.setRepositoryIdentifier(repositoryID);            createUserSessionCommand.setDataRegion(dataRegion);            try {                createUserSessionCommand.execute();                    userSession=createUserSessionCommand.getUserSession();// Get the session identifier               /* Authenticate User Session */            TrustedUserSessionCommand trustedUserSessionCommand=new TrustedUserSessionCommand(simpleConnection);            trustedUserSessionCommand.setUserName(userName);                      trustedUserSessionCommand.setSession(userSession);            try {                trustedUserSessionCommand.execute();                userSession=trustedUserSessionCommand.getSession();            } catch (CommandException e1) {                /* Trusted Connection is not accepted */                AuthenticateUserSessionCommand authenticateUserSessionCommand=new AuthenticateUserSessionCommand(simpleConnection);                authenticateUserSessionCommand.setSession(userSession);                authenticateUserSessionCommand.setUserName(userName);                authenticateUserSessionCommand.setUserPassword(password);                authenticateUserSessionCommand.execute();                    }                   SetUnicodeNormalizationCommand unicodeNormalizationCommand=new SetUnicodeNormalizationCommand(simpleConnection);            unicodeNormalizationCommand.setSession(userSession);            unicodeNormalizationCommand.setNormalizationType(SetUnicodeNormalizationCommand.NORMALIZATION_COMPOSED);            unicodeNormalizationCommand.execute();            }catch (CommandException e2) {
//                         }       }           public void setRegionProperties( )       {         //@@begin setRegionProperties()         dataRegion.setRegionCode("engUSA");         // Set the locale on data region         dataRegion.setLocale(new Locale("en", "US"));         // Set the name of data region         dataRegion.setName("US");         //@@end       }     public void setRepositoryInfo( java.lang.String repositoryName, java.lang.String userID, java.lang.String password )      {        //@@begin setRepositoryInfo()        this.repositoryName=repositoryName;        this.userName=userID;        this.password=password;            //@@end      }           public void getAuthenticatedRepositorySession( )     {       //@@begin getAuthenticatedRepositorySession()           try{               CreateRepositorySessionCommand repositorySessionCommand=new CreateRepositorySessionCommand(simpleConnection);               repositorySessionCommand.setRepositoryIdentifier(repositoryID);               repositorySessionCommand.execute();               repositorySession=repositorySessionCommand.getRepositorySession();                       AuthenticateRepositorySessionCommand authenticatedRepositorySession=new AuthenticateRepositorySessionCommand(simpleConnection);               authenticatedRepositorySession.setSession(repositorySession);               authenticatedRepositorySession.setUserName(userName);               authenticatedRepositorySession.setUserPassword(password);               authenticatedRepositorySession.execute();                       GetRepositorySchemaCommand repositroySchemaCommand=new GetRepositorySchemaCommand(simpleConnection);               repositroySchemaCommand.setSession(repositorySession);               repositroySchemaCommand.execute();               schema=repositroySchemaCommand.getRepositorySchema();                           }catch(CommandException e){
//                        }catch(Exception e){
//                        }               //@@end     }         public com.sap.mdm.ids.FieldId getFieldID( java.lang.String tableName, java.lang.String fieldCode )       {         //@@begin getFieldID()             return schema.getField(tableName,fieldCode).getId();             //@@end       }           public com.sap.mdm.ids.TableId getTableID( java.lang.String tableName )       {         //@@begin getTableID()         return schema.getTable(tableName).getId();         //@@end       }           public void searchRepository() {             //@@begin searchRepository()             ResultDefinition resultDef =                 new ResultDefinition(schema.getTable("Vendors").getId());             resultDef.addSelectField(schema.getField("Vendors", "Name").getId());             //resultDef.addSelectField(new FieldId(15));             FieldSearchDimension searchDimension =                 new FieldSearchDimension(                     schema.getField("Vendors", "Name").getId());             TextSearchConstraint constraint =                 new TextSearchConstraint("ABC", TextSearchConstraint.CONTAINS);             Search search = new Search(schema.getTable("Vendors").getId());             //search.addSearchItem(searchDimension,constraint);             RetrieveLimitedRecordsCommand limitedRecordsCommand =                 new RetrieveLimitedRecordsCommand(simpleConnection);             limitedRecordsCommand.setSearch(search);             limitedRecordsCommand.setSession(userSession);             limitedRecordsCommand.setResultDefinition(resultDef);             try {                 limitedRecordsCommand.execute();             } catch (CommandException e) {                 //                          }             //return limitedRecordsCommand.getRecords();             RecordResultSet recordSet = limitedRecordsCommand.getRecords();             String recordAsString = null;             String fieldValue = null;             for (int i = 0; i < recordSet.getCount(); i++) {                 recordAsString = "";                 FieldId[] returnedFields = recordSet.getRecord(i).getFields();                 for (int j = 0; j < returnedFields.length; j++) {                     if (recordSet                         .getRecord(i)                         .getFieldValue(returnedFields[j])                         .isNull()) {                         fieldValue = " |";                     } else {                         fieldValue =                             recordSet.getRecord(i).getFieldValue(returnedFields[j])                                 + "|";                     }                                         recordAsString += fieldValue;                     System.out.println(recordAsString);                 }             }         }                 public static void main (String[] args)                 {             Connection test=new Connection();             test.getConnection();             test.setRegionProperties();             test.setRepositoryInfo("Vendor1","Admin","mdm");             test.getAuthenticatedUserSession();             test.getAuthenticatedRepositorySession();             test.searchRepository();             test.closeconnection();              }

}

Code to Get List of Validation in a Table

Following code snippet finds out the list of Validation from a Table.

package com.sap.infosys.mdm.validationcheck;

import com.sap.mdm.commands.AuthenticateUserSessionCommand;
import com.sap.mdm.commands.CommandException;
import com.sap.mdm.commands.CreateUserSessionCommand;
import com.sap.mdm.commands.DestroySessionCommand;
import com.sap.mdm.commands.GetRepositoryRegionListCommand;
import com.sap.mdm.data.RegionProperties;
import com.sap.mdm.ids.TableId;
import com.sap.mdm.net.ConnectionException;
import com.sap.mdm.net.ConnectionPool;
import com.sap.mdm.net.ConnectionPoolFactory;
import com.sap.mdm.server.DBMSType;
import com.sap.mdm.server.RepositoryIdentifier;
import com.sap.mdm.validation.ValidationProperties;
import com.sap.mdm.validation.ValidationPropertiesResult;
import com.sap.mdm.validation.commands.RetrieveValidationsCommand;


public class GetListOfValidations {     public static void main(String[] args) {         // create connection pool to a MDM server         String serverName = " ";         ConnectionPool connections = null;         try {             connections = ConnectionPoolFactory.getInstance(serverName);         } catch (ConnectionException e) {             e.printStackTrace();             return;         }         // specify the repository to use         // alternatively, a repository identifier can be obtain from the GetMountedRepositoryListCommand         String repositoryName = "Vendor1";         String dbmsName = " ";         RepositoryIdentifier reposId =             new RepositoryIdentifier(repositoryName, dbmsName, DBMSType.MS_SQL);         // get list of available regions for the repository         GetRepositoryRegionListCommand regionListCommand =             new GetRepositoryRegionListCommand(connections);         regionListCommand.setRepositoryIdentifier(reposId);         try {             regionListCommand.execute();         } catch (CommandException e) {             e.printStackTrace();             return;         }         RegionProperties[] regions = regionListCommand.getRegions();         // create a user session         CreateUserSessionCommand sessionCommand =             new CreateUserSessionCommand(connections);         sessionCommand.setRepositoryIdentifier(reposId);         sessionCommand.setDataRegion(regions[0]); // use the first region         try {             sessionCommand.execute();         } catch (CommandException e) {             e.printStackTrace();             return;         }         String sessionId = sessionCommand.getUserSession();         // authenticate the user session         String userName = "Admin";         String userPassword = "mdm";         AuthenticateUserSessionCommand authCommand =             new AuthenticateUserSessionCommand(connections);         authCommand.setSession(sessionId);         authCommand.setUserName(userName);         authCommand.setUserPassword(userPassword);         try {             authCommand.execute();         } catch (CommandException e) {             e.printStackTrace();             return;         }         // the main table, hard-coded         TableId mainTableId = new TableId(1);         // Get the list of validations         RetrieveValidationsCommand objRtvVldCmd =             new RetrieveValidationsCommand(connections);         // set the user session         objRtvVldCmd.setSession(sessionId);         // get validation for the following tables.         objRtvVldCmd.setTableId(mainTableId);                 try {             objRtvVldCmd.execute();         } catch (CommandException e) {             e.printStackTrace();             return;         }         ValidationPropertiesResult objVldPropRslt =             objRtvVldCmd.getValidationPropertiesResult();         ValidationProperties[] validations = objVldPropRslt.getValidations();         //disply --> Validation ID | error/warning message | Validation Name         for (int i = 0; i < validations.length; i++) {             System.out.println(                 validations[i].getId()                     + " | "                     + validations[i].getMessage()                     + " | "                     + validations[i].getName());         }     }

}

A Class worth exploring for handling special characters in MDM

While development was going at full pace ,a small hurdle in form of special characters turned out to be a real speed breaker.The situtaion was that in MDM repository some field say Name contained  special chracters(Õ , û  ,Û)  in  other language like Hungarian,German ,French etc.Problem was I  logged into the Repository with english language with MDM JAVA API and  API was retrieving undesired value(O??,u??,U??) from the data manager .Although the Name string seems absolutely fine in the Data Manager.In short -value in MDM Data Manager for field name was Õ û  Û and output from API was O??u??U??

To my rescue came this class which is worth exploring when you have a situation like above

Class SetUnicodeNormalizationCommand

After you establish your connection to the server through API and Authenticate User Session ,you need to work with this class.

Connection to server would return an object of type ConnectionPool (call it connection)and UserSession authentication would return a string (call it session).Now write this piece of code

SetUnicodeNormalizationCommand cmd = new SetUnicodeNormalizationCommand(connection);

cmd.setSession(session);

cmd.setNormalizationType(SetUnicodeNormalizationCommand.NORMALIZATION_COMPOSED);

cmd.execute();

This class will keep the special characters retrieval intact.

A Class worth exploring for handling special characters in MDM

While development was going at full pace ,a small hurdle in form of special characters turned out to be a real speed breaker.The situtaion was that in MDM repository some field say Name contained  special chracters(Õ , û  ,Û)  in  other language like Hungarian,German ,French etc.Problem was I  logged into the Repository with english language with MDM JAVA API and  API was retrieving undesired value(O??,u??,U??) from the data manager .Although the Name string seems absolutely fine in the Data Manager.In short -value in MDM Data Manager for field name was Õ û  Û and output from API was O??u??U??

To my rescue came this class which is worth exploring when you have a situation like above

Class SetUnicodeNormalizationCommand

After you establish your connection to the server through API and Authenticate User Session ,you need to work with this class.

Connection to server would return an object of type ConnectionPool (call it connection)and UserSession authentication would return a string (call it session).Now write this piece of code

SetUnicodeNormalizationCommand cmd = new SetUnicodeNormalizationCommand(connection);

cmd.setSession(session);

cmd.setNormalizationType(SetUnicodeNormalizationCommand.NORMALIZATION_COMPOSED);

cmd.execute();

This class will keep the special characters retrieval intact.

How do you implement a MDM Connection Help Class?

  • In the exmaple Master Data Data Read class we used another class, ZCL_MDM_CONN_POOL_ROOT, to establish the connection to MDM.  This is just a reusable utility class that caches the API connection and contains logic to map the SAP logon langauge to the MDM Language.
  • The complete source code of this class can be downloaded here.
  • Class Properties:
  • Class Private Types:
  • Class Attributes:
  • Class Methods:
  • GET_MDM_CONNECTION
    METHOD get_mdm_connection.
    *@78\QImporting@ LANGUAGE TYPE SYLANGU DEFAULT SY-LANGU
    *@78\QImporting@ UNAME TYPE SYUNAME DEFAULT SY-UNAME
    *@78\QImporting@ REPOSITORY TYPE MDM_LOG_OBJECT_NAME
    *@78\QImporting@ USE_CONNECTION_POOL TYPE BOOLEAN DEFAULT ABAP_TRUE
    *@7B\QReturning@ VALUE( API ) TYPE REF TO CL_MDM_GENERIC_API
    *@03\QException@ CX_MDM_MAIN_EXCEPTION

    IF use_connection_pool = abap_true.
    DATA wa_api LIKE LINE OF api_cache.
    READ TABLE api_cache INTO wa_api
    WITH KEY language = language
    uname = uname
    repository = repository.
    IF sy-subrc = 0.
    ****Cached Connection Record is found, make sure the API reference is bound
    IF wa_api-api IS BOUND.
    api = wa_api-api.
    GET TIME STAMP FIELD wa_api-last_access.
    MODIFY TABLE api_cache FROM wa_api.
    ELSE.
    ****Not bound - Delete the Connection Record and Create a New Instance
    DELETE api_cache WHERE language = language
    AND uname = uname
    AND repository = repository.
    api = zcl_mdm_conn_pool_root=>create_mdm_connection(
    language = language
    uname = uname
    repository = repository
    use_connection_pool = use_connection_pool ).
    ENDIF.
    ELSE.
    ****No Cached Record - Create a New Instance
    api = zcl_mdm_conn_pool_root=>create_mdm_connection(
    language = language
    uname = uname
    repository = repository
    use_connection_pool = use_connection_pool ).
    ENDIF.
    ELSE.
    ****By Pass the Connection Pool and create a one-off Instance
    api = zcl_mdm_conn_pool_root=>create_mdm_connection(
    language = language
    uname = uname
    repository = repository
    use_connection_pool = use_connection_pool ).
    ENDIF.

    ENDMETHOD.



  • CREATE_MDM_CONNECTION
    METHOD create_mdm_connection.
    *@78\QImporting@ LANGUAGE TYPE SYLANGU DEFAULT SY-LANGU
    *@78\QImporting@ UNAME TYPE SYUNAME DEFAULT SY-UNAME
    *@78\QImporting@ REPOSITORY TYPE MDM_LOG_OBJECT_NAME
    *@78\QImporting@ USE_CONNECTION_POOL TYPE BOOLEAN DEFAULT ABAP_TRUE
    *@7B\QReturning@ VALUE( API ) TYPE REF TO CL_MDM_GENERIC_API
    *@03\QException@ CX_MDM_MAIN_EXCEPTION

    DATA mdm_language TYPE mdm_cdt_language_code.
    mdm_language = zcl_mdm_conn_pool_root=>expand_mdm_language( language ).

    **** Instantiate the API with our repository key from the dialog
    CREATE OBJECT api
    EXPORTING
    iv_log_object_name = repository.
    ****Connect to the Repository
    api->mo_accessor->connect( mdm_language ).

    IF use_connection_pool = abap_true.
    DATA wa_api LIKE LINE OF api_cache.
    wa_api-api = api.
    wa_api-language = language.
    wa_api-uname = uname.
    wa_api-repository = repository.
    GET TIME STAMP FIELD wa_api-last_access.
    INSERT wa_api INTO TABLE api_cache.
    ENDIF.

    ENDMETHOD.



  • EXPAND_MDM_LANGUAGE
    METHOD expand_mdm_language.
    *@78\QImporting@ LANGUAGE TYPE SYLANGU DEFAULT SY-LANGU Language Key of Current Text Environment
    *@7B\QReturning@ VALUE( MDM_LANGUAGE ) TYPE MDM_CDT_LANGUAGE_CODE MDM: CDT language code

    CASE language.
    WHEN c_english.
    mdm_language-language = 'eng'.
    mdm_language-country = 'US'.
    mdm_language-region = 'USA'.
    when c_german.
    mdm_language-language = 'ger'.
    mdm_language-country = 'DE'.
    * mdm_language-region = 'USA'.
    WHEN OTHERS.
    ****Use the repository Default
    CLEAR mdm_language.
    ENDCASE.

    ENDMETHOD.


How do you implement the processing for Master Data Read Class Parameters?

  • In the example Master Data Read Class that we have been looking at, the processing is generic.  In other words there is no statement in the application coding that specifies the MDM Repository, Table or Field name.  The values are supplied via parameters so that this same class can be used for more than one Master Data Characteristic.
  • You can see the area where you can supply these parameters in the following screen shot. It is the field labeled Master Data Read Class Parameters:
  • Although this is a single field, it can hold more than one value.  This is done by associating a data dictionary structure with the parameter inside the coding o the Master Data Read Class.  For the purposes of MDM Integration, you probably want a structure something like the one used this example implementation:
  • This way when you click on the pencil icon next the parameter field, a dialog pops up with the individual field selections as defined by your structure.  This even supports value input help for the individual fields.
  • So, how can this functionality be built into the Master Data Read Class?  It requires the implementation of another interface in your class - IF_RSMD_RS_GENERIC.  The sample Master Data Read Class, which can be downloaded here, contains an implementation of this interface for the purposes of processing the MDM Repository, Table and Field as parameters.
  • In the Method GET_STRUCTURE_NAME, you must specify the name of the data dictionary sturcture you are going to use:
    method if_rsmd_rs_generic~get_structure_name.
    e_struct_name = 'ZRSMD_RS_S_MDM'.
    endmethod.



  • But the most important processing are the GET and SET Methods. This is where you must supply the logic to map the data from the single parameter string into the individual fiels of your structure and vise versa:
    method if_rsmd_rs_generic~get_parameter.
    field-symbols: <l_s_struc> type zrsmd_rs_s_mdm.
    assign e_r_struc->* to <l_s_struc>.
    <l_s_struc> = o_s_gendomain.
    endmethod.

    method if_rsmd_rs_generic~set_parameter.
    field-symbols: <l_s_struc> type zrsmd_rs_s_mdm.
    assign i_r_struc->* to <l_s_struc>.
    o_s_gendomain = <l_s_struc>.
    endmethod.

    method if_rsmd_rs_generic~get_parameterstring.
    data: l_parameterstring type rsmdrclpa.

    *===Create the paramater string from the generic table structure===
    l_parameterstring+0(32) = o_s_gendomain-object_name.
    l_parameterstring+32(34) = o_s_gendomain-table .
    l_parameterstring+66(34) = o_s_gendomain-query_field.

    *===Export the parameter string====
    e_parameterstring = l_parameterstring.
    endmethod.

    method if_rsmd_rs_generic~set_parameterstring.
    data: l_parameterstring type rsmdrclpa.

    l_parameterstring = i_parameterstring.
    *===Create the structure from the parameterstring===
    o_s_gendomain-object_name = l_parameterstring+0(32).
    o_s_gendomain-table = l_parameterstring+32(34).
    o_s_gendomain-query_field = l_parameterstring+66(34).
    endmethod.


How do you implement the Master Data Read Class?

  • Master Data Read Classes have one basic requirement - They must implement the IF_RSMD_RS_ACCESS interface.
  • There are several examples of how implement a Master Data Read Class provided by SAP - like CL_RSMD_RS_GENERIC_DOMAIN and CL_RSMD_RS_GENERIC_TABLE.  For creating your own custom Master Data Read Class, it probably makes sense to start by copying from one these existing classes and only adjusting for your specific processing.
  • The complete source code (in SAPlink format) for an example implementation of a Master Data Read Class that uses MDM and the MDM ABAP APIs can be downloaded from here.
  • Of all the methods in the sample class the most important from the standpoint of the MDM integration is the GET_TEXT method. The example implementation supports the retrieval of STRING or INTEGER based supporting values for a given key from MDM:
METHOD if_rsmd_rs_access~get_text.

DATA: object_name TYPE mdm_log_object_name,
table TYPE mdm_table_code,
query_field TYPE mdm_field_code,
l_s_chavlinfo TYPE rsdm_s_chavlinfo,
l_not_assigned TYPE rs_txtlg,
l_initial_val TYPE rsd_chavl.

object_name = o_s_gendomain-object_name.
table = o_s_gendomain-table.
query_field = o_s_gendomain-query_field.


DATA lt_result_set_definition TYPE mdm_field_list_table.
DATA ls_result_set_definition LIKE LINE OF lt_result_set_definition.
DATA lt_result_set TYPE mdm_result_set_table.
DATA ls_result_set LIKE LINE OF lt_result_set.
DATA lt_result_set2 TYPE mdm_result_set_table.
DATA ls_result_set2 LIKE LINE OF lt_result_set2.
DATA ls_remote_key_filter TYPE mdm_client_system_key_query.
DATA api TYPE REF TO cl_mdm_generic_api.
DATA language TYPE mdm_cdt_language_code.
DATA keys TYPE mdm_keys.
DATA exception TYPE REF TO cx_mdm_main_exception.
FIELD-SYMBOLS <field_value> TYPE ANY.
FIELD-SYMBOLS: <wa_field> TYPE mdm_cdt_text,
<wa_string> TYPE string,
<wa_integer> TYPE mdm_gdt_integervalue,
<wa_taxonomy> TYPE mdm_taxonomy_entry,
<wa_int> TYPE mdm_gdt_integervalue.
TYPE-POOLS: mdmif.

TRY.

DATA wa_cache LIKE LINE OF me->data_cache.
READ TABLE data_cache INTO wa_cache
WITH KEY object_name = object_name
table = table
query_field = query_field.
IF sy-subrc = 0.
keys = wa_cache-keys.
lt_result_set = wa_cache-lt_result_set.
ELSE.

api = zcl_mdm_conn_pool_root=>get_mdm_connection( repository = object_name ).

DATA: result_set TYPE mdm_search_result_table.
CALL METHOD api->mo_core_service->query
EXPORTING
iv_object_type_code = table
* iv_hits_max = 1
IMPORTING
et_result_set = result_set.

****The results of a query only return the record keys - no details
****We then have to use a call to the method RETRIEVE to read
****the record details.
DATA: result TYPE mdm_search_result.
READ TABLE result_set INDEX 1 INTO result.
IF sy-subrc = 0.
keys = result-record_ids.
ENDIF.

CHECK keys IS NOT INITIAL.
****We only need the output field we are interested read from MDM
****By using the result_set_definition parameter, we can control this
****and only retrieve that single column
ls_result_set_definition-field_name = query_field.
APPEND ls_result_set_definition TO lt_result_set_definition.
CALL METHOD api->mo_core_service->retrieve
EXPORTING
iv_object_type_code = table
it_result_set_definition = lt_result_set_definition
it_keys = keys
IMPORTING
et_result_set = lt_result_set.

CLEAR wa_cache.
wa_cache-object_name = object_name.
wa_cache-table = table.
wa_cache-query_field = query_field.
wa_cache-keys = keys.
wa_cache-lt_result_set = lt_result_set.
APPEND wa_cache TO data_cache.
ENDIF.

*===Get the Initial Value Text===
CALL METHOD _textpool_read
EXPORTING
i_repid = 'SAPLRSDM'
i_key = '001'
IMPORTING
e_text = l_not_assigned.

FIELD-SYMBOLS: <wa_result> LIKE LINE OF lt_result_set.
FIELD-SYMBOLS: <wa_pair> TYPE mdm_name_value_pair,
<wa_key> LIKE LINE OF keys.

*===Append the text values in c_t_chavlinfo===
DATA: tabix TYPE sy-tabix.
DATA l_integer TYPE mdm_gdt_integervalue.
FIELD-SYMBOLS: <l_s_chavlinfo> TYPE rsdm_s_chavlinfo.
LOOP AT c_t_chavlinfo ASSIGNING <l_s_chavlinfo>
WHERE i_read_mode = rsdm_c_read_mode-text.
CLEAR <l_s_chavlinfo>-c_rc.
IF <l_s_chavlinfo>-c_chavl IS INITIAL
OR <l_s_chavlinfo>-c_chavl EQ rsd_c_initial
OR <l_s_chavlinfo>-c_chavl < 1.
<l_s_chavlinfo>-e_chatexts-txtsh = l_not_assigned.
<l_s_chavlinfo>-e_chatexts-txtmd = l_not_assigned.
<l_s_chavlinfo>-e_chatexts-txtlg = l_not_assigned.
ELSE.
l_integer = <l_s_chavlinfo>-c_chavl.
READ TABLE keys ASSIGNING <wa_key> FROM l_integer.
tabix = sy-tabix.
READ TABLE lt_result_set ASSIGNING <wa_result> INDEX tabix.
IF sy-subrc = 0.
READ TABLE <wa_result>-name_value_pairs ASSIGNING <wa_pair>
WITH KEY code = query_field.
IF sy-subrc = 0.
****The data for the column could be one of various data types
****The value itself is returned as TYPE REF TO DATA and must
****be cast into a more specific data type before it can be processed.
CASE <wa_pair>-type.
WHEN 'STRING'.
ASSIGN <wa_pair>-value->* TO <wa_string>.
WRITE <wa_key> TO l_s_chavlinfo-c_chavl LEFT-JUSTIFIED.
<l_s_chavlinfo>-e_chatexts-txtsh = <wa_string>.
<l_s_chavlinfo>-e_chatexts-txtmd = <wa_string>.
<l_s_chavlinfo>-e_chatexts-txtlg = <wa_string>.
WHEN 'INTEGER'.
ASSIGN <wa_pair>-value->* TO <wa_integer>.
WRITE <wa_key> TO l_s_chavlinfo-c_chavl LEFT-JUSTIFIED.
<l_s_chavlinfo>-e_chatexts-txtsh = <wa_integer>.
<l_s_chavlinfo>-e_chatexts-txtmd = <wa_integer>.
<l_s_chavlinfo>-e_chatexts-txtlg = <wa_integer>.
ENDCASE.
ENDIF.
ENDIF.
ENDIF.
ENDLOOP.
ENDTRY.
ENDMETHOD.

Connectivity - BI-MDM Integration

BI/MDM Frequently Asked Questions

General Questions
  • What types of BI/MDM Integration Scenarios are possible?
    There are two main types of BI/MDM Integration Scenarios that are currently being rolled out to customers. The first scenario starts with existing data in BI and uses that as the starting point to generate and populate an MDM Repostiory. The second type is integration during the BI data staging.
  • How does the Data Staging scenario work?
    There are actually two types of the data staging scenario. In each scenario, customers can use existing functionality with BI to access details from MDM to supplement the data that is being loaded into BI. An example might be a feed from an ERP system to a BI system. In this feed there might just be a master data key, like customer number. However using access to MDM, details about this customer, like their sales region, can be read and stored in the BI system or used at runtime inside BI queries.
  • What technology is necessary for the Data Staging Scenario?
    The data staging scenario utilizes the MDM ABAP API to be able to read directly from MDM (in realtime) using ABAP coding. A good overview of the MDM ABAP API in general is a requirement for starting this scenario. Also anyone interested in implementing this scenario should study this video. The video shows the basics of setting up the MDM ABAP API all the way through implementing one of the data staging scenarios.
  • How do you use the MDM API during a Data Load?
    For this situation you need to create an ABAP routine as the transformation rule type.

    During the editing of the Rule Type, you can choose Routine. You then can custom code an ABAP Routine that reads data from MDM using the MDM ABAP API.
  • How do you use the MDM API for building a Remote Master Data Characteristic?
    This scenario is a little less "free form" than the data loading routine. Here you use the existing BI functionality for master data characteristics and simply supply a custom implementation for the characteristic.
    As you maintain the characteristic, from the Master data/texts tab, you can choose a Master Data Read Class. For this you create and then use a class special suited to reading the master data values from MDM.

How do I connect to a Repository using the Class-Based MDM4A?

How do I connect to a Repository using the Class-Based MDM4A?

This is a simple example that only focuses on a few things: Instantiating the MDM4A, making a connection to a repository and exception handling.

DATA api             TYPE REF TO cl_mdm_generic_api.
DATA log_object_name TYPE mdm_log_object_name.
DATA language TYPE mdm_cdt_language_code.
DATA exception TYPE REF TO cx_mdm_main_exception.

log_object_name = 'API_CRUD_1'.
language-language = 'eng'.
language-country = 'US'. language-region = 'USA'.

TRY.
CREATE OBJECT api
EXPORTING
iv_log_object_name = log_object_name.
api->mo_accessor->connect( language ).
****Do Something
api->mo_accessor->disconnect( ).

CATCH cx_mdm_usage_error INTO exception.
****Other Exceptions...
CLEANUP.
TRY.
api->mo_accessor->disconnect( ).
CATCH cx_root.
ENDTRY.
ENDTRY.

IF NOT exception IS INITIAL.
MESSAGE exception TYPE 'E'.
ENDIF.



LOG_OBJECT_NAME is initialized with the key for our repository customizing (from Transaction MDMAPIC). That is only value you have to specify. All the other connection information will be looked up for you by the MDM4A.



We create the instance of the MDM4A by calling the CREATE OBJECT for our instance of CL_MDM_GENERIC_API. We only must pass in the configuration key. You could still have configuration, authorization, or trusting errors; but these exceptions will not be thrown until we connect to the repository in the next step.



Through the API we have access to instances of all 5 of the major interfaces (MO_ACCESSOR=IF_MDM_ACCESSOR, MO_CORE_SERVICE=IF_MDM_CORE_SERVICE, MO_ADMIN=IF_MDM_ADMIN, MO_META=IF_MDM_META, and MO_API_CONFIG=IF_MDM_API_CONFIG). We use api->mo_accessor to establish a connection to our repository. It is this point where the first communication connection is made.



First a list of repositories is retrieved from the MDM Server. This list is matched against our configuration settings to make sure the configuration is correct. Next a connection to the repository is made. The current AS-ABAP User (SY-UNAME) is passed through the interface call without specifying a password. At this point the Trusted Status of the AS-ABAP Server is also checked against the MDM Server allow.ip/deny.ip configuration files.



All processing logic is left out of this example. At the point marked "Do Something" you would place the specific logic.

Once finished with processing, you should disconnect from the MDM server explicitly with a call to the Accessor method DISCONNECT. If you end your application without disconnecting, the connection will remain open until it is cleaned up after its timeout. This will tie up system resources on the MDM Server unnecessarily.



All of our logic is placed within a single TRY...ENDTRY block. That way all errors will trigger into a single exception block. Only one Exception is shown here to save space. There is one super exception that can be caught to get all possible MDM4A specific exceptions - CX_MDM_MAIN_EXCEPTION. Inheriting from this exception are 5 more specific exceptions: CX_MDM_KERNEL (Exceptions within the Kernel layer for the MDM4A), CX_MDM_NOT_SUPPORTED (Exceptions if a method is called that isn't supported by the current release-specific provider that you are using), CX_MDM_PROVIDER (Exceptions generated within the Provider Layer of MDM4A), CX_MDM_SERVER_RC_CODE (Exceptions generated on the MDM Server. The MDM Server specific Return Code and explanatory text are passed back through this exception), and CX_MDM_USAGE_ERROR (Exceptions produced by incorrect usage of an MDM4A interface).



It is important to note the use of the CLEANUP event within the TRY...CATCH Block. Regardless of what type of exception occurred, processing can not continue. However we still want to be sure to close the interface connection and free up the resources allocated to it. Therefore we also call the Accessor DISCONNECT here. This logic path only occurs if an exception is caught. If errors occur within this Disconnect, there isn't really anything that can be done about it therefore the logic catches all exceptions (CX_ROOT) and ignores them.



Finally we process an error message with the text from the exception with the last block of coding.

Moving towards FTP free Integrations

All most all MDM integrations are FTP server dependent as the files are shared through it. Typical MDM integration scenario involves creating Remote Systems and ports on FTP server and files are exchanged through Ready folders. Using FTP involves some disadvantages which include frequent locking of sever and service getting down.

So SAP is moving forward in eliminating the FTP dependency in the integration scenarios.

Some of alternatives of FTP will include.

  • 1. ABAP APIs
  • 2. Java APIs
  • 3. MDM connector

In BI3.5 and MDM integration data has to be exchanged through FTP server.

But in the latest integration scenario (BI7 and MDM), we can completely eliminate FTP server as the exchange of data completely takes place through ABAP APIs. For this we need to install MDM_TECH and configure the connection object, establish the trusted connection. And we can push and pull the data from MDM. This is what called as "Tight Integration".

SAP Developer Network Latest Updates