Tutorials > Program model > Web services > Customize Web 2.0 and Web services to support customization of the OrderItem noun using the UserData field

< Previous | Next >


Customize the client library and component facade

In this step, you learn how to create the source code support the new engraving attributes for the Web Services


Procedure

  1. Open WebSphere Commerce Developer.

  2. In the Enterprise Explorer view, click WebSphereCommerceServerExtensionsLogic.

  3. Create a package:

    1. Right-click WebSphereCommerceServerExtensionsLogic\src and select New > Package.

    2. In the name field type com.mycompany.commerce.customization.order.

    3. Click Finish.

  4. In the new package, create three new classes. The first class, called MyOrderFacadeClient.java, extends the client API library to expect new engraving attributes from the store. The next two classes, MyExtendOrderItemProcessCmdImpl.java and ExtComposeOrderDetailsCmdImpl.java are both commands. These new classes extend existing commands and persist and retrieve the engraving information of an order item to the PATTRVALUE table.

    To create the three new classes:

    1. Right-click com.mycompany.commerce.customization.order.

    2. Select New > Class. In the name field type MyOrderFacadeClient

    3. Click Finish.

    4. Repeat to create the classes MyExtendOrderItemProcessCmdImpl, ExtComposeOrderDetailsCmdImpl.

  5. Right-click WebSphereCommerceServerExtensionsLogic and select Properties.

  6. Click Java Build Path and click Projects. Ensure that WebSphereCommerceServerExtensionsData is selected.

  7. Open MyOrderFacadeClient.java and replace the contents with the following code:

    package com.mycompany.commerce.customization.order;
    
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Set;
    
    import javax.security.auth.callback.CallbackHandler;
    
    import com.ibm.commerce.foundation.common.datatypes.BusinessContextType;
    import com.ibm.commerce.foundation.common.datatypes.CommerceFoundationFactory;
    import com.ibm.commerce.foundation.common.datatypes.UserDataType;
    import com.ibm.commerce.order.facade.client.OrderException;
    import com.ibm.commerce.order.facade.client.OrderFacadeClient;
    import com.ibm.commerce.order.facade.datatypes.OrderItemType;
    
    
    /**
     * MyOrderFacadeClient will extend OrderFacadeClient.  This customization will 
     * extend the Change noun to include new personalization attributes for  
     * the Order noun.  In other words, the Update operation is overriden to include 
     * engraving data for an existing order item. 
     */
    public class MyOrderFacadeClient extends OrderFacadeClient{
        
        private static final String CLASSNAME = MyOrderFacadeClient.class.getName();
    
        private static final java.util.logging.Logger LOGGER = com.ibm.commerce.foundation.common.util.logging.LoggingHelper
                    .getLogger(MyOrderFacadeClient.class);
        
        /**
         * Hard-coded text provided for clarity. Property files is recommended for prefix for engraving attribute name 
         */
        public static final String ENGRAVINGKEYNAME = "engraving";
        
        /**
         * Constructor
         */
        public MyOrderFacadeClient(){
            super();
        }
        
        /**
         * Constructor 
         * @param businessContext
         * @param callbackHandler
         */
        public MyOrderFacadeClient(BusinessContextType businessContext, CallbackHandler callbackHandler) {
            super(businessContext, callbackHandler);
        }
        
        /**
         * buildOrderItem() is used to take the parameters out of the Map and insert them into our message. 
         * We are customizing the updateOrderItem action to find our engraving parameters and add them into
         * the UserData section of our message.  The parameters argument will have keys starting with the word
         * engraving, for example "engravingText", "engravingFont" and "engravingSize". These keys will map
         * to the values for each order item.
         * @param parameters -- a Map contains the parameters
         * @param actionName
         * @return OrderItemType[]
         * @throws OrderException
         */
       protected OrderItemType[] buildOrderItem(Map parameters, String actionName) throws OrderException {
            
            final String strMethodName = "buildOrderItem";  
            LOGGER.entering(CLASSNAME, strMethodName);
            
            //call super to build all the other order item attributes into the message
            OrderItemType[] orderItems = super.buildOrderItem(parameters,actionName);
            
            //we only want to perform this action when updating an existing order item
            if(actionName.equals("updateOrderItem")){                   
                //find any parameters that start with the word "engraving"
                Map engravingParms= resolveEngravingParameter(parameters); 
                            
                if(engravingParms != null){
                    for (int i=0; i<orderItems.length; i++) //for all of the order items
                    {
                        OrderItemType orderItem = orderItems[i]; //get a particular orderItem
                        //prepare the userData section
                        UserDataType userData = orderItem.getUserData();
                        if (userData == null)
                        {
                            userData = CommerceFoundationFactory.eINSTANCE.createUserDataType();
                        }
                        orderItem.setUserData(userData);            
                        Map userDataFields  = userData.getUserDataField();
                       
                        //iterate through all the engraving parameters
                        Set keys = engravingParms.keySet();            
                        Iterator it = keys.iterator();            
                        while (it.hasNext())
                        {
                            // Add the engraving data to the user data element
                            String keyName = (String)it.next();
                            String[] values = (String[])engravingParms.get(keyName);
                            userDataFields.put(keyName, values[i]);                               
                        }                            
                    }
                }
            }        
            return orderItems;              
        }
       
       private Map resolveEngravingParameter(Map parameters) throws OrderException {
           Map engravingParams = new HashMap();
           Iterator keys = parameters.keySet().iterator();
           while (keys.hasNext()) {
               String key = (String) keys.next();
               if (key.startsWith(ENGRAVINGKEYNAME)) {
                   engravingParams.put(key, resolveParameter(parameters, key));
               }
           }
           return engravingParams;
       }
    }
    

  8. In this step, ExtendOrderItemProcessCmdImpl is the component command that is required to be changed to handle the new information inside the extended UserData. Replace the contents of the MyExtendOrderItemProcessCmdImpl class with the following code sample. It extends the ExtendOrderItemProcessCmdImpl command. The new command takes the new personalization parameters out of the response properties and persists them to the database. Open MyExtendedOrderItemProcessCmdImpl.java and replace the contents with the following code:

    package com.mycompany.commerce.customization.order;
    
    import java.util.Enumeration;
    import com.ibm.commerce.datatype.TypedProperty;
    import com.ibm.commerce.exception.ECException;
    import com.ibm.commerce.foundation.common.util.logging.LoggingHelper;
    import com.ibm.commerce.order.facade.OrderFacadeConstants;
    import com.ibm.commerce.order.objects.OrderItemAccessBean;
    import com.ibm.commerce.orderitems.commands.ExtendOrderItemProcessCmdImpl;
    import com.ibm.commerce.utf.objects.PAttrProdAccessBean;
    import com.ibm.commerce.utf.objects.PAttrStringValueAccessBean;
    import com.ibm.commerce.utf.objects.PAttrValueAccessBean;
    import com.ibm.commerce.utf.objects.PAttributeAccessBean;
    
     /** * When the message is received, the request properties will be processed by 
     the command * ExtendOrderItemProcessCmdImpl, so we extend this command and put 
     our new logic into the * performExecute() method.  This logic will write the 
     new personalization data into the * PAttrValue table */
    
    public class MyExtendOrderItemProcessCmdImpl extends ExtendOrderItemProcessCmdImpl{
    
        private static final String CLASSNAME = MyExtendOrderItemProcessCmdImpl.class.getName();
    
        private static final java.util.logging.Logger LOGGER = com.ibm.commerce.foundation.common.util.logging.LoggingHelper
                    .getLogger(MyExtendOrderItemProcessCmdImpl.class);
        
        /**
         * Holds new request properties
         */
        private TypedProperty myRequestProperties;    
        
        /**
         * Constructor
         */
        public MyExtendOrderItemProcessCmdImpl(){
            super();
        }
        
        /**
         * This will set the request properties for this class
         * @param aRequestproperties
         */
        public void setRequestProperties(TypedProperty aRequestproperties) throws ECException{        
            myRequestProperties = aRequestproperties;    
            super.setRequestProperties(aRequestproperties);
        }
        
        /**
         * performExecute() contains our logic, we can pull our name-value pairs out of the requestProperties and
         * send them to the appropriate table
         */
        public void performExecute() throws ECException{        
            
            final String METHODNAME = "performExecute";
            
            LOGGER.entering(CLASSNAME, METHODNAME);
            
            //call super to perform regular steps
            super.performExecute();    
                    
            if(myRequestProperties!=null){        
            Enumeration keys = myRequestProperties.keys();        
            while (keys.hasMoreElements())
            {    
                String keyName = (String)keys.nextElement();        
                //looks for name-value pairs that start with the key name "engraving"
                if (keyName.startsWith(MyOrderFacadeClient.ENGRAVINGKEYNAME))
                {        
                    //values in the pattrvalue table are stored and retrieved based on orderitem_id and pattribute_id
                    String orderitem_id=null; 
                    String pattribute_id=null;
                    
                    //AccessBeans used
                    PAttributeAccessBean pAttAccessBean = null;
                    PAttrValueAccessBean pAttValueAccessBean = null;
                    PAttrStringValueAccessBean pAttStringValueAccessBean = null;
                    PAttrProdAccessBean pAttrProdAccessBean = null;                
                    OrderItemAccessBean orderItemAccessBean = null;                                
                    
                    
                    //engraving keyName will be used to find the correct pattribute_id from the PAttribute table
                    String columnName = keyName.substring(0,keyName.lastIndexOf("_"));
                    //retrieve the engraving value associated with the keyName
                    String value = (String)myRequestProperties.get(keyName);    
                    //retrieve the orderitem_id for this engraving item
                    
                    if(myRequestProperties.containsKey(OrderFacadeConstants.ORDERITEM_ID+keyName.substring(keyName.lastIndexOf("_")))){
                    
                        orderitem_id = (String)myRequestProperties.get(OrderFacadeConstants.ORDERITEM_ID+keyName.substring(keyName.lastIndexOf("_")));
                                                        
                        try {                    
                            //get the pattribute_id from PAttribute table based on the keyName
                            pAttAccessBean = new PAttributeAccessBean();                    
                            Enumeration enumPattAccessBean = pAttAccessBean.findByName(columnName);
                            if(enumPattAccessBean.hasMoreElements()){
                                pAttAccessBean = (PAttributeAccessBean)enumPattAccessBean.nextElement();    
                                
                                pattribute_id = pAttAccessBean.getReferenceNumber();
                                
                                //cross reference the pAttribute_id to ensure that it is a valid order item in the PAttrProd table
                                orderItemAccessBean = new OrderItemAccessBean();
                                pAttrProdAccessBean = new PAttrProdAccessBean();                    
                                orderItemAccessBean.setInitKey_orderItemId(orderitem_id);                    
                                String catentry_id = orderItemAccessBean.getCatalogEntryId(); //get catentry_id based on orderItem_id
                                Enumeration validPattributeIds = pAttrProdAccessBean.findByCatentryId(new Long(catentry_id));    
                                boolean validPAttribute_id = false;
                                while(validPattributeIds.hasMoreElements()){
                                    pAttrProdAccessBean = (PAttrProdAccessBean)validPattributeIds.nextElement();
                                    if((pAttrProdAccessBean.getAttributeId()).equals(pattribute_id)){
                                        //for the current order item, this personalization attribute is allowed
                                        validPAttribute_id = true;
                                    }
                                }                    
                                                    
                                if(validPAttribute_id){                        
                                    //if a PAttrValue table entry already exists update with new value
                                    pAttValueAccessBean = new PAttrValueAccessBean();
                                    Enumeration exsistingPAttValues = pAttValueAccessBean.findByOrderItemId(Long.valueOf(orderitem_id));                         
                                    boolean foundOrderItems_id = false; 
                                    while(exsistingPAttValues.hasMoreElements()){
                                        pAttValueAccessBean =(PAttrValueAccessBean)exsistingPAttValues.nextElement();
                                        //is there a row already for this order_id and this pattribute_id    
                                        if(((String)(pAttValueAccessBean.getAttributeId())).equalsIgnoreCase(pattribute_id)){                                                    
                                            foundOrderItems_id=true; //found row                            
                                            pAttValueAccessBean.setPAttrValue((Object)value);    //do an update with new value                                    
                                            pAttValueAccessBean.commitCopyHelper();
                                        }
                                    }                
                                    
                                    //if no AttrValue table entry exists create a new one
                                    if(!foundOrderItems_id){
                                        pAttStringValueAccessBean = new PAttrStringValueAccessBean(new Long(pattribute_id),null,new Integer(0),(Object)value);
                                        pAttStringValueAccessBean.setOrderItemId(orderitem_id);        
                                        pAttStringValueAccessBean.commitCopyHelper();
                                    }                        
                                }
                            }else{
                                // trace that the product does not have engraving attributes
                                if (com.ibm.commerce.foundation.common.util.logging.LoggingHelper.isTraceEnabled(LOGGER)){
                                    LOGGER.logp(LoggingHelper.DEFAULT_TRACE_LOG_LEVEL,CLASSNAME, METHODNAME, "Rejected engraving attribute.  Catalog item does not allow pAttribute value "+columnName);
                                }
                            }
                                                    
                        } catch (Exception e) {                    
                            e.printStackTrace();
                        }
                    }
                }            
            }
            LOGGER.exiting(CLASSNAME, METHODNAME);
            }
        }    
    }
    

  9. Open ExtComposeOrderDetailsCmdImpl.java and replace the contents with the following code. It extends the ComposeOrderDetailsCmdImpl command to return engraving information, which is associated with ORDERITEMS_ID, PATTRIBUTE_ID and CATENTRY_ID, as name-value pairs.

    package com.mycompany.commerce.customization.order;
    
    import java.rmi.RemoteException;
    import java.util.Enumeration;
    import java.util.Hashtable;
    
    import javax.ejb.CreateException;
    import javax.ejb.FinderException;
    import javax.naming.NamingException;
    
    import com.ibm.commerce.exception.ECException;
    import com.ibm.commerce.exception.ECSystemException;
    import com.ibm.commerce.foundation.common.datatypes.CommerceFoundationFactory;
    import com.ibm.commerce.foundation.common.datatypes.UserDataType;
    import com.ibm.commerce.foundation.common.util.logging.LoggingHelper;
    import com.ibm.commerce.order.facade.datatypes.OrderItemType;
    import com.ibm.commerce.order.facade.server.commands.ComposeOrderDetailsCmdImpl;
    import com.ibm.commerce.order.objects.OrderItemAccessBean;
    import com.ibm.commerce.ras.ECMessage;
    import com.ibm.commerce.utf.objects.PAttrProdAccessBean;
    import com.ibm.commerce.utf.objects.PAttrValueAccessBean;
    import com.ibm.commerce.utf.objects.PAttributeAccessBean;
    
    public class ExtComposeOrderDetailsCmdImpl extends ComposeOrderDetailsCmdImpl {
        
        private static final String CLASSNAME = ExtComposeOrderDetailsCmdImpl.class.getName();
    
        private static final java.util.logging.Logger LOGGER = com.ibm.commerce.foundation.common.util.logging.LoggingHelper
                .getLogger(ExtComposeOrderDetailsCmdImpl.class);
        private static final String METHODNAME = "composeOrderItem";
        
        /**
         * Composes an {@link OrderItemType OrderItem}<code>SDO</code> from the order item
         * access bean specified.
         * 
         * @param aabOrderItem
         *            the order item access bean.
         * @return the {@link OrderItemType OrderItem}<code>SDO</code>.
         * @throws ECException
         */
        protected OrderItemType composeOrderItem(OrderItemAccessBean aabOrderItem) throws ECException {
    
            
            if (com.ibm.commerce.foundation.common.util.logging.LoggingHelper.isEntryExitTraceEnabled(LOGGER)){
                LOGGER.entering(CLASSNAME, METHODNAME);
            }    
            OrderItemType orderItem = super.composeOrderItem(aabOrderItem);
            
            try {
                
    
                // customization code here
                String orderItem_id=aabOrderItem.getOrderItemId();  
                if (com.ibm.commerce.foundation.common.util.logging.LoggingHelper.isTraceEnabled(LOGGER)){
                    LOGGER.logp(LoggingHelper.DEFAULT_TRACE_LOG_LEVEL,CLASSNAME, METHODNAME, "OrderItemId = " + orderItem_id);
                }            
                Hashtable processedAttrs = new Hashtable();
                
                PAttrValueAccessBean pAttValueAccessBean = new PAttrValueAccessBean();
                Enumeration ee = pAttValueAccessBean.findByOrderItemId(new Long(orderItem_id));
                
                //add all attrs that have values.
                while(ee.hasMoreElements()){
                    pAttValueAccessBean =(PAttrValueAccessBean)ee.nextElement();                
                    String attrId=(String)(pAttValueAccessBean.getAttributeId());   
                    if (com.ibm.commerce.foundation.common.util.logging.LoggingHelper.isTraceEnabled(LOGGER)){
                        LOGGER.logp(LoggingHelper.DEFAULT_TRACE_LOG_LEVEL,CLASSNAME, METHODNAME, "PAttributeId= " + attrId);
                    }
                    //get value for the attribute
                    String value=(String)(pAttValueAccessBean.getPAttrValue());
                    if (com.ibm.commerce.foundation.common.util.logging.LoggingHelper.isTraceEnabled(LOGGER)){
                        LOGGER.logp(LoggingHelper.DEFAULT_TRACE_LOG_LEVEL,CLASSNAME, METHODNAME, " engraving information value is "+ value);              
                    }
                    processedAttrs.put(attrId,"");
                                                     
                    //get name of the attribute
                    PAttributeAccessBean pAttAccessBean = new PAttributeAccessBean();
                    pAttAccessBean.setInitKey_referenceNumber(Long.valueOf(attrId));
                    String name=pAttAccessBean.getName();
                    if (com.ibm.commerce.foundation.common.util.logging.LoggingHelper.isTraceEnabled(LOGGER)){
                        LOGGER.logp(LoggingHelper.DEFAULT_TRACE_LOG_LEVEL,CLASSNAME, METHODNAME, "engraving information name is "+ name);                
                    }
                    
                        UserDataType userData = orderItem.getUserData();
                        if (userData == null)
                        {
                            userData = CommerceFoundationFactory.eINSTANCE.createUserDataType();
                            orderItem.setUserData(userData); 
                        }
                        userData.getUserDataField().put(name, value);
    
                }
                
                //scan pattrprod table to check the attributes that do not have the values
                PAttrProdAccessBean pAttrProdAB = new PAttrProdAccessBean();
                Enumeration pAttrProdABs = pAttrProdAB.findByCatentryId(new Long(orderItem.getCatalogEntryIdentifier().getUniqueID()));            
                if (com.ibm.commerce.foundation.common.util.logging.LoggingHelper.isTraceEnabled(LOGGER)){
                    LOGGER.logp(LoggingHelper.DEFAULT_TRACE_LOG_LEVEL,CLASSNAME, METHODNAME, "CatalogEntryID is "+orderItem.getCatalogEntryIdentifier().getUniqueID());
                }    
                while(pAttrProdABs.hasMoreElements()){
                    pAttrProdAB=(PAttrProdAccessBean)pAttrProdABs.nextElement();
                    String attrId1=(String)(pAttrProdAB.getAttributeId());                 
                    Enumeration keys=processedAttrs.keys(); 
                    boolean nameWithValue=false;
                    while  ( keys.hasMoreElements()  ){ 
                        String s=keys.nextElement().toString();
                        if(attrId1.equalsIgnoreCase(s)){   
                            nameWithValue=true;
                        }
                    }    
                    if(!nameWithValue){                    
                        PAttributeAccessBean pAttAccessBean1 = new PAttributeAccessBean();
                        pAttAccessBean1.setInitKey_referenceNumber(new Long(attrId1));
                        String name1=pAttAccessBean1.getName();
                        if (com.ibm.commerce.foundation.common.util.logging.LoggingHelper.isTraceEnabled(LOGGER)){
                            LOGGER.logp(LoggingHelper.DEFAULT_TRACE_LOG_LEVEL,CLASSNAME, METHODNAME, "engraving information name is"+ name1);
                        }
                        UserDataType userData = orderItem.getUserData();
                        if (userData == null)
                        {
                            userData = CommerceFoundationFactory.eINSTANCE.createUserDataType();
                            orderItem.setUserData(userData); 
                        }
                        userData.getUserDataField().put(name1, "");                                                 
                    }              
                }
                
            }
            catch (CreateException e)
            {
                throw new ECSystemException(ECMessage._ERR_CREATE_EXCEPTION, CLASSNAME, METHODNAME,                     new Object[] { e.toString() }, e);            
            } catch (FinderException e) {
                throw new ECSystemException(ECMessage._ERR_FINDER_EXCEPTION, CLASSNAME, METHODNAME,                     new Object[] { e.toString() }, e);
            } catch (NamingException e) {
                throw new ECSystemException(ECMessage._ERR_NAMING_EXCEPTION, CLASSNAME, METHODNAME,                     new Object[] { e.toString() }, e);
            } catch (RemoteException e) {
                throw new ECSystemException(ECMessage._ERR_REMOTE_EXCEPTION, CLASSNAME, METHODNAME,                     new Object[] { e.toString() }, e);
            }
            if (com.ibm.commerce.foundation.common.util.logging.LoggingHelper.isEntryExitTraceEnabled(LOGGER)){
                LOGGER.exiting(CLASSNAME, METHODNAME);
            }
            return orderItem;
        }
    
    }
    

  10. After entering the new code for each Java class, right-click in the editor and select Source then Organize Imports.

  11. Clean and rebuild the entire workspace by selecting Projects in WebSphere Commerce Developer. Then select Clean, ensure that Clean all projects is selected and click OK. Ensure that all build errors have disappeared.

< Previous | Next >


+

Search Tips   |   Advanced Search