Feature Pack 8WebSphere Commerce Developer

Creating REST services using the configuration-based controller command and data bean mapping framework

You can create REST services using the configuration-based controller command and data bean mapping framework. It helps create REST services and automates mappings using the restClassicSampleGen utility.

Procedure

  1. Create your resource handler, following the specified format as a base.
    The following sample resource handler accepts two resources. One gets CatalogEntry data from a data bean, and the other updates a CatalogEntry with a command:
    
    import java.util.logging.Logger;
    
    import javax.ws.rs.GET;
    import javax.ws.rs.POST;
    import javax.ws.rs.Path;
    import javax.ws.rs.PathParam;
    import javax.ws.rs.Produces;
    import javax.ws.rs.QueryParam;
    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.core.Response;
    
    import com.ibm.commerce.beans.DataBean;
    import com.ibm.commerce.catalog.beans.CatalogEntryDataBean;
    import com.ibm.commerce.catalogmanagement.commands.CatalogEntryUpdateCmd;
    import com.ibm.commerce.command.ControllerCommand;
    import com.ibm.commerce.foundation.logging.LoggingHelper;
    import com.ibm.commerce.rest.classic.core.AbstractConfigBasedClassicHandler;
    
    /**
     * This is a very simple REST handler that extends the configuration-based REST
     * classic handler. It demonstrates how to create REST resources based on a
     * {@link DataBean} and a {@link ControllerCommand} with minimal coding, as all
     * the input/output information is stored in a configuration mapping file.
     * 
     */
    @Path("store/{storeId}/sample")
    public class SampleCatalogEntryClassicRestHandler extends AbstractConfigBasedClassicHandler
    {
    	/**
    	 * IBM Copyright notice field.
    	 */
    	public static final String COPYRIGHT = com.ibm.commerce.copyright.IBMCopyright.SHORT_COPYRIGHT;
    
    	private static final String CLASSNAME = RestClassicDataBeanHandler.class.getName();
    
    	private static final Logger LOGGER = LoggingHelper.getLogger(RestClassicDataBeanHandler.class);
    
    	private static final String RESOURCE_NAME = "sample";
    
    	/*
    	 * (non-Javadoc)
    	 * @see com.ibm.commerce.foundation.rest.resourcehandler.IResourceHandler#getResourceName()
    	 */
    	@Override
    	public String getResourceName()
    	{
    		return RESOURCE_NAME;
    	}
    
    	/**
    	 * Used with WC to instantiate handler.
    	 */
    	public SampleCatalogEntryClassicRestHandler()
    	{
    		super();
    	}
    
    	/**
    	 * A sample REST GET that executes the {@link CatalogEntryDataBean} based on
    	 * the request parameters and profile specified.
    	 * 
    	 * @param storeId
    	 * @param responseFormat
    	 * @param profileName
    	 * @param catalogEntryID
    	 * @return the response
    	 */
    	@GET
    	@Path("catalogEntry")
    	@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.APPLICATION_XHTML_XML, MediaType.APPLICATION_ATOM_XML })
    	public Response processRequest(
    			@PathParam("storeId") String storeId,
    			@QueryParam("responseFormat") String responseFormat,
    			@QueryParam("profileName") String profileName,
    			@QueryParam("catalogEntryID") String catalogEntryID)
    	{
    
    		final String METHODNAME = "processRequest(String storeId, String profileName, String responseFormat, String catalogEntryID) ";
    		boolean entryExitTraceEnabled = LoggingHelper.isEntryExitTraceEnabled(LOGGER);
    		if (entryExitTraceEnabled)
    		{
    			Object[] objArr = new Object[] { storeId, profileName, responseFormat, catalogEntryID };
    			LOGGER.entering(CLASSNAME, METHODNAME, objArr);
    		}
    		
    		Response result = executeConfigBasedBeanWithContext(CatalogEntryDataBean.class.getName(), profileName, responseFormat,
    				null);
    
    		if (entryExitTraceEnabled)
    		{
    			LOGGER.exiting(CLASSNAME, METHODNAME, result);
    		}
    
    		return result;
    	}
    
    	/**
    	 * A sample REST POST that executes the {@link CatalogEntryUpdateCmd} based on
    	 * the request parameters and profile specified.
    	 * 
    	 * @param storeId
    	 * @param responseFormat
    	 * @param profileName
    	 * @return the response
    	 */
    	@POST
    	@Path("catalogEntryUpdate")
    	@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.APPLICATION_XHTML_XML, MediaType.APPLICATION_ATOM_XML })
    	public Response processRequest(@PathParam("storeId") String storeId,
    			@QueryParam(value = "responseFormat") String responseFormat,
    			@QueryParam(value = "profileName") String profileName)
    	{
    		final String METHODNAME = "processRequest(String storeId, String profileName, String responseFormat) ";
    		boolean entryExitTraceEnabled = LoggingHelper.isEntryExitTraceEnabled(LOGGER);
    		if (entryExitTraceEnabled)
    		{
    			Object[] objArr = new Object[] { storeId, profileName, responseFormat };
    			LOGGER.entering(CLASSNAME, METHODNAME, objArr);
    		}
    
    		Response result = executeConfigBasedCommandWithContext(CatalogEntryUpdateCmd.class.getName(), profileName, responseFormat,
    				storeId, null);
    
    		if (entryExitTraceEnabled)
    		{
    			LOGGER.exiting(CLASSNAME, METHODNAME, result);
    		}
    
    		return result;
    	}
    
    }
    
    
  2. Decide which entry point class (data bean or controller command) you want to use in your resource handler.

    REST calls typically require a handler that contains an entry point into the configuration-based classic handler class. The following entry points are available by default:

    1. public Response executeConfigBasedBeanWithContext(String beanClassName, String profileName, String responseFormat, Map<String, Object> paramOverrideMap)

      This method sets up the {@link BusinessContextService} start request, then delegates to {@link #executeConfigBasedBean(String, String, String, Map)}, and finally ends BCS the request.

      The following parameters are available by default:
      beanClassName
      The data bean class name.
      profileName
      The profile name for the data bean in the configuration.
      responseFormat
      The response format to use for generating the result.
      paramOverrideMap
      Defines any parameters that you want to add or override from the request object that is associated to this handler.
      Typically used if there are path parameters or entity data you want included when it maps the query parameters with the input for the command.
      The key must be a string. The value can be any type object.
      The value can be null.
    2. public JSONObject executeConfigBasedBean(String beanClassName, String profileName, String responseFormat, Map<String, Object> paramOverrideMap) throws Exception

      This method processes a data bean request using the configuration-based profile mappings. It assumes that the {@link BusinessContextService} is dealt with by the caller.

      The input parameters are automatically completed based on any path parameters that are specified in the URL, followed by any query parameters.

      An override map can be provided to inject more parameters or override preexisting parameters.

      The following parameters are available by default:
      beanClassName
      The data bean class name.
      profileName
      The profile name for the data bean in the configuration.
      responseFormat
      The response format to use for generating the result.
      paramOverrideMap
      Defines any parameters that you want to add or override from the request object that is associated to this handler.
      Typically used if there are path parameters or entity data you want included when it maps the query parameters with the input for the command.
      The key must be a string. The value can be any type object.
      The value can be null.
    3. public Response executeConfigBasedCommandWithContext(String commandInterfaceName, String profileName, String responseFormat, String storeId, Map<String, Object> paramOverrideMap)

      This method sets up the {@link BusinessContextService} start request, then delegates to * {@link #executeControllerCommand(String, String, TypedProperty, String)}, and finally ends BCS the request.

      The following parameters are available by default:
      commandInterfaceName
      The controller command interface name.
      profileName
      The profile name for the controller command in the configuration.
      responseFormat
      The response format to use for generating the result.
      paramOverrideMap
      Defines any parameters that you want to add or override from the request object that is associated to this handler.
      Typically used if there are path parameters or entity data you want included when it maps the query parameters with the input for the command.
      The key must be a string. The value can be any type object.
      The value can be null.
    4. public JSONObject executeConfigBasedCommand(String pCmdInterfaceName, String profileName, String responseFormat, String storeId, Map<String, Object> paramOverrideMap) throws Exception

      This method processes a controller command request using the configuration-based profile mappings. It assumes that the {@link BusinessContextService} is dealt with by the caller.

      The input parameters are automatically completed based on any path parameters that are specified in the URL, followed by any parameters that are found in the request body.

      An override map can be provided to inject more parameters or override preexisting parameters.

      Although the store ID is specified in the method call, it is not automatically included in the list of parameters that are provided to populate the setters of the command. You must explicitly add it to the override map, or have it included with the URL path parameters or request body.

      pCmdInterfaceName
      The controller command interface name.
      profileName
      The profile name for the controller command in the configuration.
      responseFormat
      The response format to use for generating the result.
      storeId
      The store ID.
      paramOverrideMap
      Defines any parameters that you want to add or override from the request object that is associated to this handler.
      Typically used if there are path parameters or entity data you want included when it maps the query parameters with the input for the command.
      The key must be a string. The value can be any type object.
      The value can be null.
  3. Create the XML mapping files, either by using the restClassicSampleGen utility, or manually:
    • Recommended: Using the restClassicSampleGen utility:

      Go to the WCDE_installdir\bin directory and run the utility:

      restClassicSampleGen.bat searchType=searchType basePackage=basePackage locationType=locationType location=location outputDir=outputDir classTypes=classTypes inputPrefix=inputPrefix sampleDepth=sampleDepth additionalClassPath=additionalClassPath

      Where:
      searchType
      Use ABSOLUTE when explicitly stating the classes to generate mappings for.
      Use PATTERN to find classes that match the specified Java regular expression patterns.
      The default value is ABSOLUTE.
      basePackage
      The base Java package (excluding final period) to generate mappings for.
      The default value is ''.
      locationType
      Use FILE to specify that a file is used containing line-separated entries of either Java regular expression patterns, or explicit classes in com/example/MyClass.java format.
      Use DIRECT if directly specifying a Java regular expression pattern or class name.
      The default value is DIRECT.
      location
      If the locationType FILE was specified, it is the path to the file.
      If the locationType DIRECT was specified, it is the actual Java regular expression or explicit class.
      outputDir
      The output directory. The directory is created if it does not exist. Subdirectories are created for each class type generated.
      classTypes
      One or more of the comma-separated values DATABEAN, CONTROLLERCOMMAND, and ALL.
      The default value is ALL.
      inputPrefix
      Specifies characters to prefix input parameters with in the mapping file.
      The default value is ''.
      sampleDepth
      The depth of mappings to create when recursively traversing the classes.
      The default value is 3.
      additionalClassPath
      Specifies extra JAR files and directories to include to locate classes, which are separated with ;.
      Note:
      • If spaces are used in any of the property values, you must surround the entire property and value with quotations. For example, "property1=value 1".
      • Predefined values such as ABSOLUTE are case-insensitive.
      For example:
      • To generate a mapping for the specified data bean:
        
        restClassicSampleGen.bat location=com.ibm.commerce.catalog.beans.AttributeFloatValueDataBean outputDir=C:/Temp/ClassicSamples
        
      • To generate mappings for data beans only, starting from the base package com.example.myclasses, specifying a pattern directly as a property, and prefixing all input parameters with q:
        
        restClassicSampleGen.bat searchType=pattern basePackage=com.example.myclasses classTypes=DATABEAN "location=.*" inputPrefix=q outputDir=C:/Temp/ClassicSamples
        
      • To generate the classes that are specified in a file, with a mapping depth of 1. Then, adding a JAR file and directory to the class path to locate the classes:
        
        restClassicSampleGen.bat locationType=file "location=C:/users/admin/mapping list.txt" sampleDepth=1 "additionalClassPath=c:/lib/MyJar.jar;c:/classdir" outputDir=c:/users/admin/samples
        

      Ensure that the utility runs successfully. Check the WCDE_installdir\logs\restclassic.log file for details.

    • Otherwise, to manually create the XML mapping files, create mapping files that resemble the following samples, and save them in the following locations:
      Rest.war/WebContent/WEB-INF/config/beanMapping-ext
      The directory to publish new data beans, or extend the existing data beans.
      Rest.war/WebContent/WEB-INF/config/commandMapping-ext
      The directory to publish new controller commands, or extend the existing controller commands.
      Sample data bean mapping file (com.ibm.commerce.catalog.beans.CatalogEntryDataBean.xml):
      
      <?xml version="1.0" encoding="UTF-8"?>
      <bean>
         <profiles>
            <profile name="sample">
               <inputs>
                  <input inputName="associationType" methodName="setAssociationType"/>
                  <input inputName="attachmentUsage" methodName="setAttachmentUsage"/>
                  <input inputName="availabilityDate" methodName="setAvailabilityDate"/>
                  <input inputName="baseItemId" methodName="setBaseItemId"/>
                  <input inputName="buyable" methodName="setBuyable"/>
                  <input inputName="catalogEntryID" methodName="setCatalogEntryID"/>
                  <input inputName="compactProperties" methodName="setCompactProperties"/>
                  <input inputName="description" methodName="setDescription"/>
                  <input inputName="discontinueDate" methodName="setDiscontinueDate"/>
                  <input inputName="endDate" methodName="setEndDate"/>
                  <input inputName="endOfServiceDate" methodName="setEndOfServiceDate"/>
                  <input inputName="field1" methodName="setField1"/>
                  <input inputName="field2" methodName="setField2"/>
                  <input inputName="field3" methodName="setField3"/>
                  <input inputName="field4" methodName="setField4"/>
                  <input inputName="field5" methodName="setField5"/>
                  <input inputName="initKey_catalogEntryReferenceNumber" methodName="setInitKey_catalogEntryReferenceNumber"/>
                  <input inputName="itemspc_id" methodName="setItemspc_id"/>
                  <input inputName="language_id" methodName="setLanguage_id"/>
                  <input inputName="lastOrderDate" methodName="setLastOrderDate"/>
                  <input inputName="lastUpdate" methodName="setLastUpdate"/>
                  <input inputName="manufacturerName" methodName="setManufacturerName"/>
                  <input inputName="manufacturerPartNumber" methodName="setManufacturerPartNumber"/>
                  <input inputName="markForDelete" methodName="setMarkForDelete"/>
                  <input inputName="memberId" methodName="setMemberId"/>
                  <input inputName="oid" methodName="setOid"/>
                  <input inputName="onAuction" methodName="setOnAuction"/>
                  <input inputName="onSpecial" methodName="setOnSpecial"/>
                  <input inputName="partNumber" methodName="setPartNumber"/>
                  <input inputName="shipping" methodName="setShipping"/>
                  <input inputName="startDate" methodName="setStartDate"/>
                  <input inputName="state" methodName="setState"/>
                  <input inputName="url" methodName="setUrl"/>
               </inputs>
               <outputs>
                  <output methodName="getApplicableContractIds" outputName="applicableContractIds"/>
                  <output methodName="getAvailabilityDate" outputName="availabilityDate"/>
                  <output methodName="getAvailabilityDay" outputName="availabilityDay"/>
                  <output methodName="getAvailabilityMonth" outputName="availabilityMonth"/>
                  <output methodName="getAvailabilityYear" outputName="availabilityYear"/>
                  <output methodName="getBaseItemIdInEJBType" outputName="baseItemId"/>
                  <output methodName="getBuyableInEJBType" outputName="buyable"/>
                  <output methodName="getCatalogEntryID" outputName="catalogEntryID"/>
                  <output methodName="getCatalogEntryReferenceNumberInEJBType" outputName="catalogEntryReferenceNumber"/>
                  <output methodName="getDiscontinueDate" outputName="discontinueDate"/>
                  <output methodName="getDiscontinueDay" outputName="discontinueDay"/>
                  <output methodName="getDiscontinueMonth" outputName="discontinueMonth"/>
                  <output methodName="getDiscontinueYear" outputName="discontinueYear"/>
                  <output methodName="getEndDate" outputName="endDate"/>
                  <output methodName="getEndDay" outputName="endDay"/>
                  <output methodName="getEndMonth" outputName="endMonth"/>
                  <output methodName="getEndOfServiceDate" outputName="endOfServiceDate"/>
                  <output methodName="getEndOfServiceDay" outputName="endOfServiceDay"/>
                  <output methodName="getEndOfServiceMonth" outputName="endOfServiceMonth"/>
                  <output methodName="getEndOfServiceYear" outputName="endOfServiceYear"/>
                  <output methodName="getEndYear" outputName="endYear"/>
                  <output methodName="getField1InEJBType" outputName="field1"/>
                  <output methodName="getField2InEJBType" outputName="field2"/>
                  <output methodName="getField3InEJBType" outputName="field3"/>
                  <output methodName="getField4" outputName="field4"/>
                  <output methodName="getField5" outputName="field5"/>
                  <output methodName="getFormattedAvailabilityDate" outputName="formattedAvailabilityDate"/>
                  <output methodName="getFormattedDiscontinueDate" outputName="formattedDiscontinueDate"/>
                  <output methodName="getFormattedEndDate" outputName="formattedEndDate"/>
                  <output methodName="getFormattedEndOfServiceDate" outputName="formattedEndOfServiceDate"/>
                  <output methodName="getFormattedLastOrderDate" outputName="formattedLastOrderDate"/>
                  <output methodName="getFormattedStartDate" outputName="formattedStartDate"/>
                  <output methodName="isAnyMerchandisingAssociated" outputName="isAnyMerchandisingAssociated"/>
                  <output methodName="isBundle" outputName="isBundle"/>
                  <output methodName="isCalculatedContractPriced" outputName="isCalculatedContractPriced"/>
                  <output methodName="isCatalogEntryAllowedPriceRanges" outputName="isCatalogEntryAllowedPriceRanges"/>
                  <output methodName="isDynamicKit" outputName="isDynamicKit"/>
                  <output methodName="isItem" outputName="isItem"/>
                  <output methodName="isListPriced" outputName="isListPriced"/>
                  <output methodName="isMerchandisingAssociated" outputName="isMerchandisingAssociated"/>
                  <output methodName="isPackage" outputName="isPackage"/>
                  <output methodName="isProduct" outputName="isProduct"/>
                  <output methodName="getItemspc_idInEJBType" outputName="itemspc_id"/>
                  <output methodName="getLanguage_idInEJBType" outputName="language_id"/>
                  <output methodName="getLastOrderDate" outputName="lastOrderDate"/>
                  <output methodName="getLastOrderDay" outputName="lastOrderDay"/>
                  <output methodName="getLastOrderMonth" outputName="lastOrderMonth"/>
                  <output methodName="getLastOrderYear" outputName="lastOrderYear"/>
                  <output methodName="getLastUpdateInEJBType" outputName="lastUpdate"/>
                  <output methodName="getManufacturerName" outputName="manufacturerName"/>
                  <output methodName="getManufacturerPartNumber" outputName="manufacturerPartNumber"/>
                  <output methodName="getMarkForDeleteInEJBType" outputName="markForDelete"/>
                  <output methodName="getMemberIdInEJBType" outputName="memberId"/>
                  <output methodName="getObjectPath" outputName="objectPath"/>
                  <output methodName="getOid" outputName="oid"/>
                  <output methodName="getOnAuctionInEJBType" outputName="onAuction"/>
                  <output methodName="getOnSpecialInEJBType" outputName="onSpecial"/>
                  <output methodName="getParentCatalogEntryIds" outputName="parentCatalogEntryIds"/>
                  <output methodName="getPartNumber" outputName="partNumber"/>
                  <output methodName="getStartDate" outputName="startDate"/>
                  <output methodName="getStartDay" outputName="startDay"/>
                  <output methodName="getStartMonth" outputName="startMonth"/>
                  <output methodName="getStartYear" outputName="startYear"/>
                  <output methodName="getState" outputName="state"/>
                  <output methodName="getType" outputName="type"/>
                  <output methodName="getUrl" outputName="url"/>
               </outputs>
            </profile>
         </profiles>
      </bean>
      
      Sample controller command mapping file (com.ibm.commerce.catalogmanagement.commands.CatalogEntryUpdateCmd.xml):
      
      <?xml version="1.0" encoding="UTF-8"?>
      <command>
         <profiles>
            <profile name="sample">
               <inputs>
                  <input inputName="URL" methodName="setURL"/>
                  <input inputName="XMLdetail" methodName="setXMLdetail"/>
                  <input inputName="auxdescription1" methodName="setAuxdescription1"/>
                  <input inputName="auxdescription2" methodName="setAuxdescription2"/>
                  <input inputName="availabilityDate" methodName="setAvailabilityDate"/>
                  <input inputName="availabilitydate" methodName="setAvailabilitydate"/>
                  <input inputName="available" methodName="setAvailable"/>
                  <input inputName="buyable" methodName="setBuyable"/>
                  <input inputName="catEntURL" methodName="setCatEntURL"/>
                  <input inputName="catentryId" methodName="setCatentryId"/>
                  <input inputName="descLanguage" methodName="setDescLanguage"/>
                  <input inputName="discontinueDate" methodName="setDiscontinueDate"/>
                  <input inputName="endDate" methodName="setEndDate"/>
                  <input inputName="endOfServiceDate" methodName="setEndOfServiceDate"/>
                  <input inputName="expirationdate" methodName="setExpirationdate"/>
                  <input inputName="field1" methodName="setField1"/>
                  <input inputName="field2" methodName="setField2"/>
                  <input inputName="field3" methodName="setField3"/>
                  <input inputName="field4" methodName="setField4"/>
                  <input inputName="field5" methodName="setField5"/>
                  <input inputName="fullimage" methodName="setFullimage"/>
                  <input inputName="keyword" methodName="setKeyword"/>
                  <input inputName="lastOrderDate" methodName="setLastOrderDate"/>
                  <input inputName="longdescription" methodName="setLongdescription"/>
                  <input inputName="markfordelete" methodName="setMarkfordelete"/>
                  <input inputName="memberId" methodName="setMemberId"/>
                  <input inputName="mfname" methodName="setMfname"/>
                  <input inputName="mfpartnumber" methodName="setMfpartnumber"/>
                  <input inputName="name" methodName="setName"/>
                  <input inputName="onauction" methodName="setOnauction"/>
                  <input inputName="onspecial" methodName="setOnspecial"/>
                  <input inputName="partnumber" methodName="setPartnumber"/>
                  <input inputName="published" methodName="setPublished"/>
                  <input inputName="shortdescription" methodName="setShortdescription"/>
                  <input inputName="startDate" methodName="setStartDate"/>
                  <input inputName="thumbnail" methodName="setThumbnail"/>
               </inputs>
               <outputs>
                  <output methodName="getCatentryId" outputName="catentryId"/>
                  <output methodName="getPartnumber" outputName="partnumber"/>
               </outputs>
            </profile>
         </profiles>
      </command>