背景:我正在尝试为我们的Cassandra数据库建立一个基于代码的数据迁移系统。我没有大量的Java经验,但是如果这是一个.NET项目,我将在相同的解决方案下将迁移设置为另一个项目。但是,根据经验丰富的其他团队成员的建议,建议将迁移内容与应用程序的其余部分包含在同一软件包中(我很好)。还建议最简单的方法是通过Web API端点(我对此持怀疑态度)运行迁移。为了避免打开潜在的安全漏洞,我认为我会尝试制作一个命令行实用程序来执行迁移。



我有一个带有入口点类的Spring Boot Web应用程序,如下所示:

@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 arg执行此操作时,Spring抛出此错误:


创建名称为“ migrationRunner”的bean时出错:通过字段“ session”表示不满意的依赖性


创建在类路径资源[org / springframework / boot / autoconfigure / data / cassandra / CassandraDataAutoConfiguration.class]中定义的名称为'session'的bean时出错:调用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 arg的情况下运行它仍然可以正常工作。我怀疑Spring只是没有为该Cassandra服务器选择正确的证书,即使它似乎正在获取所有其他配置属性(服务器名称,键空间等)也是如此。

问题:如何制作一个也具有命令行模式并且可以在两种模式下都可以连接到已配置的Cassandra服务器的Spring Boot servlet?

最佳答案

您需要做的就是

@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);
  }
}

09-11 13:34