Настройка гибкой иерархической структуры в Spring Boot - PullRequest
0 голосов
/ 04 марта 2019

Я пытаюсь интегрировать библиотеку Apache Tinkerpop gremlin-driver в мое приложение Spring Boot.Эта библиотека требует, чтобы конфигурация сериализатора передавалась как параметр Map<String, Object>, который, как ожидается, будет соответствовать JSON / YAML-подобной структуре.

Чтобы пользователь приложения мог настраивать драйвер во время выполнения, я попыталсяиспользовать аннотацию Spring Boot ConfigrationProperties для загрузки конфигурации Gremlin и инициализации библиотеки.

К сожалению, Spring загружает вложенные списки в конфигурации сериализатора как Map<String, Object> с ключом, представляющим индекс, вместо списка..

Expected: {
  "ioRegistries": [
    "org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry"
  ], 
  "serializeResultToString": true
}

Actual: {
  "ioRegistries": {
    "0": "org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry"
  }, 
  "serializeResultToString": true
}

application.yml

gremlin:
  endpoint: localhost
  port: 8182
  username:
  password:
  sslEnabled: false
  serializer: GRYO_V1D0
  serializerConfig:
    ioRegistries:
      - org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry
    serializeResultToString: true

GremlinApplication.java

import javax.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.apache.tinkerpop.gremlin.driver.Cluster;
import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
import org.apache.tinkerpop.gremlin.driver.ser.Serializers;
import org.apache.tinkerpop.shaded.jackson.core.JsonProcessingException;
import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

@SpringBootApplication
@EnableConfigurationProperties(GremlinConfiguration.class)
@Slf4j
public class GremlinApplication {

  private static final ObjectMapper mapper = new ObjectMapper();

  @Autowired
  private GremlinConfiguration config;

  public static void main(String[] args) {
    SpringApplication.run(GremlinApplication.class, args);
  }

  @PostConstruct
  public void setup() throws JsonProcessingException {
    log.info("Serializer Config: {}", mapper.writeValueAsString(config.getSerializerConfig()));
    // Prints 'Serializer Config: {"ioRegistries":{"0":"org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry"},"serializeResultToString":true}'

    MessageSerializer serializer = Serializers.valueOf(config.getSerializer()).simpleInstance();

    // Expects config to be map representing JSON structure, throws exception.
    // Cause: java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to java.util.List
    serializer.configure(config.getSerializerConfig(), null);

    Cluster.build(config.getEndpoint())
        .serializer(serializer)
        .credentials(config.getUsername(), config.getPassword())
        .port(config.getPort())
        .enableSsl(config.getSslEnabled())
        .create();
  }

}

GremlinConfiguration.java

import java.util.Map;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;

@Data
@NoArgsConstructor
@ConfigurationProperties("gremlin")
public class GremlinConfiguration {

  private String endpoint;
  private Integer port;
  private String username;
  private String password;
  private Boolean sslEnabled;
  private String serializer;
  private Map<String, Object> serializerConfig;

}

Есть ли способ настроить Spring Boot для преобразования этих вложенных Карт в Списки без явного определения всех возможных параметров конфигурации?

Или даже десериализовать свойство конфигурации в JsonNode Джексона (или эквивалентный), который затем можно преобразовать в требуемую структуру данных?

...