Reputation: 45
I have read through just about everything I can find and for some reason I cannot quite wrap my brain around how to make this work. After struggling in an existing project for 2 days I downloaded the Getting Started Content for Rest from Spring.io
https://spring.io/guides/gs/rest-service/
I created a resources folder in the main folder and added a file called application.properties with the following:
my.setting = HELLOTHERE
I then modified the Greeting class as follows:
package hello;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Component
public class Greeting {
private long id;
private String content;
private String dooDad;
public Greeting(long id, String content) {
this.id = id;
this.content = content;
}
public Greeting() {
// TODO Auto-generated constructor stub
}
public long getId() {
return id;
}
public String getContent() {
return content;
}
public String getDooDad() {
return dooDad;
}
@Autowired
public void setDooDad(@Value("${my.setting}")String dooDad) {
this.dooDad = dooDad;
}
}
I modified the Application class to have the @Configuration annotation as follows:
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
@SpringBootApplication
@Configuration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
I didn't modify the GreetingController class but will include it for completeness:
package hello;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
@RequestMapping("/greeting")
public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name) {
return new Greeting(counter.incrementAndGet(),
String.format(template, name));
}
}
When I run the application and look at the output I expected to see a value for dooDad, instead it is always null.
{"id":1,"content":"Hello, mike!","dooDad":null}
Any help in getting this figured out would be appreciated. I did discover that if I put the @Value annotation on a variable in the Application class it would populate that variable with the correct value, just not when it is in the Greeting Class?
Upvotes: 1
Views: 4719
Reputation: 7051
You are bypassing dependency injection by instantiating the object Greeting
yourself:
return new Greeting(counter.incrementAndGet(),
String.format(template, name));
Thus the @Component
and @Value
annotations within the Greeting
object aren't doing anything (for this particular instance).
I would suggest doing the following:
String dooDad
in the constructor@Value("${my.setting}") String dooDad
as a field in your Greeting Controller
Pass dooDad
into your new Greeting object like so:
return new Greeting(counter.incrementAndGet(), String.format(template, name), dooDad);
Update: Added example project to illustrate various options for achieving the setup described by the OP.
Upvotes: 4