Spring Boot @Autowired Environment Throws Nullpointerexception

Spring Boot - Environment @Autowired throws NullPointerException

I believe there were some lifecycle issues with Spring and the EntityManagerFactory, and you might have fallen foul of those (fixed in 4.0.0.RC1) - if your @Configuration class gets instantiated super early, it might not be eligible for autowiring. You can probably tell from the log output if that is the case.

Just out of interest, did you know that the functionality provided by your JpaConfig and PropertyConfig is already presetn out of the box if you use @EnableAutoConfiguration (as long as you @ComponentScan that package where your repositories are defined)? See the JPA sample in Spring Boot for an example.

Spring Boot @Autowired Environment throws NullPointerException

The @Configuration annotation is misused here for InventoryStreamingConsumer. Try @Component, @Repository or @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. the streamingConsumer created by your StreamingConsumerFactory factory cannot use @Autowired for injection of its properties.

You should create an @Configuration class, to tell Spring to create streamingConsumer from your factory. 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

        StreamingConsumer streamingConsumer = context.getBean(StreamingConsumer.class);

in your StreamingConsumerApplication.main() method instead to retrieve streamingConsumer

Program crashes with NullPointerException when trying to access environment variables from application.properties

Autowired works only on class instances managed by Spring. The value is injected after the constructor. Your class isn't managed by Spring and your environment property is static.

Something like this will work:

@Service // Will be instantiated by spring
public class MailService {
private static Environment env;

@Autowired // This will be called after instantiation
public void initEnvironment(Environment env){
MailService.env = env;
}

public static void send(){
// NullPointerException will be thrown if this method is called
// before Spring created the MailService instance
System.out.println("env {}" + env.getProperty("AWS_ACCESS_KEY_ID"));
}
}

You should avoid using static method if you want access to object managed by Spring.

Instead let Spring manage all your class instances and inject your service when you need it.

@Service
class AnotherService {
@Autowired
private MailService mailSvc;
...

Autowired Environment is null

Autowiring happens later than load() is called (for some reason).

A workaround is to implement EnvironmentAware and rely on Spring calling setEnvironment() method:

@Configuration
@ComponentScan(basePackages = "my.pack.offer.*")
@PropertySource("classpath:OfferService.properties")
public class PropertiesUtil implements EnvironmentAware {
private Environment environment;

@Override
public void setEnvironment(final Environment environment) {
this.environment = environment;
}

@Bean
public String load(String propertyName)
{
return environment.getRequiredProperty(propertyName);
}
}

Autowired Environment variable is NULL when @Bean annotated method is executed

There are many ways to do this.

  1. Since you are using Springboot, you do not have to create a
    Datasource explicitly like this(If you do so, you are missing out on one of the main features of springboot). If you declare the parameters in
    properties/yml with right keys, Springboot with Autoconfigure this
    for you.

    Search for spring.datasource...... here

  2. If you wish to do this on your own, then You can autowire all the variables in properties/yml file into a Bean using
    ConfigurationProperties then use this bean as method parameter in
    your bean creation method.

    check this out

  3. Use @Value{} in your AppConfig class and use it in your Datasource creation method.

Getting NullPointerException when tried to read @Autowired configuration object

A - How To Read Custom Property From application.properties In Spring Boot

A-1) Application Properties file

On of the default location of application.properties file is src/main/resources. Create this folder and also this file. Assuming your scenario, put the following properties inside application.properties file;

myconfig.ip=192.168.166.42
myconfig.port=8090

A-2) Configuration Class : AppConfig

In order to read the properties file, you need a class with @Configuration annotation. You need appropriate fields with @Value annotation for all the properties that you need to read. In addition, also you need the getter methods for these fields marked with @Value annotation. Please note that naming this class as "Configuration" is a very bad choice because there is also an annotation with the same name, thus I name it as "AppConfig"

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

@Value("${myconfig.ip}")
private String ip;

@Value("${myconfig.port}")
private int port;

public String getIp() {
return ip;
}

public int getPort() {
return port;
}

}

A-3) Demo

Then you create a fields of this AppConfig class which is written above, and mark it with @Autowired annotation. Then you can read the properties files easily;

@RestController
@RequestMapping("/")
public class InputManagementController {

@Autowired
private AppConfig config;

@RequestMapping("/test")
public String test() {
return String.format(
"Configuration Parameters: Port: %s, Ip: %s",
config.getPort(),
config.getIp()
);
}

}

A-4) Output

enter image description here

B - Solution To Problem

B-1) InputManagementController.java

@RestController
public class InputManagementController {

@Autowired
private AppConfig configuration;

@Autowired
private ElasticSearchInterface elasticSearchInterface;

@GetMapping("/crawler/start")
public String start() {
try {

System.out.println(configuration.getIp());
es.getInputs();
} catch (Exception e) {
e.printStackTrace();
}
return "started";
}
}

B-2) ElasticSearchInterface.java

@Component
public class ElasticSearchInterface {

@Autowired
private AppConfig configuration;

public List<Map<String, Object>> getInputs() {
System.out.println(configuration.getIp());

return null;
}

}

B-3) AppConfig.java

@Configuration
public class AppConfig {

@Value("${myconfig.ip}")
private String ip;

@Value("${myconfig.port}")
private int port;

public String getIp() {
return ip;
}

public int getPort() {
return port;
}

}

How to solve NullPointerException when Autowiring component in spring-boot application

Put yourself in Spring's shoes. It has to contruct a ContactView, and populate its services field.

To be able to populate the field of the object, the object needs to exist, right? So it has to call the constructor to construct the object, before being able to set its field. So, when the constructor is called, the field can't possibly be populated yet, and is thus null. Hence the NullPointerException, since you call a method on the field inside the constructor.

Solution: don't use field injection. Use constructor injection.

// NO @Autowired here
private Services services;

@Autowired // this is actually optional unless you have another constructor
public ContactView(Services services) {
this.services = services;
// ...


Related Topics



Leave a reply



Submit