Spring Boot может подключаться к Cassandra при запуске в качестве сервлета, но не в качестве командной строки - PullRequest
0 голосов
/ 07 ноября 2019

Справочная информация: Я пытаюсь настроить систему переноса данных на основе кода для нашей базы данных Cassandra. У меня нет большого опыта работы с Java, но если бы это был проект .NET, я бы настроил миграции как другой проект под тем же решением. Однако, основываясь на рекомендациях других опытных членов команды, было рекомендовано включить миграции в тот же пакет, что и остальная часть приложения (с которым я в порядке). Также было предложено, что самым простым способом было бы запустить миграцию через конечную точку веб-API (к которой я отношусь более скептически). Чтобы избежать потенциальной уязвимости безопасности, я решил попробовать утилиту командной строки для выполнения миграций.


У меня есть веб-приложение Spring Boot скласс точки входа, который выглядит следующим образом:

@Configuration
@SpringBootApplication
@EnableAutoConfiguration
@EnableCaching
@EnableScheduling
public class MyApplication extends SpringBootServletInitializer {

  @Override
  protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
    return application.sources(MyApplication.class);
  }

  public static void main(String[] args) {
    new MyApplication().configure(new SpringApplicationBuilder(MyApplication.class)).run(args);
  }
}

Однако я пытаюсь добавить функциональность для запуска пары сценариев миграции, которые упакованы с этим приложением через командную строку (например, java -jar MyApplication.jar migrate),поэтому я добавил следующий класс:

@Configuration
@SpringBootApplication
@EnableAutoConfiguration
public class MigrationRunner implements CommandLineRunner {

  @Autowired
  Session session;

  @Override
  public void run(String[] args)
  {
    MigrationResources mr = new MigrationResources();
    mr.addMigration(...);
    mr.addMigration(...);

    MigrationEngine.withSession(session).migrate(mr);
  }
}

и затем обновил свой класс точки входа следующим образом:

// annotations
public class MyApplication extends SpringBootServletInitializer {

  private final static String MIGRATE_COMMAND = "migrate";

  @Override
  protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
    return application.sources(MyApplication.class);
  }

  public static void main(String[] args) {
    if (args.length > 0 && args[0].equalsIgnoreCase(MIGRATE_COMMAND)) {
      new SpringApplicationBuilder()
          .sources(MigrationRunner.class)
          .run(Arrays.copyOfRange(args, 1, args.length));
    } else {
      new MyApplication().configure(new SpringApplicationBuilder(MyApplication.class)).run(args);
    }
  }
}

Проблема в том, что когда я выполняю это с аргументом migrate,Spring выдает эту ошибку:

Ошибка создания бина с именем'igrationRunner ': неудовлетворенная зависимость, выраженная через поле' сеанс '

Ошибка создания бина с именем' сеанс ', определенным вресурс пути к классу [org / springframework / boot / autoconfigure / data / cassandra / CassandraDataAutoConfiguration.class]: сбой вызова метода init

Все хосты попытались выполнить запрос (попытка: server022 / XX.YY.ZZ.022: 9042 (com.datastax.driver.core.exceptions.TransportException: [server022 / XX.YY.ZZ.022: 9042)] Соединение было закрыто), server022 / XX.YY.ZZ.020: 9042 (com.datastax.driver.core.exceptions.TransportException: [server020 / XX.YY.ZZ.020: 9042] Соединение было закрыто),server020 / XX.YY.ZZ.021: 9042 (com.datastax.driver.core.exceptions.TransportException: [server020 / XX.YY.ZZ.021: 9042] Соединение было закрыто))

Запуск без аргумента migrate по-прежнему работает нормально. Я подозреваю , что Spring просто не подбирает правильные сертификаты для этого сервера Cassandra, хотя, похоже, он получает все другие свойства конфигурации (имя сервера, пространство ключей и т. Д.)

Вопрос: Как создать сервлет Spring Boot, который также имеет режим командной строки и может подключаться к настроенному серверу Cassandra в обоих режимах?

1 Ответ

0 голосов
/ 07 ноября 2019

Все, что вам нужно сделать, это,

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

Вы слишком усложнили приложение. Если вы запустите MyApplication.main, который будет работать в порту 8080 по умолчанию.

Бонус, если вам нужно, чтобы оба запускались с одинакового class.

@SpringBootApplication
public class MigrationRunner implements CommandLineRunner {

  @Autowired
  Session session;


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

  @Override
  public void run(String[] args)
  {
    MigrationResources mr = new MigrationResources();
    mr.addMigration(...);
    mr.addMigration(...);

    MigrationEngine.withSession(session).migrate(mr);
  }
}
...