Thursday, June 24, 2010

Customizing MDM Retrieval Service

There are two approaches for customizing the MDM retrieval service.


·         Approach 1:----End to end customization.
                              Here we should have complete control over SQL and how we build object structure.
          Approach 2:----Extension of the inbuilt ones.
                              Extending MDM Search Framework.

In this post I wish to emphasize on the first approach.

Retrival service with complete control over SQL:
First of all create a new module project. & follow the below steps.


1. Create a new MDM entity(Right click ->New MDM Entity)   (request object)  and populate with search criteria

2. Create a new MDM entity (response object) and populate with attributes you wish to return



3. Create a new MDM Tx,  View type, multiple records returned  set the request and response(The entities we created in Step 1 & 2)





We are trying to make use of MDM Entity addition to generate the request & response objects,but we will never
execute the scripts for entity addition to db.We just need the project skelton.For implementing the retrival service
we created a new MDM Txn with the request & response objects as the entity we created earlier.

Now go and generate the code.


Within the generated code there are a few places that you need  to modify:
In the component class, populate the handleXXX( BObj ) method where XXX is the name of your transaction.


CustomSearchFrameworkComponent.java:

public DWLResponse handleSearchByClubCardNumber(SearchRequestBObj theBObj) throws Exception {
   
        DWLStatus status = new DWLStatus();
        status.setStatus(DWLStatus.SUCCESS);
        DWLResponse response = createDWLResponse();     
        BObjQuery bObjQuery = null;

        bObjQuery = getBObjQueryFactory().createSearchRequestBObjQuery(SearchRequestBObjQuery.SEARCH_REQUEST_QUERY,
                theBObj.getControl());
       
        bObjQuery.setParameter("BObj", theBObj);          
        List list = bObjQuery.getResults();

        Vector vector = new Vector();
        for (Iterator it = list.iterator(); it.hasNext();) {
           SearchResponseBObj o = (SearchResponseBObj) it.next();

            vector.add(o);

            if (o != null) {
                if (o.getStatus()==null) {
                    o.setStatus(status);
                }
                response.addStatus(o.getStatus());
            } else {
                response.addStatus(o.getStatus());
            }
        }

        response.setData(vector);

        return response;
       

    }

In the BObjQuery class for the request object populate the provideSqlStatement() to return your custom sql, and change the
provideResultSetProcessor() method.

provideSQLStatement() is not available by default in the BObjQuery class.
Right click inside the class ,Perform an Override /Implement ->Select  provideSQLStatement()
or simply copy paste the code below.



@Override
    protected String provideSQLStatement() throws BObjQueryException {
        SQLParam sqlParam = (SQLParam) this.namedParams.get("BObj");
        SearchRequestBObj csRequObj=(SearchRequestBObj)sqlParam.getValue();
        System.err.println("Search Attribute---"+csRequObj.getClubCardNumber()+"####");
        // TODO Create the SQL HERE !!!!!
        String clubCard="'"+csRequObj.getClubCardNumber().trim()+"'";
       
        //I am simply getting  LINE_OF_BUSINESS & setting it to person name.(doesn't sounds logical forgive me it
        //is just an example.
        String sql= "select LINE_OF_BUSINESS from CONTRACT where XClub_Card_Id ="+clubCard;
       
       
        return sql;
    }

   
   
Change the provideResultSetProcessor() method. 

By default in generated code the reult processor returned is  SearchRequestResultSetProcessor ,but I had written my code in
SearchResponseResultSetProcessor().So changing it.
   
 /**
     *
     *
     *
     * Provides the result set processor that is used to populate the business
     * object.
     *
     * @return
     * An instance of SearchRequestResultSetProcessor.
     *
     * @see com.dwl.bobj.query.AbstractBObjQuery#provideResultSetProcessor()
     * @see com.mycompany.mdm.search.component.SearchRequestResultSetProcessor
     *
     * @generated NOT
     */
    protected IGenericResultSetProcessor provideResultSetProcessor()
            throws BObjQueryException {

        //return new SearchRequestResultSetProcessor();
        return new  SearchResponseResultSetProcessor();
    }   
   
