[英]Spring Boot @Autowired Environment throws NullPointerException
I have a simple SpringBoot application in which i am using the Environment.class
to access the properties under application.properties
file.我有一个简单的 SpringBoot 应用程序,我在其中使用
Environment.class
访问application.properties
文件下的属性。 The Environment
bean works when it is accessed in the main
method of the Application.class
Environment
bean 在Application.class
的main
方法中访问时起作用
@Configuration
@EnableAutoConfiguration
@ComponentScan(basePackages = "com.cisco.sdp.cdx.consumers")
public class StreamingConsumerApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(StreamingConsumerApplication.class, args);
Environment env = context.getBean(Environment.class);
StreamingConsumerFactory factory = context.getBean(StreamingConsumerFactory.class);
StreamingConsumer streamingConsumer = factory.createStreamingConsumer(StreamType.valueOf(env.getRequiredProperty("streaming.application.type")));
streamingConsumer.consume();
}
}
When the same is used in a different class it throws NullPointerException
.当在不同的类中使用它时,它会抛出
NullPointerException
。 I tried annotating the class with @Configuration
, @Component
, @Repository
, @Service
annotations but did not work.我尝试使用
@Configuration
、 @Component
、 @Repository
、 @Service
注释对类进行注释,但没有奏效。
I tried @Autowired
as well as @Resource
annotations.我尝试了
@Autowired
和@Resource
注释。 But, it didn't work.但是,它没有用。
@Component
public class InventoryStreamingConsumer implements StreamingConsumer {
@Autowired
private Environment env;
@Autowired
private JavaSparkSessionSingleton sparksession;
@Autowired
private StreamingContext _CONTEXT;
private final Map<String, String> kafkaParams = new HashMap<String, String>();
@Override
public void consume() {
if(env == null) {
System.out.println("ENV is NULL");
}
System.out.println(env.getRequiredProperty("kafka.brokerlist"));
kafkaParams.put("metadata.broker.list", env.getRequiredProperty("kafka.brokerlist"));
Set<String> topics = Collections.singleton(env.getRequiredProperty("kafka.topic"));
// Unrelated code.
}
I tried following the answers provided in the below questions我尝试按照以下问题中提供的答案进行操作
Spring Boot - Environment @Autowired throws NullPointerException Spring Boot - 环境 @Autowired 抛出 NullPointerException
Autowired Environment is null 自动装配环境为空
I am looking for suggestions on solving the issue.我正在寻找解决问题的建议。
The @Configuration
annotation is misused here for InventoryStreamingConsumer
. @Configuration
注释在这里被误用于InventoryStreamingConsumer
。 Try @Component
, @Repository
or @Service
.试试
@Component
、 @Repository
或@Service
。
UPDATE更新
Another misuse is另一个误用是
StreamingConsumer streamingConsumer = factory.createStreamingConsumer(StreamType.valueOf(env.getRequiredProperty("streaming.application.type")));
@Autowired
or @Resource
can only work in bean
created by Spring
. @Autowired
或@Resource
只能在Spring
创建的bean
工作。 the streamingConsumer
created by your StreamingConsumerFactory factory
cannot use @Autowired
for injection of its properties.您的
StreamingConsumerFactory factory
创建的streamingConsumer
不能使用@Autowired
来注入其属性。
You should create an @Configuration
class, to tell Spring
to create streamingConsumer
from your factory.您应该创建一个
@Configuration
类,以告诉Spring
从您的工厂创建streamingConsumer
消费者。 Like this像这样
@Configuration
public class ConsumerCreator {
@Autowired
StreamingConsumerFactory factory;
@Bean
public StreamingConsumer streamingConsumer() {
return factory.createStreamingConsumer(StreamType.valueOf(env.getRequiredProperty("streaming.application.type")));
}
}
And use no annotation for InventoryStreamingConsumer
, meanwhile use并且对
InventoryStreamingConsumer
不使用注释,同时使用
StreamingConsumer streamingConsumer = context.getBean(StreamingConsumer.class);
in your StreamingConsumerApplication.main()
method instead to retrieve streamingConsumer
在您的
StreamingConsumerApplication.main()
方法中,而不是检索streamingConsumer
First, please annotate the main class with only @SpringBootApplication
首先,请只用
@SpringBootApplication
注释主类
@SpringBootApplication
public class StreamingConsumerApplication {
}
@ComponentScan
is required if your packages are not within the same structure as main class with main class being outside the sub-package and inside parent package with every other class in the same or some sub-package of parent package. @ComponentScan
如果您的包与主类不在同一结构内,主类在子包外部和父包内部,而所有其他类都在父包的同一或某个子包中,则需要@ComponentScan
。
Second, Please create a Configuration class and annotate it with @Configuration
separately and define a @Bean
there for StreamingConsumer streamingConsumer
and than it can be @Autowired
or injected in the InventoryStreamingConsumer
class.其次,请创建一个 Configuration 类并单独用
@Configuration
对其进行注释,并在那里为StreamingConsumer streamingConsumer
定义一个@Bean
,然后它可以被@Autowired
或注入InventoryStreamingConsumer
类中。
Third, where is the @Bean
for JavaSparkSessionSingleton defined?第三,
@Bean
在哪里定义的? Are you sure it can be AutoConfigured for injection你确定它可以为注射自动配置吗
Fourth, InventoryStreamingConsumer
can be a @Component
, injecting Environment
with @Autowiring
will work once the above things are sorted.第四,
InventoryStreamingConsumer
可以是一个@Component
,一旦上面的东西被排序,用@Autowiring
注入Environment
@Autowiring
可以工作了。
Also, recommending to change your class to this for the sake depending on how consume()
method is used.此外,建议将您的类更改为此目的,具体取决于如何
consume()
方法。
@Component
public class InventoryStreamingConsumer implements StreamingConsumer {
private final Environment env;
private final JavaSparkSessionSingleton sparksession;
private final StreamingContext _CONTEXT;
private final Map<String, String> kafkaParams = new HashMap<String, String>();
@Autowired
public InventoryStreamingConsumer(Environment env, JavaSparkSessionSingleton sparkSession, StreamingContext context) {
this.env = env;
this.sparksession = sparkSession;
this._CONTEXT = context;
}
@Override
public void consume() {
if(env == null) {
System.out.println("ENV is NULL");
}
System.out.println(env.getRequiredProperty("kafka.brokerlist"));
kafkaParams.put("metadata.broker.list", env.getRequiredProperty("kafka.brokerlist"));
Set<String> topics = Collections.singleton(env.getRequiredProperty("kafka.topic"));
// Unrelated code.
}
I have similar issue but read the properties from different file and different location like common/jdbc.properties .我有类似的问题,但从不同的文件和不同的位置读取属性,如common/jdbc.properties 。 I solved this issue by doing this:
我通过这样做解决了这个问题:
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.env.Environment;
@Configuration
@PropertySource(value = {"classpath:common/jdbc.properties"})
public class ExternalConfig implements EnvironmentAware {
private Environment environment;
public void setEnvironment(Environment environment) {
this.environment = environment;
}
@Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
return new PropertySourcesPlaceholderConfigurer();
}
public String getJdbcUrl() {
return environment.getProperty("jdbc.url");
}
}
Try adding尝试添加
@PropertySource("classpath:application.properties")
on InventoryStreamingConsumer class在 InventoryStreamingConsumer 类上
This is how am using it这就是我如何使用它
@Configuration
@ComponentScan({ "com.spring.config" })
@EnableTransactionManagement
@PropertySource("classpath:application.properties")
public class HibernateConfiguration {
private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver";
private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password";
private static final String PROPERTY_NAME_DATABASE_URL = "db.url";
private static final String PROPERTY_NAME_DATABASE_USERNAME = "db.username";
private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
@Autowired
private Environment env;
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
dataSource.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
dataSource.setUsername(env.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
dataSource.setPassword(env.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));
return dataSource;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.