Spring 启动 - application.properties:获取 Cassandra 数据时出错:java.lang.NullPointerException

Spring boot - application.properties: ERROR to get the Cassandra's data: java.lang.NullPointerException

我正在尝试从 application.properties 获取 Cassandra 的数据,但是当我尝试连接 Cassandra 的数据库时它返回 null。

错误:

java.lang.NullPointerException: null value for spark.cassandra.connection.host at org.apache.spark.SparkConf.set(SparkConf.scala:91) ~[spark-core_2.12-3.1.1.jar:3.1.1] at org.apache.spark.SparkConf.set(SparkConf.scala:83) ~[spark-core_2.12-3.1.1.jar:3.1.1]

aplication.properties:

spring.data.cassandra.cluster= myApp
spring.data.cassandra.contact-points= 127.0.0.1
spring.data.cassandra.keyspace-name= myappkeyspace
spring.data.cassandra.port= 9042

CassandraConfig

@Configuration
public class CassandraConfig extends AbstractCassandraConfiguration {

    @Value("${spring.data.cassandra.contact-points}")
    private String contactPoints;

    @Value("${spring.data.cassandra.port}")
    private int port;

    @Value("${spring.data.cassandra.keyspace-name}")
    private String keySpace;

    @Value("${spring.data.cassandra.basePackages}")
    private String basePackages;

    @Value("${spring.data.cassandra.username}")
    private String username;

    @Value("${spring.data.cassandra.password}")
    private String password;

    @Override
    protected String getKeyspaceName() {
        return keySpace;
    }

    public CassandraConfig() {
        super();
    }

    @Override
    protected String getContactPoints() {
        return contactPoints;
    }

    @Override
    protected int getPort() {
        return port;
    }

    @Override
    public SchemaAction getSchemaAction() {
        return SchemaAction.CREATE_IF_NOT_EXISTS;
    }

    @Override
    public String[] getEntityBasePackages() {
        return new String[] { basePackages };
    }

    public String getKeySpace() {
        return keySpace;
    }

    public void setKeySpace(String keySpace) {
        this.keySpace = keySpace;
    }

    public String getBasePackages() {
        return basePackages;
    }

    public void setBasePackages(String basePackages) {
        this.basePackages = basePackages;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setContactPoints(String contactPoints) {
        this.contactPoints = contactPoints;
    }

    public void setPort(int port) {
        this.port = port;
    }

    @Bean
    public CassandraConfig cluster() {
        CassandraConfig cluster = new CassandraConfig();
        cluster.setContactPoints(contactPoints);
        cluster.setPort(port);
        cluster.setUsername(username);
        cluster.setPassword(password);
        return cluster;
    }

DataSourceCassandraConfig

public SparkSession getSession() {
        CassandraConfig cassandraConfig = new CassandraConfig();
        cassandraConfig = cassandraConfig.cluster();
    
        SparkSession spark = SparkSession.builder().appName("SparkCassandraApp")
                .config("spark.cassandra.connection.host", cassandraConfig.getContactPoints())
                .config("spark.cassandra.connection.port", cassandraConfig.getPort()).config("spark.cassandra.auth.username", cassandraConfig.getUserName())
                .config("spark.cassandra.auth.password", cassandraConfig.getPassword()).master("local[2]").getOrCreate();
        return spark;
}

SpringApplication

@SpringBootApplication
@EnableCassandraRepositories(basePackages = { "br.com.myapp.*" })
@EntityScan(basePackages = { "br.com.myapp.*" })
@ComponentScan(basePackages = {"br.com.myapp.*"})
public class App extends SpringBootServletInitializer 
{
    public static void main( String[] args )
    {
        SpringApplication.run(App.class, args);
    }
}

编辑

当我在 DataSourceCassandraConfig 中调用 cassandraConfig.cluster() 时,eclipse 的调试显示空值。 观察:我在 DataSourceCassandraConfig 的 class.

中使用 @Autowired 进行了测试

问题出在 DataSourceCassandraConfig 中的代码行。

CassandraConfig cassandraConfig = new CassandraConfig();

以上行通过构造函数构造了一个新的 CassandraConfig 实例。它不使用在 spring 上下文中自动装配的那个。用这样的东西替换它:

编辑

@Autowired
CassandraConfig cassandraConfig;

public SparkSession getSession() {
        cassandraConfig = cassandraConfig.cluster();

或者更好的是,使用构造函数注入自动装配:

private final CassandraConfig inCassandraConfig;

DataSourceCassandraConfig(CassandraConfig inCassandraConfig){
    cassandraConfig = inCassandraConfig;
}

public SparkSession getSession() {
    cassandraConfig = cassandraConfig.cluster()

另一件需要注意的事情是 ComponentScan,以确保 CassandraConfig 和 DataSourceCassandraConfig 在包 br.com.myapp 内。*(或包含包名称以便我可以看到它们)。

确保所有 spring classes 都被组件扫描的一个好方法是将所有 classes 移动到 class 下面的包中@SpringBootApplication 注释(class App 在你的例子中)。此外,检查 @Value 注释是否自动连接,甚至可能注释掉代码以防止构造函数抛出异常。如果它们没有被填充,那是接线问题,class 可能没有被扫描。

问题似乎是在创建 CassandraConfig bean 时它仍然没有加载 contactPoints 的值。您正在使用的 @Values 将始终在创建 bean 后加载。

我认为你在这里能做的最好的事情就是创建一个构造函数来接收你需要的值,就像这样

public CassandraConfig (@Value("${spring.data.cassandra.contact-points}") String contactPoints) {
...whatever code...
this.contactPoints = contactPoints;
...whatever code...
}

在这种情况下,contactPoints 将在创建 bean 时加载。