Creating REST services using the configuration-based controller command and data bean mapping framework
Procedure
-
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; } }
-
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:
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.
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.
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.
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.
-
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.
- basePackage
- The base Java package (excluding final period) to generate mappings for.
- 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.
- location
- If the locationType FILE was specified, it is the path to the file.
- 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.
- inputPrefix
- Specifies characters to prefix input parameters with in the mapping file.
- sampleDepth
- The depth of mappings to create when recursively traversing the classes.
- 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>
- Recommended: Using the restClassicSampleGen utility: