Introduced in Feature Pack 1

JET RESTful Resource pattern input file and the Java class it generates

WebSphere Commerce provides a Java Emitter Template (JET) called the JET RESTful Resource pattern. The JET RESTful Resource pattern generates a Java class that retrieves feeds from Web services for a specific URL. To generate the Java class, you must create a pattern input file that contains data that the Java class requires to retrieve the feed. The Java class is called a JAX-RS resource.

Format of the pattern input file

Pattern input files provide the required information to the JET RESTful Resource pattern using the following format:

<rest componentName="component_name" packageNamePrefix="package_name_prefix">
	<noun name="noun_name" pluralNounName="plural_noun_name" 
         defaultAccessProfile="default_access_profile" defaultExpression="default_get_xpath_expression>
		<findBy expression="get_xpath_expression" name="findby_name"/>
	</noun>
</rest>

The following describes the variables in the pattern input file:

Input file variable Description
component_name The name of the component that contains the Web service from which you want to create a feed. If you are using an existing WebSphere Commerce service, obtain the component name by viewing the list in this topic:

WebSphere Commerce Web services

Examples of component names are:

  • Catalog
  • Marketing
  • Order

If you are creating a feed from a custom WebSphere Commerce Web service, use the name of the component containing the custom Web service.

package_name_prefix The prefix of the package that will contain the Java class output by this pattern.
  • For a feed from a WebSphere Commerce noun, use com.ibm.commerce
  • For a feed from a custom noun, use com.your_company_name.commerce, for example, com.mycompany.commerce
noun_name The name of the noun you want to get from the Web service for the Atom feed. To view nouns available for WebSphere Commerce components, see WebSphere Commerce Web services.
plural_noun_name The plural form of the noun you want to get from the Web service for the Atom feed. Use the identical plural_noun_name value you defined in the Atom feed URL in the previous procedure. The WebSphere Commerce convention is to use the plural form of a noun in a RESTful URL.
default_access_profile The name of the default storefront access profile to use for the WebSphere Commerce service request. The access profile defines the data to include in the response. Access profiles are defined for each noun in WebSphere Commerce Web services. Typically, storefront access profiles start with IBM_Store instead of IBM_Admin.
default_get_xpath_expression (Optional) The XPath expression for the GET service that gets all instances of a noun, rather than returning a specific instance of the noun by its identifier. Include this parameter in your pattern input file only if you need the JAX-RS resource to get all instances of a noun. For example, the Catalog noun has a GET XPath expression that gets all the sales catalogs for the store. In this case, the attribute in the pattern input file is:
defaultExpression="/Catalog[@primary='false']"

If your RESTful URL does not include an identifier, the JAX-RS resource uses the default_get_xpath_expression.

get_xpath_expression The XPath expression for the GET service that gets a noun using the internal or external identifier you specified in the URL in the previous procedure.

Example of an XPath expression that uses an internal identifier–Get Catalog service:

/Catalog[CatalogIdentifier[(UniqueID=)]]

This XPath expression gets a catalog by its unique ID and returns the catalog matching the ID.

Important: When including the XPath expression in the pattern input file, specify the following characters for the numeric UniqueID value, regardless of what is in the documented XPath expression:

{0}

The previous example XPath expression must look like this in the pattern input file:

/Catalog[CatalogIdentifier[(UniqueID={0})]]

Note: WebSphere Commerce does not provide a RESTful Web service for the Catalog noun, but you could create one using the procedures in this section.

Example of an XPath expression that uses an external identifier–Get MarketingSpotData service:

/MarketingSpotData[MarketingSpotIdentifier[ExternalIdentifier[(Name=)]]]

This XPath expression gets e-Marketing Spot data by its external identifier (in this case, its name) and returns the data for display to a customer.

Important: When including the XPath expression in the pattern input file, if the identifier value is a string, specify the following characters for the string value, regardless of what is in the documented XPath expression:

\"{0}\"

The previous example XPath expression must look like this in the pattern input file:

/MarketingSpotData[MarketingSpotIdentifier[ExternalIdentifier[(Name=\"{0}\")]]]

findby_name The suffix of the method name that is called when the URL contains an identifier. The pattern will create a method using this suffix for the name. In the generated Java class, the full method name will be findByfindby_name. The findby_name should match the identifier specified for the XPath expression for the Get service. For example, for the Get Catalog XPath expression in the previous row, an appropriate findby_name is Id.

Sample pattern input file

This example input file will generate the Java class required to get feed data from the Get Catalog service based on the unique ID of the catalog:

<rest componentName="Catalog" packageNamePrefix="com.ibm.commerce">
   <noun name="Catalog" pluralNounName="catalogs" defaultAccessProfile="IBM_Store_Details" defaultExpression="/Catalog[@primary='false']">
      <findBy expression="/Catalog[CatalogIdentifier[(UniqueID={0})]]" name="Id"/>
   </noun>
</rest>

Location of the pattern output file

The pattern generates a JAX-RS resource Java class at the following path, based on the variables you entered in the pattern input file:

package_name_prefix.component_name.rest.resources.noun_name.java

For example:

com.ibm.commerce.Catalog.rest.resources.Catalog.java

The following describes key snippets from the Java class file generated using the previous pattern input file example:

Sample snippet 1: JAX-RS URI to resource mapping

This snippet is near the top of the class file. The @Path annotation defines the URIs that this class handles. The annotation is generated based on the noun name in the pattern input file. In this example, the Catalog class, or resource, will handle all URIs in the form */stores/storeId/catalogs.

/**
 * This class converts RESTful Catalog requests into WebSphere
 * Commerce Catalog requests and returns data in either XML, JSON, or
 * Atom feed format.
 */
@Path("stores/{storeId}/catalogs")
@Encoded
public class Catalog {
…

Sample snippet 2: JAX-RS URI to method mapping

This is the middle section of the class file. Its purpose is to:
  • Determine the requested response formats based on the responseFormat query parameters and the HTTP Accept header.
  • Call the findByName helper method to perform the WebSphere Commerce service request.
  • Return the response.

The @Path annotation defines the URIs that this method handles. This value is appended to the path defined for the class and is generated based on the findby_name value specified in the pattern input. In this example, this method handles all URIs in the form */stores/storeId/catalogs/findby_name.

/**
	 * This method performs a GetCatalog by id request.
	 * 
	 * @param id the Catalog id.
	 * @param storeId the store Id.
	 * @param accessProfile the access profile of the Get request.
	 * @param responseFormat the response format (xml, json, or atom).
	 * @return The Catalog noun in the specified format.
	 * @throws WebApplicationException 
	 * @throws IOException
	 * @throws CatalogException
	 */
	@GET
	@Produces( { "application/atom+xml", "application/json", "application/xml" })
	@Path("{id}")
	public Response findById(
	        @PathParam("id") String id,
	        @PathParam("storeId") String storeId,
	        @QueryParam(value = "accessProfile") String accessProfile,
	        @QueryParam(value = "responseFormat") String responseFormat
	        ) throws WebApplicationException, IOException, CatalogException {
	
	    final String METHODNAME = "findById(String, String, String, String, String, String)";
	
	    if (com.ibm.commerce.foundation.common.util.logging.LoggingHelper
	            .isEntryExitTraceEnabled(LOGGER)) {
	        LOGGER.entering(CLASSNAME, METHODNAME);
	    }
	    	  	
	    Response result = null;
	    Object[] params = { id };
	    String expression = MessageFormat.format(FIND_BY_ID_XPATH, params);
	
	    // Perform the service request and return the response in the appropriate format.
	    result = getCatalog(expression, accessProfile, responseFormat);
	    	
	    if (com.ibm.commerce.foundation.common.util.logging.LoggingHelper
	            .isEntryExitTraceEnabled(LOGGER)) {
	        LOGGER.exiting(CLASSNAME, METHODNAME);
	    }
	
	    return result;
	
	}

Sample snippet 3: Find by name helper method

This snippet is near the bottom of the class file. Its purpose is to:
  • Create a GET service request for the noun using the GET XPath expression defined in the pattern input file.
  • Use the JAX-RS runtime to convert the response into Atom format.
   /**
	 * This method performs a <code>GetCatalog</code> service request.
	 * 
	 * @param expression the XPath expression.
	 * @param accessProfile the access profile of the get expression.
	 * @param responseFormat the response format.
	 * @return the Catalog noun.
	 * @throws CatalogException the exception representing the error of the
	 *             <code>GetCatalog<code> request.
	 * @throws WebApplicationException 
	 * @throws IOException
	 */
	protected Response getCatalog(String expression, String accessProfile, String responseFormat)
			throws CatalogException, WebApplicationException, IOException {

		final String METHODNAME = "getCatalog(String, String, String)";

		if (com.ibm.commerce.foundation.common.util.logging.LoggingHelper
				.isEntryExitTraceEnabled(LOGGER)) {
			LOGGER.entering(CLASSNAME, METHODNAME);
		}
		
		 // Get the response format, either from the Http header or URL, the URL takes precedence.
	    MediaType format = StoreConfigurationHelper.getResponseFormat(responseFormat, headers);
		
		if (accessProfile == null) {
	    	accessProfile = DEFAULT_ACCESS_PROFILE;
	    }
						
		// Build the Get request.
		SelectionCriteriaHelper selectionCriteria = buildExpression(expression, accessProfile);
		GetType getVerb = buildGetVerb(selectionCriteria.getSelectionCriteriaExpression());
						
		// Perform the service request.
		CatalogFacadeClient client = new CatalogFacadeClient(businessContext, null);
		DataObject dataArea = (DataObject) client.getCatalog(getVerb);
																
		// For XML or JSON, the JAX-RS runtime will resolve the appropriate provider.
		// For Atom, the feed is directly populated.
		Response result = null;
		if (MediaType.APPLICATION_ATOM_XML_TYPE.isCompatible(format)) {
			AtomFeedSDOProvider provider = new AtomFeedSDOProvider();
			AtomFeed feed = provider.writeTo(dataArea, businessContext, uri, context);
			result = Response.ok(feed).type(MediaType.APPLICATION_ATOM_XML).build();
		} else {
			result = Response.ok(dataArea).type(format).build();
		}	
		
		if (com.ibm.commerce.foundation.common.util.logging.LoggingHelper
				.isEntryExitTraceEnabled(LOGGER)) {
			LOGGER.exiting(CLASSNAME, METHODNAME);
		}

		return result;
	}