Example Using Generic (XML) Resource Objects
Introduction
Resource is the primary object representation to solve all the complex integration problems in a generic way. So, the interface was designed to support all the different domain object representations from heterogeneous backends easily by providing generic APIs to retrieve properties and child objects of domain objects.
One typical Resource implementation nowadays is probably in XML data format. CRISP provides a default implementation of Resource interface for XML data with JdomResource which uses JDOM library to parse XML data.
Single Resource Object from an XML Element
Let's see a simple XML data representing a product data from a backend system:
<product> <name>NEC MultiSync X431BT</name> <sku>4150349</sku> <description>MultiSync X431BT - 109.22 cm (43 ") , 1920 x 480, 16:4, 500 cd/m², 3000:1, 8 ms</description> <extendedData> <entry> <key>title</key> <value xsi:type="xs:string">NEC MultiSync X431BT</value> </entry> <entry> <key>type</key> <value xsi:type="xs:string">Link</value> </entry> <entry> <key>uri</key> <value xsi:type="xs:string">Incentro-HIC-Site/-/products/4150349</value> </entry> <entry> <key>description</key> <value xsi:type="xs:string">MultiSync X431BT - 109.22 cm (43 ") , 1920 x 480, 16:4, 500 cd/m², 3000:1, 8 ms</value> </entry> </extendedData> </product>
The example XML data shown above can be mapped to a Resource object. For more details,
- The top level XML Element is mapped to a Resource object.
- Attributes of an Element are treated as primitive properties of Resource object, as type of String.
- Child XML Element such as "name", "sku" and "extendedData" is treated as a child Resource object property.
- Both primitive properties and nested Resource object properties can be accessed through Resource#getValueMap().get(String name).
- JdomResource will return a String value or null for attributes, or child Resource object when invoked on Resource#getValueMap()#get(String name). However, when invoked on Resource#getValueMap()#get(String name, Class type), JdomResource will try to convert each value to a properly typed value (e.g, String, Number, Resource, etc.) based on the given type automatically.
- In addition, for convenience, JdomResource implements Resource#getDefaultValue() to return the text content String value of its underlying XML element object. The implementation of Resource#getDefaultValue(Class type) in JdomResource also tries to convert the default value to a properly typed value (e.g, String, Number, Resource, etc.) based on the given type automatically.
Suppose you retrieved single Resource object through ResourceServiceBroker#resolve(...) method. Then you can easily access the properties and nested child resoruces like the following example:
ResourceServiceBroker broker = CrispHstServices.getDefaultResourceServiceBroker(HstServices.getComponentManager()); Resource product = resourceServiceBroker.resolve("demoProductCatalogsXml", "/products.xml/sku/12345678901"); String name = (String) ((Resource) product.getValueMap().get("name")).getDefaultValue(); String sku = (String) ((Resource) product.getValueMap().get("sku")).getDefaultValue(); String description = (String) ((Resource) product.getValueMap().get("description")).getDefaultValue(); Resource extendedData = (Resource) product.getValueMap().get("extendedData"); // ...
JdomResource also allows to use standard XPath expression in Resource#getValue(String relPath) method implementation. So, you can simply use Resource#getValue(String relPath) by passing a relative XPath expression like the following example:
ResourceServiceBroker broker = CrispHstServices.getDefaultResourceServiceBroker(HstServices.getComponentManager()); Resource product = resourceServiceBroker.resolve("demoProductCatalogsXml", "/products/sku/12345678901"); // You can directly access "title" property of "extendedData" child resource object like this: String title = ((Resource) product.getValue("extendedData/entry[key='description']/value")).getDefaultValue(); // ...
Please see the JavaDoc of Resource for detail.
Multiple Resource Collection from an XML element
Let's see a simple XML data representing a collection of product data from a backend system:
<data> <products> <product> <name>NEC MultiSync X431BT</name> <sku>4150349</sku> <description>MultiSync X431BT - 109.22 cm (43 ") , 1920 x 480, 16:4, 500 cd/m², 3000:1, 8 ms</description> <extendedData> <entry> <key>title</key> <value xsi:type="xs:string">NEC MultiSync X431BT</value> </entry> <entry> <key>type</key> <value xsi:type="xs:string">Link</value> </entry> <entry> <key>uri</key> <value xsi:type="xs:string">Incentro-HIC-Site/-/products/4150349</value> </entry> <entry> <key>description</key> <value xsi:type="xs:string">MultiSync X431BT - 109.22 cm (43 ") , 1920 x 480, 16:4, 500 cd/m², 3000:1, 8 ms</value> </entry> </extendedData> </product> <product> <name>NEC PA271W</name> <sku>4696003</sku> <description>PA271W, 68.58 cm (27 ") LCD, 2560 x 1440, 6ms, 1000:1, 300cd/m2, 1.073B</description> <extendedData> <entry> <key>title</key> <value xsi:type="xs:string">NEC PA271W</value> </entry> <entry> <key>type</key> <value xsi:type="xs:string">Link</value> </entry> <entry> <key>uri</key> <value xsi:type="xs:string">Incentro-HIC-Site/-/products/4696003</value> </entry> <entry> <key>description</key> <value xsi:type="xs:string">PA271W, 68.58 cm (27 ") LCD, 2560 x 1440, 6ms, 1000:1, 300cd/m2, 1.073B</value> </entry> </extendedData> </product> <!-- SNIP --> </products> </data>
The example XML data shown above can be mapped to a Resource object as well. The Resource object represents the root XML element.
- Resource#getChildren() will return an iterable collection.
Suppose you retrieved a Resource object containing product collection data through ResourceServiceBroker#findResources(...) method. Then you can easily iterate resoruces like the following example:
ResourceServiceBroker broker = CrispHstServices.getDefaultResourceServiceBroker(HstServices.getComponentManager()); Resource data = resourceServiceBroker.findResources("demoProductCatalogsXml", "/products.xml"); Resource products = ((Resource) data.getValue("products")).getChildren(); for (Resource product : products.getChildren()) { String name = (String) ((Resource) product.getValueMap().get("name")).getDefaultValue(); String sku = (String) ((Resource) product.getValueMap().get("sku")).getDefaultValue(); String description = (String) ((Resource) product.getValueMap().get("description")).getDefaultValue(); // ... }
Pagination with Resource Object
Resource object supports paginating methods. For example, you can pass offset index and limit count of the paginated result on Resource#getChildren(long offset, long limit) like the following example to retrieve only specific set of the page:
// ... ResourceServiceBroker broker = CrispHstServices.getDefaultResourceServiceBroker(HstServices.getComponentManager()); Resource data = resourceServiceBroker.findResources("demoProductCatalogsXml", "/products.xml"); // The following will retrieve only the first page of the result when the page size is 10. for (Resource lead : ((Resource) data.getValue("products")).getChildren(0, 10)) { String name = (String) ((Resource) product.getValueMap().get("name")).getDefaultValue(); String sku = (String) ((Resource) product.getValueMap().get("sku")).getDefaultValue(); String description = (String) ((Resource) product.getValueMap().get("description")).getDefaultValue(); // ... }
Please see the JavaDoc of Resource interface for detail.