All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.target.edge.client.service.DefaultTargetService Maven / Gradle / Ivy

There is a newer version: 2.6.1
Show newest version
/*
 * Copyright 2021 Adobe. All rights reserved.
 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. You may obtain a copy
 * of the License at http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under
 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
 * OF ANY KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package com.adobe.target.edge.client.service;

import static com.adobe.target.edge.client.ondevice.OnDeviceDecisioningService.TIMING_EXECUTE_REQUEST;
import static org.apache.http.HttpStatus.SC_OK;

import com.adobe.target.delivery.v1.model.DeliveryResponse;
import com.adobe.target.delivery.v1.model.Geo;
import com.adobe.target.delivery.v1.model.Telemetry;
import com.adobe.target.edge.client.ClientConfig;
import com.adobe.target.edge.client.http.DefaultTargetHttpClient;
import com.adobe.target.edge.client.http.ResponseStatus;
import com.adobe.target.edge.client.http.ResponseWrapper;
import com.adobe.target.edge.client.http.TargetHttpClient;
import com.adobe.target.edge.client.model.TargetDeliveryRequest;
import com.adobe.target.edge.client.model.TargetDeliveryResponse;
import com.adobe.target.edge.client.utils.CookieUtils;
import com.adobe.target.edge.client.utils.StringUtils;
import com.adobe.target.edge.client.utils.TimingTool;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.concurrent.CompletableFuture;

import kong.unirest.HttpResponse;
import kong.unirest.UnirestParsingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DefaultTargetService implements TargetService {

  public static final String SDK_USER_KEY = "X-EXC-SDK";
  public static final String SDK_USER_VALUE = "AdobeTargetJava";
  public static final String SDK_VERSION_KEY = "X-EXC-SDK-Version";
  public static final String SESSION_ID = "sessionId";
  public static final String ORGANIZATION_ID = "imsOrgId";
  private String sdkVersion;
  private final TargetHttpClient targetHttpClient;
  private final ClientConfig clientConfig;
  private String stickyLocationHint;
  private final TelemetryService telemetryService;
  private static final Logger logger = LoggerFactory.getLogger(DefaultTargetHttpClient.class);

  public DefaultTargetService(ClientConfig clientConfig, TelemetryService telemetryService) {
    TargetHttpClient targetHttpClient = new DefaultTargetHttpClient(clientConfig);
    if (clientConfig.isLogRequests()) {
      this.targetHttpClient = TargetHttpClient.createLoggingHttpClient(targetHttpClient);
    } else {
      this.targetHttpClient = targetHttpClient;
    }

    loadDefaultProperties();
    setDefaultHeaders();

    this.clientConfig = clientConfig;
    this.telemetryService = telemetryService;
  }

  private void loadDefaultProperties() {
    Properties defaultProps = new Properties();
    try {
      defaultProps.load(getClass().getResourceAsStream("/gradle.properties"));
    } catch (IOException e) {
      logger.warn("Unable to load default SDK properties");
    }

    this.sdkVersion = defaultProps.getProperty("version");
  }

  private void setDefaultHeaders() {
    this.targetHttpClient.addDefaultHeader(SDK_USER_KEY, SDK_USER_VALUE);
    if (this.sdkVersion != null) {
      this.targetHttpClient.addDefaultHeader(SDK_VERSION_KEY, this.sdkVersion);
    }
  }

  @Override
  public TargetDeliveryResponse executeRequest(TargetDeliveryRequest deliveryRequest) {
    TimingTool timer = new TimingTool();
    timer.timeStart(TIMING_EXECUTE_REQUEST);
    TargetDeliveryResponse targetDeliveryResponse;

    Telemetry telemetry = telemetryService.getTelemetry();
    if (!telemetry.getEntries().isEmpty()) {
      deliveryRequest.getDeliveryRequest().setTelemetry(telemetry);
    }
    cleanUpGeoContext(deliveryRequest);
    ResponseWrapper response = callDeliveryApi(deliveryRequest);

    targetDeliveryResponse = getTargetDeliveryResponse(deliveryRequest, response.getHttpResponse());

    /* capture Telemetry information once original request's response is received */

    telemetryService.addTelemetry(
        deliveryRequest,
        timer,
        targetDeliveryResponse,
        response.getParsingTime(),
        response.getResponseSize());

    return targetDeliveryResponse;
  }

  @Override
  public CompletableFuture executeRequestAsync(
      TargetDeliveryRequest deliveryRequest) {
    TimingTool timer = new TimingTool();
    timer.timeStart(TIMING_EXECUTE_REQUEST);

    Telemetry telemetry = telemetryService.getTelemetry();
    if (!telemetry.getEntries().isEmpty()) {
      deliveryRequest.getDeliveryRequest().setTelemetry(telemetry);
    }
    cleanUpGeoContext(deliveryRequest);
    CompletableFuture> responseCompletableFuture =
        callDeliveryApiAsync(deliveryRequest);
    return responseCompletableFuture.thenApply(
        response -> {
          TargetDeliveryResponse targetDeliveryResponse =
              getTargetDeliveryResponse(deliveryRequest, response.getHttpResponse());
          telemetryService.addTelemetry(
              deliveryRequest,
              timer,
              targetDeliveryResponse,
              response.getParsingTime(),
              response.getResponseSize());
          return targetDeliveryResponse;
        });
  }

  @Override
  public ResponseStatus executeNotification(TargetDeliveryRequest deliveryRequest) {
    TimingTool timer = new TimingTool();
    timer.timeStart(TIMING_EXECUTE_REQUEST);
    NotificationService.setBeaconToFalse(deliveryRequest.getDeliveryRequest());
    TargetDeliveryResponse targetDeliveryResponse;
    Telemetry telemetry = telemetryService.getTelemetry();
    if (!telemetry.getEntries().isEmpty()) {
      deliveryRequest.getDeliveryRequest().setTelemetry(telemetry);
    }
    cleanUpGeoContext(deliveryRequest);
    ResponseWrapper response = callDeliveryApi(deliveryRequest);
    targetDeliveryResponse = getTargetDeliveryResponse(deliveryRequest, response.getHttpResponse());
    telemetryService.addTelemetry(
        deliveryRequest,
        timer,
        targetDeliveryResponse,
        response.getParsingTime(),
        response.getResponseSize());

    return new ResponseStatus(
        response.getHttpResponse().getStatus(), response.getHttpResponse().getStatusText());
  }

  @Override
  public CompletableFuture executeNotificationAsync(
      TargetDeliveryRequest deliveryRequest) {
    TimingTool timer = new TimingTool();
    timer.timeStart(TIMING_EXECUTE_REQUEST);
    NotificationService.setBeaconToFalse(deliveryRequest.getDeliveryRequest());
    Telemetry telemetry = telemetryService.getTelemetry();
    if (!telemetry.getEntries().isEmpty()) {
      deliveryRequest.getDeliveryRequest().setTelemetry(telemetry);
    }
    cleanUpGeoContext(deliveryRequest);
    CompletableFuture> responseCompletableFuture =
        callDeliveryApiAsync(deliveryRequest);
    return responseCompletableFuture.thenApply(
        response -> {
          TargetDeliveryResponse targetDeliveryResponse =
              getTargetDeliveryResponse(deliveryRequest, response.getHttpResponse());
          telemetryService.addTelemetry(
              deliveryRequest,
              timer,
              targetDeliveryResponse,
              response.getParsingTime(),
              response.getResponseSize());
          return new ResponseStatus(
              response.getHttpResponse().getStatus(), response.getHttpResponse().getStatusText());
        });
  }

  private Map getQueryParams(TargetDeliveryRequest deliveryRequest) {
    Map queryParams = new HashMap<>();
    queryParams.put(SESSION_ID, deliveryRequest.getSessionId());
    queryParams.put(ORGANIZATION_ID, clientConfig.getOrganizationId());
    return queryParams;
  }

  private TargetDeliveryResponse getTargetDeliveryResponse(
      TargetDeliveryRequest deliveryRequest, HttpResponse response) {
    DeliveryResponse deliveryResponse = retrieveDeliveryResponse(response);
    updateStickyLocationHint(deliveryResponse);
    return new TargetDeliveryResponse(
        deliveryRequest, deliveryResponse, response.getStatus(), response.getStatusText());
  }

  private DeliveryResponse retrieveDeliveryResponse(HttpResponse response) {
    DeliveryResponse deliveryResponse = response.getBody();
    if (deliveryResponse == null) {
      Optional parsingError = response.getParsingError();

      throw new RuntimeException(
          "Error parsing delivery response: {}. "
              + (parsingError.isPresent() ? parsingError.get().getOriginalBody() : ""));
    }
    return deliveryResponse;
  }

  private void updateStickyLocationHint(DeliveryResponse deliveryResponse) {
    if (StringUtils.isNotEmpty(stickyLocationHint)) {
      return;
    }
    if (deliveryResponse != null
        && deliveryResponse.getStatus() == SC_OK
        && deliveryResponse.getId() != null
        && deliveryResponse.getId().getTntId() != null) {
      String tntId = deliveryResponse.getId().getTntId();
      this.stickyLocationHint = CookieUtils.locationHintFromTntId(tntId);
    }
  }

  @Override
  public void close() throws Exception {
    targetHttpClient.close();
  }

  private String getBestLocationHint(TargetDeliveryRequest deliveryRequest) {
    if (deliveryRequest.getLocationHint() != null) {
      return deliveryRequest.getLocationHint();
    }
    return stickyLocationHint;
  }

  private ResponseWrapper callDeliveryApi(TargetDeliveryRequest deliveryRequest) {
    String url = clientConfig.getUrl(getBestLocationHint(deliveryRequest));
    return targetHttpClient.execute(
        getQueryParams(deliveryRequest),
        url,
        deliveryRequest.getDeliveryRequest(),
        DeliveryResponse.class);
  }

  private CompletableFuture> callDeliveryApiAsync(
      TargetDeliveryRequest deliveryRequest) {
    String url = clientConfig.getUrl(getBestLocationHint(deliveryRequest));
    return targetHttpClient.executeAsync(
        getQueryParams(deliveryRequest),
        url,
        deliveryRequest.getDeliveryRequest(),
        DeliveryResponse.class);
  }

  private void cleanUpGeoContext(TargetDeliveryRequest deliveryRequest) {
    Geo geo = null;
    if (deliveryRequest.getDeliveryRequest() != null
        && deliveryRequest.getDeliveryRequest().getContext() != null) {
      geo = deliveryRequest.getDeliveryRequest().getContext().getGeo();
    }

    if (geo != null) {
      if (geo.getStateCode() != null && geo.getStateCode().isEmpty()) {
        geo.setStateCode(null);
      }
      if (geo.getCity() != null && geo.getCity().isEmpty()) {
        geo.setCity(null);
      }
      if (geo.getCountryCode() != null && geo.getCountryCode().isEmpty()) {
        geo.setCountryCode(null);
      }
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy