Example with Simple JSON REST API
Introduction
The following example ResourceResolver bean definition will give hints on how to configure conneciton information, RestTemplate object configuration, ResourceLinkResolver object configuration, cache control configuration, etc.
The following ResourceResolver Spring Framework Beans configuration can be set at /hippo:configuration/hippo:modules/crispregistry/hippo:moduleconfig/crisp:resourceresolvercontainer/demoProductCatalogs/@crisp:beandefinition property in the repository for "demoProductCatalogs" resource space, for instance.
ResourceResolver Configuration
Suppose you have a backend REST API having a URL pattern, http://localhost:8080/example-commerce/api/v1/products/*, to be able to retrieve product data in JSON format. You can simply configure a ResourceResolver with SimpleJacksonRestTemplateResourceResolver to pass the result JSON data as Resource object(s) to the application and its templates like the following example. For more details, please see the JavaDocs.
Bloomreach Experience Manager 16:
<?xml version="1.0" encoding="UTF-8"?> <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-4.1.xsd"> <bean parent="abstractCrispSimpleJacksonRestTemplateResourceResolver" class="org.onehippo.cms7.crisp.core.resource.jackson.SimpleJacksonRestTemplateResourceResolver"> <property name="cacheEnabled" value="${cache.enabled}" /> <property name="baseUri" value="${example.commerce.api.base.uri}" /> <property name="restTemplate"> <bean class="org.springframework.web.client.RestTemplate"> <property name="requestFactory" ref="org.springframework.http.client.ClientHttpRequestFactory" /> </bean> </property> <property name="resourceLinkResolver"> <bean class="org.onehippo.cms7.crisp.core.resource.FreemarkerTemplateResourceLinkResolver"> <property name="templateSource"> <value>http://www.example.com/products/${(preview == "true")?then("staging", "current")}/sku/${resource.valueMap['SKU']!"unknown"}/overview.html</value> </property> </bean> </property> <property name="resourceDataCache"> <bean class="org.onehippo.cms7.crisp.core.resource.SpringResourceDataCache"> <constructor-arg> <bean class="org.springframework.cache.caffeine.CaffeineCache" factory-bean="caffeineCacheInstanceFactory" factory-method="createSpringCacheInstance"> <constructor-arg value="demomarketoCache" /> <constructor-arg value="initialCapacity=10,maximumSize=1000,expireAfterWrite=100s,expireAfterAccess=100s" /> </bean> </constructor-arg> </bean> </property> </bean> </beans>
Bloomreach Experience Manager 14 & 15:
<?xml version="1.0" encoding="UTF-8"?> <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-4.1.xsd"> <bean parent="abstractCrispSimpleJacksonRestTemplateResourceResolver" class="org.onehippo.cms7.crisp.core.resource.jackson.SimpleJacksonRestTemplateResourceResolver"> <property name="cacheEnabled" value="${cache.enabled}" /> <property name="baseUri" value="${example.commerce.api.base.uri}" /> <property name="restTemplate"> <bean class="org.springframework.web.client.RestTemplate"> <property name="requestFactory" ref="org.springframework.http.client.ClientHttpRequestFactory" /> </bean> </property> <property name="resourceLinkResolver"> <bean class="org.onehippo.cms7.crisp.core.resource.FreemarkerTemplateResourceLinkResolver"> <property name="templateSource"> <value>http://www.example.com/products/${(preview == "true")?then("staging", "current")}/sku/${resource.valueMap['SKU']!"unknown"}/overview.html</value> </property> </bean> </property> <property name="resourceDataCache"> <bean class="org.onehippo.cms7.crisp.core.resource.SpringResourceDataCache"> <constructor-arg> <bean class="org.springframework.cache.ehcache.EhCacheCache"> <constructor-arg> <bean parent="abstractCrispResourceEhCache"> <property name="cacheName" value="demoProductCatalogsCache" /> <property name="maxEntriesLocalHeap" value="1000" /> <property name="maxEntriesLocalDisk" value="0" /> <property name="timeToLiveSeconds" value="60" /> <property name="timeToIdleSeconds" value="60" /> </bean> </constructor-arg> </bean> </constructor-arg> </bean> </property> </bean> </beans>
The following properties are used in the bean configuration through pairs of crisp:propnames and crisp:propvalues properties at /hippo:configuration/hippo:modules/crispregistry/hippo:moduleconfig/crisp:resourceresolvercontainer/demoProductCatalogs node for "demoProductCatalogs" resource space, for instance.
Property Name | Example Value |
---|---|
cache.enabled | true |
example.commerce.api.base.uri | http://localhost:8080/example-commerce/api/v1 |
- cacheEnabled property is to enable or disable caching in the ResourceResolver level.
- baseUri property is to set the base URI of the backend REST API. So, invocations on ResourceServiceBroker for this resource space will take a relative resource path to combine it with the base URI to invoke the backend service in the end.
- restTemplate property is to set a Spring Framework RestTemplate object. In this simple example, because we don't need any authentication against the backend REST API, it simply set an instance of org.springframework.web.client.RestTemplate. org.springframework.http.client.ClientHttpRequestFactory is the default requestFactory bean definition in CRISP module library.
- resourceLinkResolver is a property to set a custom ResourceLinkResolver component for this ResourceResolver. Because content or data from an external service is not something that we can generate URI links automatically unlike content documents, the URI links must be generated in a custom way if needed. You can add a custom ResourceLinkResolver in this property to generate a URI link for an external content or data item. For your convenience, CRISP module library has shipped with a generic Freemarker template based custom resource link resolver component, org.onehippo.cms7.crisp.core.resource.FreemarkerTemplateResourceLinkResolver, with which you can use templating technique to generate a URI string with a given resource object.
- Finally, resourceDataCache property specifies a ResourceResolver specific ResourceDataCache object. If this property is set and the specific resource is cacheable, the ResourceServiceBroker may cache resource specific data in the specified ResourceDataCache. If not set but the specific resource is still cacheable, ResourceServiceBroker may cache resource specific data in a globally-shared ResourceDataCache by default.
What If Only Basic Authentication Supported by Backend?
Suppose your REST service backend supports only Basic Authentication. How can you set up the Basic Authentication headers for the ResourceResolver? Spring Framework provides a built-in solution, org.springframework.http.client.support.BasicAuthorizationInterceptor, that you can configure in the restTemplate bean like the following:
<?xml version="1.0" encoding="UTF-8"?> <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-4.1.xsd"> <bean parent="abstractCrispSimpleJacksonRestTemplateResourceResolver" class="org.onehippo.cms7.crisp.core.resource.jackson.SimpleJacksonRestTemplateResourceResolver"> <!-- SNIP --> <property name="restTemplate"> <bean class="org.springframework.web.client.RestTemplate"> <!-- SNIP --> <!-- Set the interceptors property with BasicAuthorizationInterceptor to enable Basic Authentcation. --> <property name="interceptors"> <list> <bean class="org.springframework.http.client.support.BasicAuthorizationInterceptor"> <constructor-arg value="${basic.auth.username}" /> <constructor-arg value="${basic.auth.password}" /> </bean> </list> </property> </bean> </property> <!-- SNIP --> </bean> </beans>
The above configuration assumes that you defined two string properties, basic.auth.username and basic.auth.password through the pairs of crisp:propnames and crisp:propvalues properties at /hippo:configuration/hippo:modules/crispregistry/hippo:moduleconfig/crisp:resourceresolvercontainer/demoProductCatalogs node for "demoProductCatalogs" resource space, for instance.