I'm learning how to create a RESTful API with Springboot, and the @Value tag is not injecting values from application.properties, nor is it injecting values specified in the tag itself. I have my project structured as such:
- api
- config
- controllers
- model
- services
- SpringApplication.java
- resources
- application.properties
Strangely, this behavior only seems to occur within files located in my "services" folder. The @Value
tag works as expected in files located in my "controllers" folder. Below are examples of what I am doing:
@Value("${var}")
String variable
"var" is defined in application.properties as var=some_string
but variable is still initialized as 'null'
@Value("I am directly assigning a value to this variable, but it still comes out null")
String variable
I believe I am using the correct import: import org.springframework.beans.factory.annotation.Value
.
At first I just thought the "services" folder was blind to the directory where application.properties is located, but after trying to directly inject values, I'm not so sure what to think.
Edit
All of the classes in the services folder are annotated with @Service
and nothing else. Below is what the class looks like. I've opted to leave out implementations of the methods, other variables, and irrelevant imports. The code/methods all work as expected when hard-coding the variables. My focus is the @Value tag.
package myapi.api.services;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Value("${var}")
String variable;
public List<Data> getData() {
return new ArrayList<Data>();
}
public void postData() {
}
Edit 2
Below is the APIController class, stored in the "controllers" folder. Again, I've opted to leave out irrelevant methods/imports/variables. I would also like to note, that the @Value
tag works as expected in this class.
package myapi.api.controllers;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import myapi.api.services.MyService;
import lombok.RequiredArgsConstructor;
@RestController
@RequestMapping("api")
@RequiredArgsConstructor
public class APIController {
@Autowired
private final static MyService myService = new MyService();
@GetMapping("/getdata")
public List<Data> getData() {
return myService.getData();
}
}
CodePudding user response:
@Autowired
private final static MyService myService = new MyService();
Three issues:
First, you cannot have a new
operator. Spring controls the lifecycle of your class instances. It will call new
for you in the background. Remove the entire new operator stanza.
Next: your your field cannot be final
. After construction of the class, Spring will need to modify that field with a proxy. Remove the final
declaration;
Finally: your field cannot be static
. static
variables have a certain lifecycle with the JVM, and you need to let the Spring framework manage your lifecycle. remove the static operator.
The correct declaration should be:
@Autowired
private MyService myService;