RESTful API Support – Content Context Aware JAX-RS Services
1. Overview
Bloomreach Content supports content and context-aware JAX-RS services. This allows you to develop JAX-RS components for your content and use the full set of XM URL mapping and link rewriting features within your JAX-RS endpoints.
Info: Bloomreach provides several options for exposing REST APIs. Review this overview to determine which approach fits your requirements.
To use content/context-aware JAX-RS services, configure the relevant mount(s) in the repository to use the JaxrsContentRestPipeline. You must also enable this pipeline in your Spring configuration.
2. Enabling a Content/Context Aware RESTful Mount
To expose content/context-aware RESTful JAX-RS services, create a dedicated mount in your configuration.
/restapi: jcr:primaryType: hst:mount hst:alias: restapi hst:namedpipeline: JaxrsRestContentPipeline
This configuration creates a /restapi mount that routes requests through the JaxrsRestContentPipeline. This pipeline is provided by default and supports content/context-aware RESTful services.
If you add the restapi mount directly under the hst:root mount, any URL starting with /restapi/ will be processed as a RESTful JAX-RS service endpoint.
The mount alias restapi can be referenced when generating links using the <hst:link /> tag by specifying the mount attribute.
3. Developing and Configuring Content/Context Aware JAX-RS Components
You can implement any JAX-RS component for use with XM. The root @Path must match the primary node type name, as shown below:
package org.hippoecm.hst.demo.jaxrs.services; @Path("/demosite:productdocument/") public class ProductContentResource extends AbstractContentResource { @GET @Path("/") public ProductRepresentation getProductResource( @Context HttpServletRequest servletRequest, @Context HttpServletResponse servletResponse) { // Implementation here return null; } }
The JaxrsRestContentPipeline dynamically constructs the JAX-RS resource base path using the primary node type of the target content node. It then invokes the JAX-RS engine to match the request path to a registered resource.
Your JAX-RS component receives the HstRequestContext for the request, giving you access to the target content node and the original invocation path.
For example, if you access http://localhost:8080/site/restapi/products/opel.html and the node at /products/opel is of type demosite:productdocument, the getProductResource method in the example above is invoked.
To register your JAX-RS component, add its bean definition to the sourceList of customRestContentResourceProviders in your Spring configuration:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!-- Import pipeline configurations for JaxrsRestPlainPipeline and JaxrsRestContentPipeline --> <import resource="classpath:/org/hippoecm/hst/site/optional/jaxrs/SpringComponentManager-rest-jackson.xml" /> <import resource="classpath:/org/hippoecm/hst/site/optional/jaxrs/SpringComponentManager-rest-plain-pipeline.xml" /> <import resource="classpath:/org/hippoecm/hst/site/optional/jaxrs/SpringComponentManager-rest-content-pipeline.xml" /> <!-- Plain JAX-RS Resource Providers (not used for Content/Context Aware JAX-RS Services) --> <bean id="customRestPlainResourceProviders" class="org.springframework.beans.factory.config.ListFactoryBean"> <property name="sourceList"> <list> </list> </property> </bean> <!-- Content/Context Aware JAX-RS Resource Providers --> <bean id="customRestContentResourceProviders" class="org.springframework.beans.factory.config.ListFactoryBean"> <property name="sourceList"> <list> <!-- Register your JAX-RS component as a singleton resource provider --> <bean class="org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider"> <constructor-arg> <bean class="org.hippoecm.hst.demo.jaxrs.services.ProductContentResource" /> </constructor-arg> </bean> </list> </property> </bean> </beans>
You can register additional custom JAX-RS components as needed.
4. Generating URLs and Links
You can generate URLs for RESTful services using the XM API and tag libraries.
To create a link to the RESTful services mount in a JSP page:
<script language="javascript"> // Generate a URI for the RESTful services mount based on the current content path. var uri = '<hst:link path="${hstRequest.requestContext.resolvedSiteMapItem.pathInfo}" mount="restapi"/>'; </script>
This URI can be used to invoke your JAX-RS component. In this example, the generated link targets the getProductResource() method.
If your JAX-RS component exposes additional methods with sub-paths, use the subPath attribute in the link tag. For example:
package org.hippoecm.hst.demo.jaxrs.services; @Path("/demosite:productdocument/") public class ProductContentResource extends AbstractContentResource { @GET @Path("/") public ProductRepresentation getProductResource( @Context HttpServletRequest servletRequest, @Context HttpServletResponse servletResponse) { // Implementation here return null; } @GET @Path("/body/") public HippoHtmlRepresentation getHippoHtmlRepresentation( @Context HttpServletRequest servletRequest, @Context HttpServletResponse servletResponse) { return super.getHippoHtmlRepresentation(servletRequest, null, null); } }
To create a link for the getHippoHtmlRepresentation() method, specify the sub-path:
<script language="javascript"> // Generate a URI for the RESTful services mount with the "/body/" sub-path. var uri = '<hst:link path="${hstRequest.requestContext.resolvedSiteMapItem.pathInfo}" mount="restapi" subPath="body/" />'; </script>
You can generate different links for each method in your JAX-RS component by specifying the appropriate subPath.
By default, the generated URI uses ./ as a separator between the content path and the sub-path, for example:
http://localhost:8080/site/restapi/products/opel.html./body/
The subPath value (body/) is separated from the main content path by ./. The link rewriting component uses this delimiter to distinguish between the content path and the sub-path. In this example, the container uses /products/opel.html to resolve the content node and body/ to build the sub-path for the RESTful service URL. The JAX-RS engine is then invoked with the resource path /demosite:productdocument/body/.
If you need to use a different separator, set the following property in /WEB-INF/hst-config.properties:
container.request.path.suffix.delimiter = ./
5. Using Matrix Parameters
Content/context-aware JAX-RS services support matrix parameters via the @MatrixParam annotation. Matrix parameters must be appended to the subPath to be effective.
Valid examples:
http://localhost:8080/site/restapi/products/open.html./body/content;p1=1http://localhost:8080/site/restapi/products/open.html./body/content;p1=1;p2=2http://localhost:8080/site/restapi/products/open.html./body/content;p1=1;p2=2;p3=3
In these cases, you can access the matrix parameters in your JAX-RS method using @MatrixParam("p1"), @MatrixParam("p2"), etc.
Invalid examples:
http://localhost:8080/site/restapi/products/open.html;p1=1./body/contenthttp://localhost:8080/site/restapi/products/open.html;p1=1;p2=2./body/content;p3=3
In these cases, matrix parameters in the page path (such as p1 and p2) are not available to your JAX-RS service. Only matrix parameters appended to the subPath (such as p3 in the second example) are accessible.
Limitation: The Apache CXF JAX-RS runtime used by XM does not support matrix parameters in multiple path segments. If you need to use multiple matrix parameters, append them to a single path segment, such as ./body/content;p1=1;p2=2. If you distribute matrix parameters across segments (e.g., ./body;p1=1/content;p2=2), CXF will not match your JAX-RS service.
6. Built-in JAX-RS Components
XM provides built-in JAX-RS components for system node types in the org.hippoecm.hst.jaxrs.services.content package.
| Primary node type | Component class | Description |
|---|---|---|
hippo:document | HippoDocumentContentResource | Default document type content resource provider |
hippostd:folder | HippoFolderContentResource | Default folder type content resource provider |
hippostd:directory | HippoDirectoryContentResource | Default directory type content resource provider |
hippostd:fixeddirectory | HippoFixedDirectoryContentResource | Default fixed directory type content resource |
hippofacnav:facetnavigation | HippoFacetNavigationContentResource | Default facet navigation content resource |
hippofacnav:facetsavailablenavigation | HippoFacetsAvailableNavigationContentResource | Default facet available navigation content |
hippofacnav:facetsubnavigation | HippoFacetSubNavigationContentResource | Default facet sub-navigation content resource |
hippogallery:imageset | ImageSetContentResource | Default image content resource provider |
You can extend org.hippoecm.hst.jaxrs.services.content.AbstractContentResource or org.hippoecm.hst.jaxrs.services.AbstractResource to implement your own JAX-RS components. These abstract classes provide utility methods for content retrieval and management. Refer to the built-in implementations for guidance.
7. Summary
Bloomreach Content supports development of content/context-aware JAX-RS components. You can register custom JAX-RS components for specific content node types by using the node type name as the root path annotation. Additional operations can be exposed using sub-paths, which are addressable via the subPath attribute in link tags.
Several system content node types are mapped to built-in JAX-RS components by default. Use these implementations and the provided abstract classes as references when developing your own components.