Movatterモバイル変換


[0]ホーム

URL:


BloomreachBloomreach
Hippo CMS

Bloomreach Documentation version

Bloomreach.com

Getting Started

Introduction

From application's perspective, the main entry point to useCRISP services isResourceServiceBroker. You should always retrieve content or data via ResourceServiceBroker which always returns aResource instance as a result.

Finding Resources from Simple JSON API Backend

Suppose you have a simple REST API athttp://localhost:8080/example-commerce/api/v1/products/ which returns product data like the following example in JSON array:

[  {    "SKU": "12345678901",    "description": "MultiSync X123BT - 109.22 cm (43 \") , 1920 x 480, 16:4, 500 cd\/m\u00b2, 3000:1, 8 ms",    "name": "CBA MultiSync X123BT",    "extendedData": {      "title": "CBA MultiSync X123BT",      "type": "Link",      "uri": "Awesome-HIC-Site\/-\/products\/12345678901",      "description": "MultiSync X123BT - 109.22 cm (43 \") , 1920 x 480, 16:4, 500 cd\/m\u00b2, 3000:1, 8 ms"    }  },  {    "SKU": "12345678902",    "description": "PA123W, 68.58 cm (27 \") LCD, 2560 x 1440, 6ms, 1000:1, 300cd\/m2, 1.073B",    "name": "CBA PA123W",    "extendedData": {      "title": "CBA PA123W",      "type": "Link",      "uri": "Awesome-HIC-Site\/-\/products\/12345678902",      "description": "PA123W, 68.58 cm (27 \") LCD, 2560 x 1440, 6ms, 1000:1, 300cd\/m2, 1.073B"    }  },  //...]

You can configure the baseUri property tohttp://localhost:8080/example-commerce/api/v1 inResourceResolver component configuration (seeExample with Simple JSON REST API as a reference). Then you can use "/products/" as a resource relative path when invoking ResourceServiceBroker like the following example:

ResourceServiceBroker broker = CrispHstServices.getDefaultResourceServiceBroker(HstServices.getComponentManager());Resource productCatalogs = broker.findResources("demoProductCatalogs", "/products/");request.setAttribute("productCatalogs", productCatalogs);

Get a reference to the singletonResourceServiceBroker by using CrispHstServices.getDefaultResourceServiceBroker(HstServices.getComponentManager()).

After that, you can get content or data from an external backend by passing itsresource space name, "demoProductCatalogs" in this example (seeExample with Simple JSON REST API as a reference) and a relative resource path, "/products/" in this example.

The ResourceServiceBroker may invoke the backend REST service or it may retrieve a cached resource data for the caller. Anyway, it always returns a Resource object that allows to retrieve all the properties and traverse child Resource objects and properties very easily.

In the example code shown above, it sets the returned Resource object to "productCatalog" request attribute. So, that attribute can be accessed in a template (in Freemarker, JSP, etc) through the variable name, "productCatalog".

For example, the following example shows how you can retrieve properties and child resources in Freemarker templates:

<#assign crisp=JspTaglibs ["http://www.onehippo.org/jsp/hippo/crisp/tags"]><#-- SNIP --><#if productCatalogs?? && productCatalogs.anyChildContained>  <article>    <h3>Related Products</h3>    <ul>      <#list productCatalogs.children.collection as product>        <#assign extendedData=product.valueMap['extendedData'] />        <li>          <@crisp.link var="productLink" resourceSpace='demoProductCatalogs' resource=product>            <@crisp.variable name="preview" value="${hstRequestContext.preview?then('true', 'false')}" />            <@crisp.variable name="name" value="${product.valueMap['name']}" />          </@crisp.link>          <a href="${productLink}">            [${product.valueMap['SKU']!}] ${extendedData.valueMap['title']!}          </a>          (${product.getValue('extendedData/description')!})        </li>      </#list>    </ul>  </article></#if>
  • You can check if there's any child Resource objects throughResource#isAnyChildContained() Java method orresource.anyChildContainer in an evaluation expression in templates.
  • Resource#getChildren()#getCollection() returns a read-onlyjava.util.Collection object to be able to easily iterate child items in Freemarker templates.
  • Resource#getValueMap() returns aValueMap object (extension ofjava.util.Map interface) through which you can access all the properties or child resource objects very easily.
  • Also,Resource#getValue(String relPath) method supports a relative property path for convenience. For example, if a "product" resource object (backed by a JSON object) contains a child JSON object ("extendedData"), then you can access "description" property of "extendedData" resource object directly throughResource#getValue("extendedData/description") which is equivalent to((Resource) Resource#getValueMap().get("extendedData")).getValueMap().get("description").
  • In the example shown above,<@crisp.link />(or<crisp:link /> in JSP) tab library used to generate a URI link for the specificResource object. The link generation topic is discussed in the next section.

 

Custom Link Generation for Resources

In the previous example, the followingCRISP link tag library is used:

<@crisp.link var="productLink" resourceSpace='demoProductCatalogs' resource=product>  <@crisp.variable name="preview" value="${hstRequestContext.preview?then('true', 'false')}" />  <@crisp.variable name="name" value="${product.valueMap['name']}" /></@crisp.link>

Basically, a link for a Resource cannot be generated without a configured customResourceLinkResolver component in a ResourceResolver component. Please seeExample with Simple JSON REST API for an example configuration with a custom ResourceLinkResolver.

Anyway, the idea is that if you use<@crisp.link /> (or<crisp:link /> in JSP) tag library in a template with specifyingresource space name,resource bean, then the tag library will invokeResourceServiceBroker to invoke the underlyingResourceLinkResolver for the specificResourceResolver component specified by theresource space name to create a URI link for the template. So, the underlying customResourceLinkResolver will ge given aresource space name anda Resource object to generate a URI link.

However, sometimes it might not be enough only with those, but it may require more "variables" to determine a right URI link for the Resource object. For that reason,<@crisp.link /> (or<crisp:link /> in JSP) tag library supports embedding<@crisp.variable /> (or<crisp:variable /> in JSP) tags to pass more variables to use in URI link generation process.

For example, you will be able to find the following Freemarker templating based customResourceLinkResolver configuration inExample with Simple JSON REST API:

<bean>  <property name="templateSource">    <value>http://www.example.com/products/${(preview == "true")?then("staging", "current")}/sku/${resource.valueMap['SKU']!"unknown"}/overview.html</value>  </property></bean>

The template may use two variables, "preview" and "name", passed by the<@crisp.variable /> (or<crisp:variable /> in JSP) tags inside<@crisp.link /> (or<crisp:link /> in JSP) tag in its expressions. But in this specific example, it used "preview" variable only for demonstration purpose.

Finding Resources with Path Variables to Expand Resource Relative Path

It was discussed that we can findResource objects onResourceServiceBroker by passing a logicalresource space name and arelative resource path in the previous sections. However, sometimes, you might want to change therelative resource path dynamically based on some runtime variables because the backend REST API URL could vary in situations. For that reason,ResourceServiceBroker supportsPath Variables on invocations, too. See the following example:

ResourceServiceBroker broker = CrispHstServices.getDefaultResourceServiceBroker(HstServices.getComponentManager());final Map<String, Object> pathVars = new HashMap<>();// Note: Just as an example, let's try to find all the data by passing empty query string.pathVars.put("fullTextSearchTerm", "");Resource productCatalogs = resourceServiceBroker.findResources(RESOURCE_SPACE_DEMO_PRODUCT_CATALOG,        "/products/?q={fullTextSearchTerm}", pathVars);request.setAttribute("productCatalogs", productCatalogs);

In this example, it is assumed that the relative resource path cannot be statically determined every time, but could be determined at runtime based on some variables. e.g, "/products/q=hippo" where "hippo" can be determined at runtime by variables.

In this case, you can pass variables map on ResourceServiceBroker#findResources(String resourceSpace, String baseAbsPath, Map pathVariables) operation.

The resource relative path parameter will be expanded using the given path variables (pathVars), if there's any. For example, ifpathVars looks like{"var1":"hello","var2":"world"} and the resource relative path parameter is ".../some/path/{var1}/{var2}/overview", then it is expanded to ".../some/path/hello/world/overview" when making a real request to the backend.

Resolving Single Resource

Resolving single resource is similar to finding multiple resources fromResourceServiceBroker. You can simply replace the operation by "resolveResource(...)" and expect the resultResource object represents the single resource directly.

Supposehttp://localhost:8080/example-commerce/api/v1/products/sku/12345678901 returns the following JSON data:

{  "SKU": "12345678901",  "description": "MultiSync X123BT - 109.22 cm (43 \") , 1920 x 480, 16:4, 500 cd\/m\u00b2, 3000:1, 8 ms",  "name": "CBA MultiSync X123BT",  "extendedData": {    "title": "CBA MultiSync X123BT",    "type": "Link",    "uri": "Awesome-HIC-Site\/-\/products\/12345678901",    "description": "MultiSync X123BT - 109.22 cm (43 \") , 1920 x 480, 16:4, 500 cd\/m\u00b2, 3000:1, 8 ms"  }}

Then the following code will return a product resource representation backed by the JSON data.

ResourceServiceBroker broker = CrispHstServices.getDefaultResourceServiceBroker(HstServices.getComponentManager());Resource product = resourceServiceBroker.resolve("demoProductCatalogs", "/products/sku/12345678901");assert "CBA MultiSync X123BT".equals(product.getValueMap().get("name"));

You can also expand the resource relative path by variables, too.

ResourceServiceBroker broker = CrispHstServices.getDefaultResourceServiceBroker(HstServices.getComponentManager());final Map<String, Object> pathVars = new HashMap<>();pathVars.put("sku", "12345678901");Resource product = resourceServiceBroker.resolve("demoProductCatalogs", "/products/sku/{sku}", pathVars);assert "CBA MultiSync X123BT".equals(product.getValueMap().get("name"));

Using HTTP POST Method

Sometimes the target backend system allows only HTTPPOST method instead of HTTPGET method (the default option) when resolving resources or binaries in their REST API implementations. Just as an example,ElasticSearch Search APIs provides HTTPPOST based API for a richer query capability.

As HTTP GET method is used in CRISP API by default, you should give amessage exchange hint (of org.onehippo.cms7.crisp.api.exchange.ExchangeHint type) to switch the HTTP method toPOST in that case. In each resource or binary resolving operations ofResourceServiceBroker, you can provide an additionalExchangeHint argument which should be created by usingorg.onehippo.cms7.crisp.api.exchange.ExchangeHintBuilder.

Resource resolution methods such as #findResources(...) and#resolve(...) support only eitherGET (the default method) orPOST method since resource resolutions are semantically consistent withGET method or practically applicable withPOST method for many backends in reality nowadays.
If you want to use other HTTP methods such asPUT orDELETE for your Web/REST Services backends for some reason, please consider using#resolveBinary(...) method instead, which is explained in the next section.

The following example shows how you can suggest using HTTPPOST method in message exchange, and it also shows how you can add or set custom HTTP request headers and/or request body in the request.

// You can build an ExchangeHint using ExchangeHintBuilder to change the HTTP method to POST with the request headers and request body.Resource products = resourceServiceBroker.findResources("demoProductCatalogs", "/products/",        ExchangeHintBuilder.create()                .methodName("POST")                .requestHeader("Content-Type", "application/json;charset=UTF-8")                .requestBody("{ \"filterFieldName\": ... }")                .build());
If you want to set aUTF-8 encoded (JSON) string for therequestBody, please make sure you pass ajava.lang.String object in.requestBody(...) call. Otherwise, the SpringRestTemplate might not be able to convert it (a non-String object such as Jackson'sJsonNode object) properly. SpringRestTemplate internally uses an org.springframework.http.converter.StringHttpMessageConverter object which reads theContent-Type request header (e.g, "application/json;charset=UTF-8") to find a proper character set to parse the request body. ISO-8859-1, by default ifcharset is not provided in the header value. Therefore, if you pass a non-String object (such as JacksonJsonNode object) in.requestBody(...) call, it will be converted by something else (such as org.springframework.http.converter.json.MappingJackson2HttpMessageConverter) other than org.springframework.http.converter.StringHttpMessageConverter object, which can lead to a failure in parsing the request body mesage.

Resolving Single Binary

If the target backend resource data is not representing aResource but representing just (downloadable) ad hoc (binary) data, you can resolve the target data to aorg.onehippo.cms7.crisp.api.resource.Binary object instead. Suppose you configured aResourceResolver for a DAM (Digital Asset Management) system, and you want to download binary resource data such as images or PDF files from it. In this case, you can useResourceServiceBroker#resolveBinary(String resourceSpace, String absPath, ...) which returns a org.onehippo.cms7.crisp.api.resource.Binary object if resolved, like the following example:

// Suppose you get the ID of the asset to download from a Resource already.String assetId = "1234567890";Binary binary = null;InputStream is = null;BufferedInputStream bis = null;try {    final ResourceServiceBroker broker = CrispHstServices.getDefaultResourceServiceBroker(HstServices.getComponentManager());    final Map<String, Object> pathVars = new HashMap<>();    pathVars.put("assetId", assetId);    // Suppose you configured a ResourceResolver for a WebDAM REST API backend system.    // It is to download the binary asset data from WebDAM REST API by appending the downloadable asset path.    binary = broker.resolveBinary("webdamImages", "/assets/{assetId}/download", pathVars);    // You can read the binary and do something as you need...    is = binary.getInputStream();    bis = new BufferedInputStream(is);    // Do somethingn with the input stream on the binary data...} finally {    IOUtils.closeQuietly(bis);    IOUtils.closeQuietly(is);    // NOTE: Make sure to invoke Binary#dispose() to clean up any temporary file or streams assocated with the binary.    if (binary != null) {        binary.dispose();    }}

Please make sure to invokeBinary#dispose() after use to clean up any temporary file or streams associated with the binary object. It depends onResourceResolver andBinary implementations, but it is always necessary to invoke the Binary#dispose() method after use for safety, to not keep garbage. The defaultBinary implementation stores the binary data into a temporary file under the hood, so it can have a chance to delete the temporary file when#dispose() method is invoked.

Any resolvedBinary objects arenot cached in any circumstances unlikeResource objects. So, any caching related configuration wouldn't affectBinary content.

You can also provide an additionalExchangeHint argument which should be created by usingorg.onehippo.cms7.crisp.api.exchange.ExchangeHintBuilder to use a different HTTP method or set any custom request headers. The following example shows how you can suggest using HTTPPOST method in message exchange.

// You can build an ExchangeHint using ExchangeHintBuilder to change the HTTP method to POST with the request headers and request body.binary = broker.resolveBinary("demoProductCatalogs", "/products/",        ExchangeHintBuilder.create()                .methodName("POST")                .requestBody("{ \"filterFieldName\": ... }")                .build());// ...
In v2.2.1 or higher versions, unlike the resource resolution methods such as #findResources(...) and#resolve(...), you can use any other HTTP methods such as POST,PUT orDELETE as well when using #resolveBinary(...) method.

 

Did you find this page helpful?
How could this documentation serve you better?
Cheers!
On this page
    Did you find this page helpful?
    How could this documentation serve you better?
    Cheers!

    [8]ページ先頭

    ©2009-2025 Movatter.jp