Learning to use Cortex Java SDK
Learning to use Cortex Java SDK
Cortex Java SDK can consume Cortex resources in client applications that are built with Java.
Setup
Cortex Java SDK is available from the Elastic Path Public Maven Repository.
<dependency> <groupId>com.elasticpath.rest</groupId> <artifactId>cortex-jaxrs-client</artifactId> <version>2.0.0</version> </dependency>
Usage
Cortex Java SDK is based on the JAX-RS Java API and includes a set of extensions to facilitate development with Cortex. The SDK provides both a straight JAX-RS Client service as well as a user-scoped Cortex client that scopes Cortex calls to a specific user.
JAX-RS Client
The JAX-RS Client can call any REST service, not just Cortex. The client is injected via an OSGi SCR annotation:
@Reference javax.ws.rs.client.Client jaxrsClient;
JAX-RS Client Configuration
To configure the JAX-RS client instance, edit its settings through the OSGi admin console. Additionally, you can add and remove ClientConfigurator services through the admin console.
Name | Details |
---|---|
apache-connector | Configures the JAX-RS client to use the Apache HttpClient Connector. If this configuration is removed, JAX-RS will fall back to using Java's default HttpURLConnection. |
jackson | Supplies a Jackson ObjectMapper for JAX-RS to use for JSON marshalling. |
json-unmarshaller | Instructs JAX-RS to utilize Elastic Path's JSON Unmarshaller to map JSON data into data objects. |
CortexClient
- A user-scoped wrapper around the JAX-RS client to facilitate REST calls to Cortex
- JSON Unmarhsaller types to marshall/unmarshal JSONs
Client instances should not be stored between requests.
Using Cortex Client in an OSGi Environment
@Reference com.elasticpath.rest.client.CortexClientFactory clientFactory; ... MultivaluedMap<String, Object> headers = new MultivaluedHashMap<String, Object>(); headers.putSingle(HeaderKeys.X_EP_USER_ID_KEY, "customerId"); headers.putSingle(HeaderKeys.X_EP_USER_ROLES_KEY, "PUBLIC"); headers.putSingle(HeaderKeys.AUTHORIZATION_KEY, "authToken"); com.elasticpath.rest.client.CortexClient client = clientFactory.create(headers, scope);
Using Cortex Client in an Non-OSGi Environment
<?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.0.xsd"> <bean id="jacksonObjectMapper" class="com.elasticpath.example.ApplicationObjectMapper" init-method="init"/commerce-legacy/> <!-- Note that this is a custom com.fasterxml.jacson.databind.ObjectMapper extension which disables the FAIL_ON_UNKNOWN_PROPERTIES on initialization. this.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) --> <bean id="jsonUnmarshaller" class="com.fasterxml.jackson.contrib.jsonpath.DefaultJsonUnmarshaller"/commerce-legacy/> <bean id="zoomModelIntrospector" class="com.elasticpath.rest.client.urlbuilding.zoom.ZoomModelIntrospector"/commerce-legacy/> <bean id="zoomQueryFactory" class="com.elasticpath.rest.client.urlbuilding.zoom.ZoomQueryFactory"/commerce-legacy/> <bean id="cortexUrlFactoryImpl" class="com.elasticpath.rest.client.urlbuilding.impl.CortexUrlFactoryImpl"> <constructor-arg ref="zoomModelIntrospector"/commerce-legacy/> <constructor-arg ref="zoomQueryFactory"/commerce-legacy/> </bean> <bean id="jacksonProvider" class="com.elasticpath.rest.client.unmarshalling.JacksonProvider" > <constructor-arg ref="jacksonObjectMapper"/commerce-legacy/> </bean> <bean id="jsonUnmarshallReaderInterceptor" class="com.elasticpath.rest.client.unmarshalling.JsonUnmarshallReaderInterceptor"> <constructor-arg ref="jsonUnmarshaller"/commerce-legacy/> </bean> </beans>
... public CortexClientFactory exampleCortexClientFactorySetup(final ApplicationContext context) { ClientConfig clientConfig = new ClientConfig(); clientConfig.register(new WebApplicationExceptionMapper()) .register(jacksonProvider) .register(jsonUnmarshallReaderInterceptor) .register(new LoggingFilter(Logger.getLogger(App.class.getName()), true)) // Should be configurable at runtime .property(ClientProperties.CONNECT_TIMEOUT, CONNECT_TIMEOUT) // Should be configurable at runtime .property(ClientProperties.READ_TIMEOUT, READ_TIMEOUT); // Should be configurable at runtime //Real implementation will want to pass configurable values to this builder. HttpClientConfigurator httpClientConfigurator = new HttpClientConfiguratorBuilder().build(); httpClientConfigurator.configure(clientConfig); Client jaxRsClient = ClientBuilder.newClient(clientConfig); CortexUrlFactory cortexUrlFactory = (CortexUrlFactory) context.getBean("cortexUrlFactoryImpl"); //Cortex url should be configurable at runtime. return new CortexClientFactoryImpl(cortexUrlFactory, jaxRsClient, "http://localhost:9080/cortex/"); }
Constructing URIs
Cortex Java SDK provides four class level annotations to construct Cortex resource URLs:
- @Zoom: Adds a Zoom query parameter to the request URL.
- @Path: Used together with @Zoom, @Path specifies the relation/link to follow from the Zoom request.
- @FollowLocation: Adds a FollowLocation query parameter to the request URL.
Example: Zoom and FollowLocation
A class that models the expected response should be annotated as follows:
@Zoom(@Path("order")) @FollowLocation public class Cart {}
baseUrl = "http://localhost:9080/cortex/" path = "carts/mobee/default" result = cortexUrlFactory.addQueryParametersToResourceUrl(baseUrl, path, Cart.class) //result = "http://localhost:9080/cortex/carts/mobee/default?zoom=order&followLocation=true"
Example: Without Query Parameters
baseUrl = "http://localhost:9080/cortex/" path = "carts/mobee/default" result = cortexUrlFactory.createResourceUrl(baseUrl, path) //result = "http://localhost:9080/cortex/carts/mobee/default"
Example: With Entry Point Resource
A class that models the expected response should be annotated as follows:
@EntryPointUri(“carts/{scope}/default”) @Zoom(@Path("lineitems")) @FollowLocation public class Carts {}
baseUrl = “http://localhost:9080/cortex/” store = “mobee” result = cortexUrlFactory.createResourceUrlFromAnnotations(baseUrl, store, Carts.class) //result = "http://localhost:9080/cortex/carts/mobee/default?zoom=lineitems&followLocation=true"
Unmarshalling Cortex Responses
Cortex Java SDK unmarshalling is provided by the Elastic Path JSON Unmarshaller, an open source project. This section shows some simple examples of how to use the JSON Unmarshaller. For more complex unmarhalling examples, see the JSON Unmarshaller project page.
Cortex Java SDK provides two annotations to extract data from a Cortex response:
- @JsonProperty: Extracts a JSON property from a Cortex response.
-
@JsonPath: Uses JSONPath to extract either a single or multiple JSON properties from a Cortex response. This annotation is useful to extract nested JSON properties.Tip: JSONPath Expression Tester
Cortex Studio comes bundled with a JSONPath tester for creating and testing JSONPath expressions.
{ "self": { "type": "elasticpath.carts.cart", "uri": "/commerce-legacy/carts/mobee/gwu=?zoom=lineitems:element", "href": "http://api.demo.elasticpath.com/cortex/carts/mobee/gwu=?zoom=lineitems:element" }, "total-quantity": 1, "_lineitems": [ { "_element": [ { "self": { "type": "elasticpath.carts.line-item", "uri": "/commerce-legacy/carts/mobee/gwu=/lineitems/gq4=", "href": "http://api.demo.elasticpath.com/cortex/carts/mobee/gwu=/lineitems/gq4=" }, "links": [ { "rel": "list", "type": "elasticpath.collections.links", "uri": "/commerce-legacy/carts/mobee/gwu=/lineitems", "href": "http://api.demo.elasticpath.com/cortex/carts/mobee/gwu=/lineitems" } ], "quantity": 1 } ] } ], "links": [ { "rel": "lineitems", "rev": "cart", "type": "elasticpath.collections.links", "uri": "/commerce-legacy/carts/mobee/gwu=/lineitems", "href": "http://api.demo.elasticpath.com/cortex/carts/mobee/gwu=/lineitems" }, { "rel": "order", "rev": "cart", "type": "elasticpath.orders.order", "uri": "/commerce-legacy/orders/mobee/hbr=", "href": "http://api.demo.elasticpath.com/cortex/orders/mobee/hbr=" }, { "rel": "total", "rev": "cart", "type": "elasticpath.totals.total", "uri": "/commerce-legacy/totals/carts/mobee/gwu=", "href": "http://api.demo.elasticpath.com/cortex/totals/carts/mobee/gwu=" } ] }
Example: Extract JSON Property using @JsonProperty
public class Cart {) @JsonProperty("total-quantity") private String totalQuantity; }
Example: Extract Nested JSON Properties using @JsonPath
public class Cart { //Non-nested JSON property @JsonPath("$.total-quantity") private int totalQuantity; //Nested Property @JsonPath("$._lineitems[0]._element[0].quantity") private int quantity; //Nested Array @JsonPath("$._lineitems[0]._element") private List<LineItem> lineItems; }