Both the methods are invoked when     List list = bObjQuery.getResults(); is executed from the handleSearchByClubCardNumber() in
CustomSearchFrameworkComponent class.

In the above code we cahnged the reult set processor to "return new  SearchResponseResultSetProcessor()",but we are yet to write code in SearchResponseResultSetProcessor


In  SearchResponseResultSetProcessor class for the response object, populate the getObjectFromResultSet() method:


  /**
     *
     *
     *
     * Creates business objects from the supplied result set.
     *
     * @generated NOT
     */
    public Vector getObjectFromResultSet(ResultSet rs) throws Exception {
        Vector boVector = new Vector();
       
        // loop through the result set and get the column data
        while ( rs.next() ) {
            boVector.add( getBObjFromRS( rs ) );
        }
       
        return boVector;
    }

    /**
     *
     *
     *
     * Creates one business object from the supplied result set.
     *
     * @generated NOT
     */
    private SearchResponseBObj getBObjFromRS( ResultSet rs ) {
        SearchResponseBObj bobj = new SearchResponseBObj();
       
        try {
            // *** These MUST match the parameters requested in the SQL.
            /*bobj.setName( rs.getString(1) );
            bobj.setDOB( rs.getString(2) );
            bobj.setAddressLine1( rs.getString(3) );
            bobj.setAddressLine2( rs.getString(4) );
            bobj.setCity( rs.getString(5) );
            bobj.setPostCode( rs.getString(6) );
             */
            bobj.setPersonName(rs.getString(1));
            //bobj.setLineofBusiness(rs.getString(2));
           
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
       
        return bobj;
    }

Now  lets move on to our dtd,xsd,properties file & db changes.


It is a must that we put the  SearchRequestBObj?, SearchResponseBObj? in TCRMExtension.
Please see the liks to dtds & xsd at the bottom of the post.

Now you are done with merging.

DB Insert Statements:Only the METADATA file  you need to execute & only the following statements you need to execute.

-- Notes
-- MDM TODO statements are placed in the generated SQL file when user changes are required.
-- 1. Edit the following SQL files following any instructions given by MDM TODO statements.
-- 2. Connect to the database.
-- 3. Run each SQL file as shown below and in the same order.
--             db2 -tvf CustomSearchFramework_SETUP_DB2.sql
--             db2 -v -td@ -f CustomSearchFramework_TRIGGERS_DB2.sql
--             db2 -tvf CustomSearchFramework_CONSTRAINTS_DB2.sql
--             db2 -tvf CustomSearchFramework_MetaData_DB2.sql


----------------------------------------------
-- Component type
----------------------------------------------

INSERT INTO DB2ADMIN.COMPONENTTYPE (COMPONENT_TYPE_ID, DWL_PROD_TP_CD, COMPON_TYPE_VALUE, COMPON_LONG_DESC, LAST_UPDATE_DT)
   VALUES ( 1000032, 1, 'CustomSearchFrameworkFinderImpl', null, CURRENT TIMESTAMP);
INSERT INTO DB2ADMIN.COMPONENTTYPE (COMPONENT_TYPE_ID, DWL_PROD_TP_CD, COMPON_TYPE_VALUE, COMPON_LONG_DESC, LAST_UPDATE_DT)
   VALUES ( 1000030, 1, 'SearchRequestBObj', null, CURRENT TIMESTAMP);
INSERT INTO DB2ADMIN.COMPONENTTYPE (COMPONENT_TYPE_ID, DWL_PROD_TP_CD, COMPON_TYPE_VALUE, COMPON_LONG_DESC, LAST_UPDATE_DT)
   VALUES ( 1000034, 1, 'CustomSearchFrameworkComponent', null, CURRENT TIMESTAMP);
INSERT INTO DB2ADMIN.COMPONENTTYPE (COMPONENT_TYPE_ID, DWL_PROD_TP_CD, COMPON_TYPE_VALUE, COMPON_LONG_DESC, LAST_UPDATE_DT)
   VALUES ( 1000043, 1, 'SearchResponseBObj', null, CURRENT TIMESTAMP);

----------------------------------------------
-- Add SearchRequest object to V_GROUP table
----------------------------------------------

INSERT INTO DB2ADMIN.V_GROUP (GROUP_NAME, APPLICATION, OBJECT_NAME, LAST_UPDATE_DT, SORTBY)
  VALUES ('SearchRequestBObj', 'TCRM', 'com.mycompany.mdm.search.component.SearchRequestBObj', CURRENT TIMESTAMP, 'LAST_UPDATE_DT');


----------------------------------------------
-- Add SearchResponse object to V_GROUP table
----------------------------------------------

INSERT INTO DB2ADMIN.V_GROUP (GROUP_NAME, APPLICATION, OBJECT_NAME, LAST_UPDATE_DT, SORTBY)
  VALUES ('SearchResponseBObj', 'TCRM', 'com.mycompany.mdm.search.component.SearchResponseBObj', CURRENT TIMESTAMP, 'LAST_UPDATE_DT');


----------------------------------------------
-- Transactions
----------------------------------------------

INSERT INTO DB2ADMIN.CDBUSINESSTXTP (BUSINESS_TX_TP_CD, NAME, DESCRIPTION, EXPIRY_DT, LAST_UPDATE_DT, TX_LOG_IND, TX_OBJECT_TP, DEPRECATED_SINCE, DWL_PROD_TP_CD)
   VALUES (1000006, 'addSearchRequest',  null, null, CURRENT TIMESTAMP, 'Y', 'P', null, 1);
  
INSERT INTO DB2ADMIN.BUSINESSTXREQRESP (BUSTX_REQRESP_ID, BUSINESS_TX_TP_CD, APPLICATION, GROUP_NAME, REQ_RESP_IND, TX_PARAM_TP_CD, PARAM_NAME, PARAM_ORDER, LAST_UPDATE_USER, LAST_UPDATE_DT, COLLECTION_IND)
values (1000108, 1000006, 'TCRM', 'SearchRequestBObj', 'I', null, null, 1, 'cusadmin', CURRENT TIMESTAMP, null);

INSERT INTO DB2ADMIN.BUSINESSTXREQRESP (BUSTX_REQRESP_ID, BUSINESS_TX_TP_CD, APPLICATION, GROUP_NAME, REQ_RESP_IND, TX_PARAM_TP_CD, PARAM_NAME, PARAM_ORDER, LAST_UPDATE_USER, LAST_UPDATE_DT, COLLECTION_IND)
values (1000109, 1000006, 'TCRM', 'SearchRequestBObj', 'O', null, null, null, 'cusadmin', CURRENT TIMESTAMP, 'Y');
       
INSERT INTO DB2ADMIN.CDBUSINESSTXTP (BUSINESS_TX_TP_CD, NAME, DESCRIPTION, EXPIRY_DT, LAST_UPDATE_DT, TX_LOG_IND, TX_OBJECT_TP, DEPRECATED_SINCE, DWL_PROD_TP_CD)
   VALUES (1000009, 'updateSearchRequest',  null, null, CURRENT TIMESTAMP, 'Y', 'P', null, 1);
  
INSERT INTO DB2ADMIN.BUSINESSTXREQRESP (BUSTX_REQRESP_ID, BUSINESS_TX_TP_CD, APPLICATION, GROUP_NAME, REQ_RESP_IND, TX_PARAM_TP_CD, PARAM_NAME, PARAM_ORDER, LAST_UPDATE_USER, LAST_UPDATE_DT, COLLECTION_IND)
values (1000110, 1000009, 'TCRM', 'SearchRequestBObj', 'I', null, null, 1, 'cusadmin', CURRENT TIMESTAMP, null);

INSERT INTO DB2ADMIN.BUSINESSTXREQRESP (BUSTX_REQRESP_ID, BUSINESS_TX_TP_CD, APPLICATION, GROUP_NAME, REQ_RESP_IND, TX_PARAM_TP_CD, PARAM_NAME, PARAM_ORDER, LAST_UPDATE_USER, LAST_UPDATE_DT, COLLECTION_IND)
values (1000111, 1000009, 'TCRM', 'SearchRequestBObj', 'O', null, null, null, 'cusadmin', CURRENT TIMESTAMP, 'Y');
       
INSERT INTO DB2ADMIN.CDBUSINESSTXTP (BUSINESS_TX_TP_CD, NAME, DESCRIPTION, EXPIRY_DT, LAST_UPDATE_DT, TX_LOG_IND, TX_OBJECT_TP, DEPRECATED_SINCE, DWL_PROD_TP_CD)
   VALUES (1000011, 'getSearchRequest', null, null, CURRENT TIMESTAMP, 'Y', 'I', null, 1);

INSERT INTO DB2ADMIN.BUSINESSTXREQRESP (BUSTX_REQRESP_ID, BUSINESS_TX_TP_CD, APPLICATION, GROUP_NAME, REQ_RESP_IND, TX_PARAM_TP_CD, PARAM_NAME, PARAM_ORDER, LAST_UPDATE_USER, LAST_UPDATE_DT, COLLECTION_IND)
values (1000112, 1000011, null, null, 'I', 1, 'pkId', 1, 'cusadmin', CURRENT TIMESTAMP, null);

INSERT INTO DB2ADMIN.BUSINESSTXREQRESP (BUSTX_REQRESP_ID, BUSINESS_TX_TP_CD, APPLICATION, GROUP_NAME, REQ_RESP_IND, TX_PARAM_TP_CD, PARAM_NAME, PARAM_ORDER, LAST_UPDATE_USER, LAST_UPDATE_DT, COLLECTION_IND)
values (1000113, 1000011, null, null, 'I', 5, 'aDWLControl', 2, 'cusadmin', CURRENT TIMESTAMP, null);

INSERT INTO DB2ADMIN.BUSINESSTXREQRESP (BUSTX_REQRESP_ID, BUSINESS_TX_TP_CD, APPLICATION, GROUP_NAME, REQ_RESP_IND, TX_PARAM_TP_CD, PARAM_NAME, PARAM_ORDER, LAST_UPDATE_USER, LAST_UPDATE_DT, COLLECTION_IND)
values (1000114, 1000011, 'TCRM', 'SearchRequestBObj', 'O', null, null, null, 'cusadmin', CURRENT TIMESTAMP, 'Y');

INSERT INTO DB2ADMIN.CDBUSINESSTXTP (BUSINESS_TX_TP_CD, NAME, DESCRIPTION, EXPIRY_DT, LAST_UPDATE_DT, TX_LOG_IND, TX_OBJECT_TP, DEPRECATED_SINCE, DWL_PROD_TP_CD)
   VALUES (1000019, 'addSearchResponse',  null, null, CURRENT TIMESTAMP, 'Y', 'P', null, 1);
  
INSERT INTO DB2ADMIN.BUSINESSTXREQRESP (BUSTX_REQRESP_ID, BUSINESS_TX_TP_CD, APPLICATION, GROUP_NAME, REQ_RESP_IND, TX_PARAM_TP_CD, PARAM_NAME, PARAM_ORDER, LAST_UPDATE_USER, LAST_UPDATE_DT, COLLECTION_IND)
values (1000115, 1000019, 'TCRM', 'SearchResponseBObj', 'I', null, null, 1, 'cusadmin', CURRENT TIMESTAMP, null);

INSERT INTO DB2ADMIN.BUSINESSTXREQRESP (BUSTX_REQRESP_ID, BUSINESS_TX_TP_CD, APPLICATION, GROUP_NAME, REQ_RESP_IND, TX_PARAM_TP_CD, PARAM_NAME, PARAM_ORDER, LAST_UPDATE_USER, LAST_UPDATE_DT, COLLECTION_IND)
values (1000116, 1000019, 'TCRM', 'SearchResponseBObj', 'O', null, null, null, 'cusadmin', CURRENT TIMESTAMP, 'Y');
       
INSERT INTO DB2ADMIN.CDBUSINESSTXTP (BUSINESS_TX_TP_CD, NAME, DESCRIPTION, EXPIRY_DT, LAST_UPDATE_DT, TX_LOG_IND, TX_OBJECT_TP, DEPRECATED_SINCE, DWL_PROD_TP_CD)
   VALUES (1000022, 'updateSearchResponse',  null, null, CURRENT TIMESTAMP, 'Y', 'P', null, 1);
  
INSERT INTO DB2ADMIN.BUSINESSTXREQRESP (BUSTX_REQRESP_ID, BUSINESS_TX_TP_CD, APPLICATION, GROUP_NAME, REQ_RESP_IND, TX_PARAM_TP_CD, PARAM_NAME, PARAM_ORDER, LAST_UPDATE_USER, LAST_UPDATE_DT, COLLECTION_IND)
values (1000117, 1000022, 'TCRM', 'SearchResponseBObj', 'I', null, null, 1, 'cusadmin', CURRENT TIMESTAMP, null);

INSERT INTO DB2ADMIN.BUSINESSTXREQRESP (BUSTX_REQRESP_ID, BUSINESS_TX_TP_CD, APPLICATION, GROUP_NAME, REQ_RESP_IND, TX_PARAM_TP_CD, PARAM_NAME, PARAM_ORDER, LAST_UPDATE_USER, LAST_UPDATE_DT, COLLECTION_IND)
values (1000118, 1000022, 'TCRM', 'SearchResponseBObj', 'O', null, null, null, 'cusadmin', CURRENT TIMESTAMP, 'Y');
       
INSERT INTO DB2ADMIN.CDBUSINESSTXTP (BUSINESS_TX_TP_CD, NAME, DESCRIPTION, EXPIRY_DT, LAST_UPDATE_DT, TX_LOG_IND, TX_OBJECT_TP, DEPRECATED_SINCE, DWL_PROD_TP_CD)
   VALUES (1000024, 'getSearchResponse', null, null, CURRENT TIMESTAMP, 'Y', 'I', null, 1);

INSERT INTO DB2ADMIN.BUSINESSTXREQRESP (BUSTX_REQRESP_ID, BUSINESS_TX_TP_CD, APPLICATION, GROUP_NAME, REQ_RESP_IND, TX_PARAM_TP_CD, PARAM_NAME, PARAM_ORDER, LAST_UPDATE_USER, LAST_UPDATE_DT, COLLECTION_IND)
values (1000119, 1000024, null, null, 'I', 1, 'pkId', 1, 'cusadmin', CURRENT TIMESTAMP, null);

INSERT INTO DB2ADMIN.BUSINESSTXREQRESP (BUSTX_REQRESP_ID, BUSINESS_TX_TP_CD, APPLICATION, GROUP_NAME, REQ_RESP_IND, TX_PARAM_TP_CD, PARAM_NAME, PARAM_ORDER, LAST_UPDATE_USER, LAST_UPDATE_DT, COLLECTION_IND)
values (1000120, 1000024, null, null, 'I', 5, 'aDWLControl', 2, 'cusadmin', CURRENT TIMESTAMP, null);

INSERT INTO DB2ADMIN.BUSINESSTXREQRESP (BUSTX_REQRESP_ID, BUSINESS_TX_TP_CD, APPLICATION, GROUP_NAME, REQ_RESP_IND, TX_PARAM_TP_CD, PARAM_NAME, PARAM_ORDER, LAST_UPDATE_USER, LAST_UPDATE_DT, COLLECTION_IND)
values (1000121, 1000024, 'TCRM', 'SearchResponseBObj', 'O', null, null, null, 'cusadmin', CURRENT TIMESTAMP, 'Y');

INSERT INTO DB2ADMIN.CDBUSINESSTXTP (BUSINESS_TX_TP_CD, NAME, DESCRIPTION, EXPIRY_DT, LAST_UPDATE_DT, TX_LOG_IND, TX_OBJECT_TP, DEPRECATED_SINCE, DWL_PROD_TP_CD)
   VALUES (1000028, 'searchByClubCardNumber',  null, null, CURRENT TIMESTAMP, 'Y', 'P', null, 1);
  
INSERT INTO DB2ADMIN.BUSINESSTXREQRESP (BUSTX_REQRESP_ID, BUSINESS_TX_TP_CD, APPLICATION, GROUP_NAME, REQ_RESP_IND, TX_PARAM_TP_CD, PARAM_NAME, PARAM_ORDER, LAST_UPDATE_USER, LAST_UPDATE_DT, COLLECTION_IND)
values (1000122, 1000028, 'TCRM', 'SearchRequestBObj', 'I', null, null, 1, 'cusadmin', CURRENT TIMESTAMP, null);

INSERT INTO DB2ADMIN.BUSINESSTXREQRESP (BUSTX_REQRESP_ID, BUSINESS_TX_TP_CD, APPLICATION, GROUP_NAME, REQ_RESP_IND, TX_PARAM_TP_CD, PARAM_NAME, PARAM_ORDER, LAST_UPDATE_USER, LAST_UPDATE_DT, COLLECTION_IND)
values (1000123, 1000028, 'TCRM', 'SearchResponseBObj', 'O', null, null, null, 'cusadmin', CURRENT TIMESTAMP, 'N');
       

For transactions:

In CDBUSINESSTXTP &  BUSINESSTXREQRESP you can insert the statemets for searchByClubCardNumber alone,but I added for
add,update& get also.No specific reasons just for safety.


In tcrm_extension.properties


#-------------Added for CustomSearchFramework

#-----------------------------------------------------------------------
# ADDITION: SearchRequest CONTROLLER METHODS
#
addSearchRequest = com.mycompany.mdm.search.controller.CustomSearchFrameworkTxnBean
updateSearchRequest = com.mycompany.mdm.search.controller.CustomSearchFrameworkTxnBean
getSearchRequest = com.mycompany.mdm.search.controller.CustomSearchFrameworkFinderImpl

#-----------------------------------------------------------------------
# ADDITION: SearchRequestBObj BUSINESS OBJECT
#
SearchRequestBObj = com.mycompany.mdm.search.component

#-----------------------------------------------------------------------
# ADDITION: SearchRequestBObj WEB SERVICES
services.endpoints.message.converter.com.mycompany.mdm.search.component.SearchRequestBObj=com.mycompany.mdm.search.customsearchframework.service.to.convert.SearchRequestBObjConverter
services.endpoints.message.converter.com.mycompany.mdm.search.customsearchframework.service.to.SearchRequest=com.mycompany.mdm.search.customsearchframework.service.to.convert.SearchRequestBObjConverter

#-----------------------------------------------------------------------
# ADDITION: SearchResponse CONTROLLER METHODS
#
addSearchResponse = com.mycompany.mdm.search.controller.CustomSearchFrameworkTxnBean
updateSearchResponse = com.mycompany.mdm.search.controller.CustomSearchFrameworkTxnBean
getSearchResponse = com.mycompany.mdm.search.controller.CustomSearchFrameworkFinderImpl

#-----------------------------------------------------------------------
# ADDITION: SearchResponseBObj BUSINESS OBJECT
#
SearchResponseBObj = com.mycompany.mdm.search.component

#-----------------------------------------------------------------------
# ADDITION: SearchResponseBObj WEB SERVICES
services.endpoints.message.converter.com.mycompany.mdm.search.component.SearchResponseBObj=com.mycompany.mdm.search.customsearchframework.service.to.convert.SearchResponseBObjConverter
services.endpoints.message.converter.com.mycompany.mdm.search.customsearchframework.service.to.SearchResponse=com.mycompany.mdm.search.customsearchframework.service.to.convert.SearchResponseBObjConverter

CustomSearchFramework.BObjQueryFactory=com.mycompany.mdm.search.bobj.query.CustomSearchFrameworkModuleBObjQueryFactoryImpl
customsearchframework_component = com.mycompany.mdm.search.component.CustomSearchFrameworkComponent
   
searchByClubCardNumber = com.mycompany.mdm.search.controller.CustomSearchFrameworkFinderImpl

In DWLCommon_extension.properties

#-------------Added for CustomSearchFramework


###################################################
# Webservices addition
###################################################

Parser.tcrm.CustomSearchFrameworkService=com.mycompany.mdm.search.customsearchframework.service.to.convert.CustomSearchFrameworkServiceRequestParser
Constructor.tcrm.CustomSearchFrameworkService=com.mycompany.mdm.search.customsearchframework.service.to.convert.CustomSearchFrameworkServiceResponseConstructor

Now you are ready!!.


Here is your request xml.

              RequestXML



Response:
             Response of Search





Links to dtd & xsds:


http://docs.google.com/leaf?id=0B3obvedGI1lvZTg3MjVkZmMtZmVhNS00MDU1LWJlNTUtM2VlOTNkOTNkMTRm&sort=name&layout=list&num=50

Thursday, June 10, 2010

IBM MDM Composite Transactions

As per the IBM MDM developers guide there are 2 ways for implementing Composite Transactions.

1)Using custom business proxies.
2)Using composite xml transactions.
Here we will discuss the first approach.
The steps to be followed are in creating a Business Proxy(BP) are

