(Developer)Configuration-based controller command and data bean mapping framework
The configuration-based controller command and data bean mapping framework allows the activation of data beans or the running of controller commands using REST services. The framework significantly reduces the amount of custom code necessary. It provides a way to describe what inputs and outputs are required from a data bean or controller command through a mapping file. A mapping file represents one data bean or controller command. It is further subdivided into profiles, allowing multiple REST resources with different properties to work on the same data bean or controller command. The custom code required to write a resource handler for a single REST resource can be as simple as a single line. The input mapping, type casting, activation, running, and responses are all handled by the framework. To help produce a custom mapping file and handler, a generator tool is provided (restClassicSampleGen), further reducing the effort of creating custom REST resources.Note: This framework does not use the request properties object (setRequestProperties method) for controller commands. We must define individual setter and getter methods in the controller command. If you need to use the request properties, use the AbstractClassicResourceHandler directly. The configuration-based controller command and data bean mapping framework uses the following concepts:
- AbstractConfigBasedClassicHandler
The main entry point (superclass) from which all configuration-based handlers extend.
The abstract is itself a subclass of AbstractClassicResourceHandler, which is the base class for a REST resource handler.
Within are methods to activate data beans and run controller commands.
- Data bean and controller command models
Internally, data beans and controller commands are parsed on-demand into models, which are then cached and used by the framework.
- Configuration of data bean and controller command mappings to REST
To make REST calls to data beans and controller commands, mapping configuration files are used.
These mapping configuration files are broken up into profiles, which allow different types of calls for the same data bean or controller command. For example, to specify different output values per profile.
Profiles are included by default for REST data bean and controller command services, while we can add our own profiles to a customization extension directory.
Each configuration file exists for a single data bean or controller command. They describe the mapping of input names (from the REST call) to the corresponding data bean or controller command setter-type method. For each profile in the file, output mappings are supplied. They describe how the getter-type methods and properties from the data bean or controller command should be mapped back to a REST entity output. For example, in JSON format.
The following diagram shows the configuration-based command and data bean mapping framework:Where:
- A REST call is made to access a data bean (GET) or a controller command (POST).
- The data bean or controller command handler intercepts the call. It requests the configuration-based REST framework to set the properties for the data bean or controller command, activate, and return the response.
- The framework performs the following tasks:
- Introspects the data bean or controller command class to build its model. This model is then cached. A RestException occurs if there is a problem with the model.
Note: Setter-methods that have the same name but take different parameters, for example, String versus Long, are considered. The ideal parameter is chosen, based on the data type passed in for the setter.
- Parses the mapping profile, so it can determine how to map from the REST call to the data bean or controller command. Then, map the response back to the HTTP format requested. For example, JSON. The mapping profile is then cached. A RestException occurs if there is a problem with the mapping file.
- Instantiates the data bean or controller command.
- Populates the setter-methods based on the mapping file and data that is provided from the REST call.
- Activates the data bean or runs the controller command.
- Constructs the response using the mapping model to determine what response methods (getter-type methods) to call on the data bean or controller command.
- After all values are fetched, the response is returned to the main handler, and is then transmitted to the client.
Framework entry points
A REST call still requires the creation of a handler, based on Apache Wink/JAX-RS. The handler is relatively small. It is typically required to define the annotations for Apache Wink to understand how to make the REST call to the handler and supply the requested information. The code that is contained within the handler is typically one line of code, consisting of the entry point into the configuration-based classic handler. 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 to add or override from the request object 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.
- public JSONObject executeConfigBasedBean
(String beanClassName, String profileName, String responseFormat, Map<String, Object> paramOverrideMap) throws ExceptionThis 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 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 to add or override from the request object 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.
- 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 to add or override from the request object 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.
- public JSONObject executeConfigBasedCommand
(String pCmdInterfaceName, String profileName, String responseFormat, String storeId, Map<String, Object> paramOverrideMap) throws ExceptionThis 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 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 provided to populate the setters of the command. We 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 to add or override from the request object 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.
Mapping files
The built-in and extension points are composed of four directories:
- Rest.war/WebContent/WEB-INF/config/beanMapping
Reserved for IBM internal use. Contains the default data bean profiles.
- Rest.war/WebContent/WEB-INF/config/beanMapping-ext
Used to publish new data beans and extend the default data beans.
- Rest.war/WebContent/WEB-INF/config/commandMapping
Reserved for IBM internal use. Contains the default controller command profiles.
- Rest.war/WebContent/WEB-INF/config/commandMapping-ext
Used to publish new controller commands and extend the default controller commands.
The configuration files are named after the fully qualified name of the data bean or controller command that they expose. Any profiles in the extension directories take precedence over the ones in the default directories. This enables you to override default profiles. However, the preferred method is to subclass a data bean or create a new controller command interface that extends another, and refer to the original profile in their own profile.
Creating mapping files
We can create the XML mapping files, either using the restClassicSampleGen utility, or manually.
For more information about its usage, see Creating REST services using the configuration-based controller command and data bean mapping framework.
Sample data bean mapping file
The following snippet is a sample data bean mapping file for a sample profile. Output method entries can be nested, to allow the retrieval of nested data from the result of another method:
- com.ibm.commerce.common.beans.StoreDataBean.xml
<?xml version="1.0" encoding="UTF-8"?> <bean> <profiles> <profile name="IBM_Store_Summary"> <inputs> <input methodName="setStoreId" inputName="storeId"/> <input methodName="setStoreRelationshipTypeName" inputName="storeRelationshipTypeName"/> <input methodName="setJspStoreDir" inputName="jspStoreDir"/> </inputs> <outputs> <output methodName="getStoreLevel" outputName="storeLevel"/> <output methodName="getFilePath" outputName="filePath"/> <output methodName="getJspPath" outputName="jspPath"/> <output methodName="getJspStoreDirFilePath" outputName="jspStoreDirFilePath"/> <output methodName="getJspStoreDir" outputName="jspStoreDir"/> <output methodName="getStoreLevel" outputName="storeLevel"/> <output methodName="getStoreType" outputName="storeType"/> <output methodName="getDirectory" outputName="directory"/> <output methodName="getRelatedStoresByStoreRelationshipTypeName" outputName="relatedStores"/> <output methodName="getStoreEntityDescriptionDataBean" outputName="storeEntityDescription"> <output methodName="getDisplayName" outputName="displayName"/> </output> </outputs> </profile> <profile name="IBM_Store_DisplayName"> <inputs> <input methodName="setStoreId" inputName="storeId"/> <input methodName="setStoreRelationshipTypeName" inputName="storeRelationshipTypeName"/> <input methodName="setJspStoreDir" inputName="jspStoreDir"/> </inputs> <outputs listName="resultList" > <output methodName="getStoreEntityDescriptionDataBean" outputName="storeEntityDescription"> <output methodName="getDisplayName" outputName="displayName"/> </output> </outputs> </profile> </profiles> </bean>
Sample controller command mapping file
The following snippet is a sample controller command mapping file for a sample profile:
- com.ibm.commerce.catalogmanagement.commands.CatalogEntryUpdateCmd.xml
<?xml version="1.0" encoding="UTF-8"?> <command> <inputs> <input inputName="auxdescription1" methodName="setAuxdescription1"/> <input inputName="auxdescription2" methodName="setAuxdescription2"/> <input inputName="catentryId" methodName="setCatentryId"/> </inputs> <profiles> <profile name="sample"> <outputs> <output methodName="getCatentryId" outputName="catentryId"/> </outputs> </profile> </profiles> </command>
Mapping file structure
The mapping files use the following structure:
- bean or command
The root element of the configuration file.
- inputs
List of inputs to the data bean or controller command. Inputs are merged between the default and extension version of the file.
- profiles
List of profiles that are exposed as output of the data bean or controller command.
- input
An element that represents an input to a data bean or controller command.
- methodName
The name of the method to call on the data bean or controller command for setting the input property. For example: setCatalogId.
- inputName
The name of the input that is read from the request.
- required
Specifies whether the input is mandatory (true or false). Missing mandatory inputs cause request failures.
- profile
A profile represents a subset of the output fields of a data bean or controller command that are exposed. Different profiles have different names. All the default profiles have a name that is prefixed by IBM_.
- name
The name of the profile.
- outputs
A list of outputs to the profile.
- outputs
Surrounds a list of output elements.
- listName
An optional attribute that enables you to surround the REST response with an array of the provided name. Typically used in default profiles with a name of resultList for REST calls that return a single object to create consistency with list-type REST calls that return a resultList array.
- output
An output represents a field that is completed the response.
- methodName
The name of the method to call on the data bean or controller command to get the output value. The method must return a simple type, such as a number, Boolean, date, or string. Otherwise, it must be a step towards a nested output. Failure to do so results in an exception.
- outputName
The name of the output as it appears in the JSON or XML response.
- list of other output nodes
Outputs might look further down the data bean relationships to get properties of their embedded objects.
- extend
Identifies a profile that the current profile extends. All inputs and outputs of the profile is added to the current profile. Typically used for customization.
- profileName
The name of the profile.
- profileClass
The fully qualified class name containing the profile to extend. Default is the same name as the class the current profile represents. Enables an extension to extend a default profile.