HTTP endpoint database
HttpEndpointDatabase allows you to integrate with a third-party service that uses an HTTP API. A subclass of HttpEndpointDatabase can convert Data queries to HTTP API calls and return the results as if they were retrieved from the Dari underlying database. The search experience is the same for the end user, whether a query is on the underlying database or converted to an HTTP request to a third-party API.
HttpEndpointDatabase includes methods for extracting Dari query predicates and values for constructing HTTP API calls. It also includes methods that you can override to open and close connections to a third-party service, and to save objects to the underlying Dari database.
An HttpEndpointDatabase subclass must implement the doInitialize and readPartial methods inherited from the Dari AbstractDatabase and Database classes, respectively.
The following example shows a simple implementation of HttpEndpointDatabase that leverages the Getty REST Search API to retrieve images from that service. The GettyDatabase class gets the predicate and associated values from a Dari query, constructs an HTTP request that is sent to the Getty API, and returns the Getty response as a Dari PaginatedResult object.
1public class GettyDatabase extends HttpEndpointDatabase {23private static final Logger LOGGER = LoggerFactory.getLogger(GettyDatabase.class);4public static final String API_KEY_SUB_SETTING = "apiKey";5public static final String API_URL_SUB_SETTING = "apiUrl";6public static final String DEFAULT_API_URL = "https://api.gettyimages.com/v3";78private String apiUrl;9private String apiKey;1011public String getApiUrl() {12return apiUrl;13}1415public void setApiUrl(String apiUrl) {16this.apiUrl = apiUrl;17}1819public String getApiKey() {20return apiKey;21}2223public void setApiKey(String apiKey) {24this.apiKey = apiKey;25}2627@Override28protected void doInitialize(String settingsKey, Map<String, Object> settings) {29setApiUrl(ObjectUtils.to(String.class, settings.get(API_URL_SUB_SETTING)));30setApiKey(ObjectUtils.to(String.class, settings.get(API_KEY_SUB_SETTING)));31}3233@Override /* Must be implemented */34public <T> PaginatedResult<T> readPartial(Query<T> query, long offset, int limit) {3536String apiKey = getApiKey();37if (apiKey == null) {38return PaginatedResult.empty();39}4041try {42String apiUrl = ObjectUtils.firstNonBlank(getApiUrl(), DEFAULT_API_URL);43Predicate predicate = query.getPredicate();4445final String fields = "id,title,display_set";4647URL url = new URL(StringUtils.addQueryParameters(apiUrl + "/search/images",48"phrase", findQueryStringPredicateValue(predicate),49"fields", fields,50"page", offset + 1,51"page_size", limit));5253HttpClient httpClient = HttpClientBuilder.create().build();54HttpGet get = new HttpGet(url.toString());55get.addHeader("Api-Key", apiKey);56HttpResponse response = httpClient.execute(get);5758if (response == null) return PaginatedResult.empty();5960Map<String, Object> responseMap = (Map<String, Object>) ObjectUtils61.fromJson(EntityUtils.toString(response.getEntity()));62List<Object> images = ((List<Object>) responseMap.get("images"));6364if (images != null) {65List<Object> items = images.stream()66.map(image -> (Map<String, Object>) image)67.filter(Objects::nonNull)68.collect(Collectors.toList());6970return Optional.ofNullable((Long) responseMap.get("result_count"))71.map(count -> new PaginatedResult(offset, limit, count, items))72.orElse(new PaginatedResult(offset, limit, items));73}74else return PaginatedResult.empty();7576} catch (IOException error) {77LOGGER.error("Unable to perform Getty request!", error);78}79return PaginatedResult.empty();80}81}
- 4. Final variables that refer to the URL and security key for the Getty REST API. The API_URL_SUB_SETTING specifies the host for the API, and the API_KEY_SUB_SETTING specifies the security key issued by the service. These values are set in the client. A default host site is set on DEFAULT_API_URL in the event that the Getty API URL is not set in the client.
- 27. Implementation for the doInitialize method, which sets the Getty URL and security key. Instead of calling doInitialize, a client can set the Getty URL and security key using the public setter methods setApiUrl and setApiKey.
- 36. Gets the Getty security key.
- 42. Gets the URL for the Getty REST API.
- 43. Gets the predicate from the Dari query passed to the method.
- 45. Initializes a fields variable that specifies the data to be retrieved from the Getty service.
- 47. Creates a URL object to be passed in the HTTP request to the Getty service. The URL specifies the HTTP endpoint (/search/images) and the fields variable. Also included in the URL is phrase, the value of the Dari predicate. This value is retrieved with the HttpEndpointDatabase#findQueryStringPredicateValue method.
- 54. Creates HTTP-related objects and submits the request to the Getty service. JSON data returned from the service is set on response.
- 62. Creates a list of objects from the JSON image data.
- 65. Creates a list of objects to construct a PaginatedResult object returned by the method.
SourceDatabaseProvider implementation
Objects retrieved from a third-party service are represented as ExternalItem objects in Brightspot. External items are associated with a source database provider, which specifies the Database object that retrieves data from a third-party service.
For GettyDatabase that integrates with the Getty third-party service, the GettyDatabaseProvider is the source database provider. It provides the glue between the ExternalItem objects that represent retrieved Getty images and GettyDatabase. GettyDatabaseProvider implements SourceDatabaseProvider#get, which creates the GettyDatabase instance and sets the Getty API key on the instance. The key is retrieved from the Brightspot UI.
1public class GettyDatabaseProvider implements SourceDatabaseProvider {23@Override4public Database get(ObjectType type) {5GettyDatabase db = new GettyDatabase();6db.setEnvironment(Database.Static.getDefault().getEnvironment());7db.setApiKey(Application.Static.getInstance(CmsTool.class).as(GettySettings.class).getApiKey());8return db;9}10}