1. Create a  Java project and your BP class extending the DWLTXnBP
2. Override the execute method.
3. Entry in DWLCommon_extension.properties.
4. Register the transaction name in CDBUSINESSTXTP & COMPONENTTYPE table.
5.Given dependency to the BP java project in  MDM.EAR.
6.Associate jars to the build path of the Java project we created.
7.Add reference in Manifest of DWLCommonServiceEJB.
8. Stop,Clean build,publish and run the transaction through XML Tester.

Step 1: Create a  Java project and your BP class extending the DWLTXnBP
Create a Java project Eg:BasicCompositeTransactionProject
My Class I named it like CreateCustomerBP.java

Step 2:Override the execute method.
public Object execute(Object arg0) throws BusinessProxyException{
//Give a Sysout for testing.
}

Step 3:Entry in DWLCommon_extension.properties.
Add the following entry in DWLCommon_extension.properties
BusinessProxy.tcrm.myXXXTranasactionName = com.XXXXX.mdm.MyCustomBP

Eg:
BusinessProxy.tcrm.createCustomerComposite=com.XXXX.mdm.CreateCustomerBP


Step 4:Register the transaction name in CDBUSINESSTXTP table .
insert into DB2ADMIN.CDBUSINESSTXTP (business_tx_tp_cd, name, tx_log_ind, last_update_dt, tx_object_tp)
 values (900201, 'createCustomerComposite', 'Y', current timestamp, 'P');

