Getting Started

Overview

The primary entry point for using CRISP services in your application is the ResourceServiceBroker. Always use the ResourceServiceBroker to retrieve content or data. This broker consistently returns a Resource instance.

Accessing Resources from a Simple JSON API Backend

Assume you have a REST API at http://localhost:8080/example-commerce/api/v1/products/ that returns product data as a 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" } }, //... ]

Configure the baseUri property to http://localhost:8080/example-commerce/api/v1 in your ResourceResolver component. For reference, see Example with Simple JSON REST API. Use /products/ as the resource relative path when calling the ResourceServiceBroker:

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

Obtain the singleton ResourceServiceBroker using CrispHstServices.getDefaultResourceServiceBroker(HstServices.getComponentManager()).

To retrieve content from an external backend, provide the resource space name (for example, "demoProductCatalogs") and a relative resource path (such as /products/). The ResourceServiceBroker may call the backend REST service or return cached resource data, but always returns a Resource object. This object allows you to access properties and traverse child resources.

In the example above, the returned Resource object is set as the productCatalogs request attribute. You can access this attribute in templates (such as Freemarker or JSP) using the variable name productCatalogs.

The following Freemarker example demonstrates how to access properties and child resources:

<#assign crisp=JspTaglibs ["http://www.onehippo.org/jsp/hippo/crisp/tags"]> <#-- SNIP --> <#if productCatalogs?? && productCatalogs.anyChildContained> <article class="has-edit-button"> <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>

Key points:

  • Use Resource#isAnyChildContained() in Java or resource.anyChildContained in templates to check for child resources.
  • Resource#getChildren().getCollection() returns a read-only java.util.Collection for iterating child items in Freemarker.
  • Resource#getValueMap() provides a ValueMap (an extension of java.util.Map) to access properties or child resources.
  • Resource#getValue(String relPath) supports relative property paths. For example, to access the "description" property of the "extendedData" child object, use Resource#getValue("extendedData/description").
  • The <@crisp.link /> (or <crisp:link /> in JSP) tag generates a URI link for a specific Resource object. Link generation is covered in the next section.

The previous example uses the CRISP link tag library:

<@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 link for a Resource cannot be generated unless you configure a custom ResourceLinkResolver component in your ResourceResolver. See Example with Simple JSON REST API for a sample configuration.

When you use <@crisp.link /> (or <crisp:link /> in JSP) in a template and specify the resource space and resource bean, the tag library calls the ResourceServiceBroker. This broker invokes the configured ResourceLinkResolver for the specified resource space to generate a URI link.

If additional variables are required to determine the correct URI, you can pass them using <@crisp.variable /> (or <crisp:variable /> in JSP) tags inside <@crisp.link />.

For example, a Freemarker-based custom ResourceLinkResolver configuration might look like:

<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>

The template can use variables such as "preview" and "name" passed by <@crisp.variable />. In this example, only "preview" is used for demonstration.

Using Path Variables to Expand Resource Relative Paths

You can dynamically construct the relative resource path by using path variables with the ResourceServiceBroker. This is useful when the backend REST API URL depends on runtime values.

ResourceServiceBroker broker = CrispHstServices.getDefaultResourceServiceBroker(HstServices.getComponentManager()); final Map<String, Object> pathVars = new HashMap<>(); // Example: Find all data with an 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, the relative resource path is determined at runtime using variables. For instance, /products/q=hippo can be generated by providing the variable "hippo".

Pass a map of variables to ResourceServiceBroker#findResources(String resourceSpace, String baseAbsPath, Map pathVariables). The resource relative path will be expanded using the provided variables. For example, if pathVars is {"var1":"hello","var2":"world"} and the path is .../some/path/{var1}/{var2}/overview, the expanded path is .../some/path/hello/world/overview.

Resolving a Single Resource

To resolve a single resource, use the resolveResource(...) method. The returned Resource object represents the single resource.

Suppose http://localhost:8080/example-commerce/api/v1/products/sku/12345678901 returns:

{ "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" } }

The following code retrieves the product resource:

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 use path variables to expand the resource path:

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 the HTTP POST Method

Some backend systems require HTTP POST instead of the default GET method for resource or binary resolution. For example, ElasticSearch Search APIs use POST for advanced queries.

To use POST, provide an exchange hint (org.onehippo.cms7.crisp.api.exchange.ExchangeHint) to the ResourceServiceBroker. Use ExchangeHintBuilder to construct the hint.

Note: The #findResources(...) and #resolve(...) methods support only GET (default) and POST. If you need to use PUT or DELETE, use #resolveBinary(...) as described in the next section.

The following example demonstrates how to specify POST and set custom headers and request body:

// Build an ExchangeHint to use POST with custom headers and body. Resource products = resourceServiceBroker.findResources("demoProductCatalogs", "/products/", ExchangeHintBuilder.create() .methodName("POST") .requestHeader("Content-Type", "application/json;charset=UTF-8") .requestBody("{ \"filterFieldName\": ... }") .build());

When setting a UTF-8 encoded JSON string as the request body, ensure you pass a String to .requestBody(...). If you pass a non-String object (such as a Jackson JsonNode), Spring's RestTemplate may not convert it as expected. The StringHttpMessageConverter uses the Content-Type header to determine the character set (defaulting to ISO-8859-1 if not specified). Passing a non-String object may result in a different converter being used, which can cause parsing failures.

Resolving a Single Binary

If the backend provides binary data (such as images or PDFs) instead of a Resource, use ResourceServiceBroker#resolveBinary(String resourceSpace, String absPath, ...) to retrieve a org.onehippo.cms7.crisp.api.resource.Binary object.

For example, to download a binary asset from a DAM system:

// Assume assetId is obtained from a Resource. 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); // Download the binary asset from the backend. binary = broker.resolveBinary("webdamImages", "/assets/{assetId}/download", pathVars); // Process the input stream as needed. is = binary.getInputStream(); bis = new BufferedInputStream(is); // Implement your logic for handling the binary data. } finally { IOUtils.closeQuietly(bis); IOUtils.closeQuietly(is); // Always call dispose() to release resources associated with the binary. if (binary != null) { binary.dispose(); } }

Always call Binary#dispose() after use to release temporary files or streams. The default implementation stores binary data in a temporary file, which is deleted when dispose() is called.

Unlike Resource objects, Binary objects are never cached. Caching settings do not affect binary content.

You can also provide an ExchangeHint to use a different HTTP method or set custom headers. The following example shows how to use POST for binary resolution:

// Build an ExchangeHint to use POST with a request body. binary = broker.resolveBinary("demoProductCatalogs", "/products/", ExchangeHintBuilder.create() .methodName("POST") .requestBody("{ \"filterFieldName\": ... }") .build()); // ...

Note: In version 2.2.1 and higher, #resolveBinary(...) supports all HTTP methods, including POST, PUT, and DELETE. In contrast, #findResources(...) and #resolve(...) support only GET and POST.

Share Feedback
Page: /build/crisp-api/introduction-config/getting-started
Section: Build
Category *
Getting Started | Bloomreach Content Documentation