AEM Invoke API – How to use HTTP Client Factory

Problem Statement:

We have created an HTTP Client factory but how to execute requests and handle responses?

Requirement:

Show some examples to build the request and make a request to the external system and handle the response.

Introduction:

HTTP Client factory is an OSGi Service that creates an HTTP connection based on the external system based on the domain and connection configuration.

In order to use this service,

Build URI:

we need to build the key value map using NameValuePair and add these params to URIBuilder. Once the request is created

@Override
  public String buildURL(@NotNull String apiEndpointURI, boolean buildExternalLink,
    Map < String, String > parameterMap) throws MalformedURLException {
    if (MapUtils.isNotEmpty(parameterMap)) {
      URIBuilder builder = new URIBuilder();
      List < NameValuePair > nvpList = new ArrayList < > (parameterMap.size());
      parameterMap.entrySet().stream()
        .filter(entry -> StringUtils.isNoneBlank(entry.getKey(), entry.getValue()))
        .forEach(entry -> nvpList.add(new BasicNameValuePair(entry.getKey(), entry.getValue())));
      return returnApiEndpointURI(apiEndpointURI, buildExternalLink, builder, nvpList);
    }
    return returnApiEndpointURI(apiEndpointURI, buildExternalLink, null, null);
  }

  private String returnApiEndpointURI(String apiEndpointURI, boolean buildExternalLink,
    URIBuilder builder, List < NameValuePair > nvpList) {
    if (buildExternalLink) {
      return StringUtils.join(httpClientFactory.getApiStoreLocatorHostName(),
        httpClientFactory.getExternalURIType(), apiEndpointURI,
        null != builder ? builder.addParameters(nvpList).toString() : StringUtils.EMPTY);
    } else {
      return StringUtils.join(apiEndpointURI,
        null != builder ? builder.addParameters(nvpList).toString() : StringUtils.EMPTY);
    }
  }

Make a Request:

we can make use of request methods like POST

String responseString = httpClientFactory.getExecutor().execute(httpClientFactory.post(buildURL(apiEndPointURI, false, params)).addHeader("Content-Type", contentType)).handleResponse(HANDLER);

Response Handler:

Get the response and handle the request using StringObjectResponseHandler.

package com.mysite.core.http.impl;

import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.impl.client.BasicResponseHandler;

/**
 * Handling response using Basic response Handler
 */
public class StringObjectResponseHandler implements ResponseHandler < String > {

  private BasicResponseHandler handler = new BasicResponseHandler();

  @Override
  public String handleResponse(HttpResponse httpResponse) throws
  ClientProtocolException,
  IOException {
    String responseString = handler.handleResponse(httpResponse);
    HttpClientUtils.closeQuietly(httpResponse);
    return responseString;
  }
}

Complete file for implementation:

package com.mysite.core.services.impl;

import com.drew.lang.annotations.NotNull;
import com.mysite.core.http.impl.StringObjectResponseHandler;
import com.mysite.core.services.APIInvoker;
import com.mysite.core.services.HttpClientFactory;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.sling.api.servlets.HttpConstants;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Component(service = APIInvoker.class)
public class ExampleAPIInvoker implements APIInvoker {
  private static final Logger LOGGER = LoggerFactory.getLogger(ExampleAPIInvoker.class);
  private static final StringObjectResponseHandler HANDLER = new StringObjectResponseHandler();

  @Reference
  private HttpClientFactory httpClientFactory;

  @Override
  public String invokeAPI(String apiEndPointURI, String httpMethod, Map < String, String > params,
    String bodyText, String contentType) {
    try {
      if (StringUtils.isNotEmpty(bodyText)) {
        LOGGER.info("API Request Params {}", bodyText);
      } else {
        LOGGER.info("API Request Params {}", params);
      }
      if (StringUtils.equalsAnyIgnoreCase(httpMethod, HttpConstants.METHOD_POST) &&
        StringUtils.isEmpty(bodyText)) {
        String responseString =
          httpClientFactory.getExecutor().execute(httpClientFactory.post(buildURL(apiEndPointURI, false, params)).addHeader("Content-Type", contentType)).handleResponse(HANDLER);
        return responseString;
      }
    } catch (MalformedURLException exception) {
      LOGGER.debug("MalformedURLException while invoking API, {}", exception.getMessage());
    } catch (ClientProtocolException exception) {
      LOGGER.debug("ClientProtocolException while invoking API, {}", exception.getMessage());
    } catch (IOException exception) {
      LOGGER.debug("IOException while invoking API, {}", exception.getMessage());
    }
    return StringUtils.EMPTY;
  }

  @Override
  public String buildURL(@NotNull String apiEndpointURI, boolean buildExternalLink,
    Map < String, String > parameterMap) throws MalformedURLException {
    if (MapUtils.isNotEmpty(parameterMap)) {
      URIBuilder builder = new URIBuilder();
      List < NameValuePair > nvpList = new ArrayList < > (parameterMap.size());
      parameterMap.entrySet().stream()
        .filter(entry -> StringUtils.isNoneBlank(entry.getKey(), entry.getValue()))
        .forEach(entry -> nvpList.add(new BasicNameValuePair(entry.getKey(), entry.getValue())));
      return returnApiEndpointURI(apiEndpointURI, buildExternalLink, builder, nvpList);
    }
    return returnApiEndpointURI(apiEndpointURI, buildExternalLink, null, null);
  }

  private String returnApiEndpointURI(String apiEndpointURI, boolean buildExternalLink,
    URIBuilder builder, List < NameValuePair > nvpList) {
    if (buildExternalLink) {
      return StringUtils.join(httpClientFactory.getApiStoreLocatorHostName(),
        httpClientFactory.getExternalURIType(), apiEndpointURI,
        null != builder ? builder.addParameters(nvpList).toString() : StringUtils.EMPTY);
    } else {
      return StringUtils.join(apiEndpointURI,
        null != builder ? builder.addParameters(nvpList).toString() : StringUtils.EMPTY);
    }
  }
}

Create REST service using HTTP Client factory

Check this out URI

One thought on “AEM Invoke API – How to use HTTP Client Factory

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s