@Override
  public AniServiceDto getByAniService(String aniServiceId, String clientSecret) throws Exception {
    if (StringUtils.isEmpty(aniServiceId) || StringUtils.isEmpty(clientSecret)) {
      throw new Exception("AniServiceId or ClientSecret is null.");
    }

    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder
        .append(anicelMeta.getAniServiceBusUrl())
        .append(anicelMeta.getServiceBusGetByUrl())
        .append("/")
        .append(aniServiceId)
        .append("/")
        .append(clientSecret);

    UriComponentsBuilder uriComponentsBuilder =
        UriComponentsBuilder.fromHttpUrl(stringBuilder.toString());
    LOGGER.info(uriComponentsBuilder.toUriString());
    AniServiceHttpMessage result =
        restTemplateFactory
            .getRestTemplate(new Class[] {AniServiceDto.class})
            .getForObject(uriComponentsBuilder.toUriString(), AniServiceHttpMessage.class);

    if (result.getResultCode() == Message.ResultCode.SUCCESS) {
      return result.getReturnObj();
    } else {
      StringBuilder builder =
          new StringBuilder("message: ")
              .append(result.getMsg())
              .append(", error code:")
              .append(result.getResultCode());
      throw new Exception(builder.toString());
    }
  }
  @Override
  public AniServiceDto register(AniServiceRegisterDto registerDto) throws Exception {
    if (!DomainObjectValidator.isDomainObjectValid(registerDto)) {
      throw new ValidationException("Invalid AniServiceRegisterDto Instance.");
    }

    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.setContentType(MediaType.APPLICATION_JSON);
    httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
    HttpEntity<AniServiceRegisterDto> requestEntity = new HttpEntity<>(registerDto, httpHeaders);

    UriComponentsBuilder uriComponentsBuilder =
        UriComponentsBuilder.fromHttpUrl(
            anicelMeta.getAniServiceBusUrl() + anicelMeta.getServiceBusRegisterUrl());

    LOGGER.info("post url : {}.", uriComponentsBuilder.toUriString());

    AniServiceHttpMessage result =
        restTemplateFactory
            .getRestTemplate(new Class[] {AniServiceDto.class})
            .postForObject(
                uriComponentsBuilder.toUriString(), requestEntity, AniServiceHttpMessage.class);

    if (result.getResultCode() == Message.ResultCode.SUCCESS) {
      return result.getReturnObj();
    } else {
      StringBuilder builder =
          new StringBuilder("message: ")
              .append(result.getMsg())
              .append(", error code:")
              .append(result.getResultCode());
      throw new Exception(builder.toString());
    }
  }
  /**
   * Retrieve a list of Entities
   *
   * @param ids an optional list of entity IDs (cannot be used with idPatterns)
   * @param idPattern an optional pattern of entity IDs (cannot be used with ids)
   * @param types an optional list of types of entity
   * @param attrs an optional list of attributes to return for all entities
   * @param query an optional Simple Query Language query
   * @param geoQuery an optional Geo query
   * @param orderBy an option list of attributes to difine the order of entities
   * @param offset an optional offset (0 for none)
   * @param limit an optional limit (0 for none)
   * @param count true to return the total number of matching entities
   * @return a pagined list of Entities
   */
  public ListenableFuture<Paginated<Entity>> getEntities(
      Collection<String> ids,
      String idPattern,
      Collection<String> types,
      Collection<String> attrs,
      String query,
      GeoQuery geoQuery,
      Collection<String> orderBy,
      int offset,
      int limit,
      boolean count) {

    UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(baseURL);
    builder.path("v2/entities");
    addParam(builder, "id", ids);
    addParam(builder, "idPattern", idPattern);
    addParam(builder, "type", types);
    addParam(builder, "attrs", attrs);
    addParam(builder, "query", query);
    addGeoQueryParams(builder, geoQuery);
    addParam(builder, "orderBy", orderBy);
    addPaginationParams(builder, offset, limit);
    if (count) {
      addParam(builder, "options", "count");
    }

    return adaptPaginated(
        request(HttpMethod.GET, builder.toUriString(), null, Entity[].class), offset, limit);
  }
 /**
  * Retrieve a list of entity types
  *
  * @param offset an optional offset (0 for none)
  * @param limit an optional limit (0 for none)
  * @param count true to return the total number of matching entities
  * @return a pagined list of entity types
  */
 public ListenableFuture<Paginated<EntityType>> getEntityTypes(
     int offset, int limit, boolean count) {
   UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(baseURL);
   builder.path("v2/types");
   addPaginationParams(builder, offset, limit);
   if (count) {
     addParam(builder, "options", "count");
   }
   return adaptPaginated(
       request(HttpMethod.GET, builder.toUriString(), null, EntityType[].class), offset, limit);
 }
 /**
  * Discover registration matching entities and their attributes
  *
  * @param bulkQueryRequest defines the list of entities, attributes and scopes to match
  *     registrations
  * @param offset an optional offset (0 for none)
  * @param limit an optional limit (0 for none)
  * @param count true to return the total number of matching entities
  * @return a paginated list of registration
  */
 public ListenableFuture<Paginated<Registration>> bulkDiscover(
     BulkQueryRequest bulkQueryRequest, int offset, int limit, boolean count) {
   UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(baseURL);
   builder.path("v2/op/discover");
   addPaginationParams(builder, offset, limit);
   if (count) {
     addParam(builder, "options", "count");
   }
   return adaptPaginated(
       request(HttpMethod.POST, builder.toUriString(), bulkQueryRequest, Registration[].class),
       offset,
       limit);
 }
  /**
   * Retrieve the list of all Registrations
   *
   * @return a list of registrations
   */
  public ListenableFuture<List<Registration>> getRegistrations() {

    UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(baseURL);
    builder.path("v2/registrations");

    ListenableFuture<ResponseEntity<Registration[]>> e =
        request(HttpMethod.GET, builder.toUriString(), null, Registration[].class);
    return new ListenableFutureAdapter<List<Registration>, ResponseEntity<Registration[]>>(e) {
      @Override
      protected List<Registration> adapt(ResponseEntity<Registration[]> result)
          throws ExecutionException {
        return new ArrayList<>(Arrays.asList(result.getBody()));
      }
    };
  }
 /**
  * Query multiple entities in a single operation
  *
  * @param bulkQueryRequest defines the list of entities, attributes and scopes to match entities
  * @param orderBy an optional list of attributes to order the entities (null or empty for none)
  * @param offset an optional offset (0 for none)
  * @param limit an optional limit (0 for none)
  * @param count true to return the total number of matching entities
  * @return a paginated list of entities
  */
 public ListenableFuture<Paginated<Entity>> bulkQuery(
     BulkQueryRequest bulkQueryRequest,
     Collection<String> orderBy,
     int offset,
     int limit,
     boolean count) {
   UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(baseURL);
   builder.path("v2/op/query");
   addPaginationParams(builder, offset, limit);
   addParam(builder, "orderBy", orderBy);
   if (count) {
     addParam(builder, "options", "count");
   }
   return adaptPaginated(
       request(HttpMethod.POST, builder.toUriString(), bulkQueryRequest, Entity[].class),
       offset,
       limit);
 }
 /**
  * Update, append or delete multiple entities in a single operation
  *
  * @param bulkUpdateRequest a BulkUpdateRequest with an actionType and a list of entities to
  *     update
  * @return Nothing on success
  */
 public ListenableFuture<Void> bulkUpdate(BulkUpdateRequest bulkUpdateRequest) {
   UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(baseURL);
   builder.path("v2/op/update");
   return adapt(request(HttpMethod.POST, builder.toUriString(), bulkUpdateRequest, Void.class));
 }