INSERT INTO DB2ADMIN.COMPONENTTYPE (COMPONENT_TYPE_ID, DWL_PROD_TP_CD, COMPON_TYPE_VALUE, COMPON_LONG_DESC, LAST_UPDATE_DT)
VALUES (900201, 1, 'CreateCustomerBP', 'DWLSampleCreateCustomerBP Composite Transaction Business Proxy', CURRENT TIMESTAMP);

Step 5:Given dependency to the BP java project in  MDM.EAR
Inside MDM project ->META-INF->application.xml ->Module tab ->Project Utility jars->Add BasicCompositeTransactionProject.jar




Step 6.Associate jars to the build path of the Java project we created.

CoreUtilities.jar ManagementCommon.jar CommonUtilities.jar Logging.jar ConfigurationRepository.jar ConfigurationClient.jar DWLCommonServices.jar icu4j.jar BTM.jar Services.jar Base.jar




Step 7.Add reference in Manifest of DWLCommonServiceEJB .
Go to DWLCommonServicesEJB ->MET-INF->Manifest.mf -> Dependencies->Check BasicCompositeTransactionProject.jar


8. Stop,Clean build,publish and run the transaction through XML Tester.
Try Add/Remove the MDM by right clicking the server.

One normal error that we see in the course of  development is

BTM ITxRxException occurred in Request and Response Framework.
<Throwable>com.dwl.base.exception.DWLBaseException: com.mypack.compositetxns.CreateCustomerBP</Throwable>

The main reason is not following the step 7.Add reference in Manifest of DWLCommonServiceEJB properly.

Sample Code:

import com.dwl.base.DWLCommon;
import com.dwl.base.DWLControl;
import com.dwl.base.requestHandler.DWLTransactionPersistent;
import com.dwl.base.requestHandler.DWLTxnBP;
import com.dwl.tcrm.common.TCRMCommon;
import com.dwl.tcrm.common.TCRMResponse;
import com.dwl.tcrm.financial.component.TCRMContractBObj;
import com.dwl.unifi.tx.exception.BusinessProxyException;
import com.XXX.app.tscd.extension.component.XContractBObjExt;





public class CreateCustomerBP  extends DWLTxnBP{
      DWLControl objDWLControl = null;
    @Override
   
    public Object execute(Object arg0) throws BusinessProxyException{
        // TODO Auto-generated method stub
       
           Object objResponse = null;
       
        try{
        System.err.println("Inside execute...");
        DWLTransactionPersistent objDWLTransactionPersistent = (DWLTransactionPersistent) arg0;
        objDWLControl = objDWLTransactionPersistent.getTxnControl();
        objResponse = processBusinessObject(objDWLTransactionPersistent);
       
        System.err.println("Reached..here..");
        }
       
        catch (Exception objException) {
             objException.printStackTrace();
             
           
         }
        return objResponse;
        //return super.execute(arg0);
    }
   
   
    private Object processBusinessObject(
            DWLTransactionPersistent objDWLTransactionPersistent)
            throws Exception {
        TCRMResponse resAddContract = null;
        DWLCommon objTxnTopLevelObject = (DWLCommon) objDWLTransactionPersistent
        .getTxnTopLevelObject();
        System.err.println("Top Level Object---- "+objTxnTopLevelObject.getClass().toString());
        if ((objTxnTopLevelObject instanceof TCRMContractBObj)) {
       
        System.err.println("Top Level Object instanace of TCRMContractBObj ");
       
        TCRMContractBObj ourTCRMContract=(TCRMContractBObj)objTxnTopLevelObject;
       
       
        XContractBObjExt xContractBobj= (XContractBObjExt)objTxnTopLevelObject;
        System.err.println("Club card Number"+xContractBobj.getXClubCardNbr());
        System.err.println("Line of Business---"+ourTCRMContract.getLineOfBusiness());
        resAddContract=doAddContract(ourTCRMContract);   
        }else{
            System.err.println("Top Level Object NOT instanace of TCRMContractBObj ");
           
           
        }
       
       
       
        return resAddContract;   
    }
   
   
public TCRMResponse doAddContract(TCRMContractBObj ourTCRMContract){
       
   
        System.err.println("In doAddContract()");
        TCRMResponse resAddContract = null;
        //XContractBObjExt xcontract =new XContractBObjExt();
        final String TXN_ADDCONTRACT="addContract";
       
        try {
            resAddContract =  executeAddContract(TXN_ADDCONTRACT,ourTCRMContract);
        } catch (BusinessProxyException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    /*   
        try{
           
           
            if(ourTCRMContract.getXClubCardId() != null){
                System.out.println("XML :::"+objInputXContractBObjExt_dup.toXML());
                resAddContract =  executeAddContract(TXN_ADDCONTRACT,objInputXContractBObjExt_dup);
            }
        }catch (Exception e) {
            System.out.println("Exception in doAddCOntract");
            e.printStackTrace();
        }*/
        return resAddContract;
    }
   
    public TCRMResponse executeAddContract(final String TXN_ADDCONTRACT, final TCRMCommon topLevelObj) throws BusinessProxyException{
        TCRMResponse resExecuteAddContract = null;
        try{
       
        System.err.println("IN executeAddContract()");
       
       
        DWLTransactionPersistent dtpObj = new DWLTransactionPersistent();
       
        //System.out.println("objDWLControl :::"+objDWLControl.toString());
        dtpObj.setTxnControl(objDWLControl);
        dtpObj.setTxnTopLevelObject(topLevelObj);
        dtpObj.setTxnType(TXN_ADDCONTRACT);
       
        resExecuteAddContract = (TCRMResponse) super.processPersistentObject(dtpObj);
       
        }
        catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
        return resExecuteAddContract;
       
    }
   
   
   

}

One thing to remember is to change the  DWLServiceControllerTester class in the XML tester project.

//Composite MDM Service Hashmap
        context.put("TargetApplication", "tcrm");
        context.put("RequestType", "standard");
        context.put("ResponseType", "standard");
        context.put("CompositeTxn", "true");
        context.put("CompositeParser", "DWLService");
        context.put("CompositeConstructor", "DWLService");
        context.put("OperationType", "all");


References:
1)MDM Developer Guide.
2)http://www.ibm.com/developerworks/forums/thread.jspa?threadID=328058&tstart=0