Reputation: 691
I have the application.properties, which is located in the resources
apllication.properties
hsm.provider=software
hsm.name=TestHsm
hsm.port=3001
hsm.ip=127.0.0.1
hsm.timeout=10000
and the Controller
@RestController
@RequestMapping("/hsm")
public class Controller {
@Value("${hsm.ip}")
private String ip;
@Value("${hsm.port}")
private String port;
@Value("${hsm.name}")
private String name;
@Value("${hsm.timeout}")
private String timeout;
@Value("${hsm.provider}")
private String provider;}
}
however when i run application, all variables remain NULL. What am i missing?
EDIT This is the projectstructure as of the src folder
src
├───main
│ ├───java
│ │ └───com
│ │ └───xyz
│ │ └───hsmservice
│ │ └───hsm
│ │ └───api
│ │ Application.java
│ │ Controller.java
│ │ HSM.java
│ │
│ └───resources
│ │ application.properties
│ │
│ └───META-INF
│ plugin.xml
│
└───test
├───java
│ LibraryTest.java
│
└───resources
EDIT 2 Here is the application class
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Upvotes: 24
Views: 84644
Reputation: 471
@Value returns null because of the following reasons, so make sure
1.The class in which you use @Value is not declared as any of the spring initialized class for ex: component,service,repository. So make the class as spring-managed class
@Component
class ClassA {
@Value("${property.value}")
private String valueString;
}
OR
@Service
class ClassA {
@Value("${property.value}")
private String valueString;
}
OR
@Repository
class ClassA {
@Value("${property.value}")
private String valueString;
}
2.You must be passing this class as a newly initialised object, from the place where you are calling the method in this class. You should @Autowire the class in the calling class and then use the method.
@Component
public class ClassA {
private final String propertyValue;
@Autowired
public ClassA(@Value("${propery.value}") String propertyValue) {
this.propertyValue = propertyValue;
}
}
Upvotes: 1
Reputation: 1
See the answer is very simple I have been through the same problem So I am writing this here so that nobody faces it again.
In order to use the values injected in the bean of a class.
You need to autowire that class in which the injection has been done to another class where you want the values to be used.
And the injected vales will never be null.
Since once spring has started with autowiring the beans would always be fetched with non null values.
Upvotes: -2
Reputation: 717
You can use a separate class that autowires the values from properties file. Create a class like this:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Properties {
public static String hsmProvider;
@Autowired
public Properties(@Value("${hsm.provider}") String hsmProvider){
Properties.hsmProvider = hsmProvider;
}
}
You can use the property anywhere as Properties.hsmProvider
Upvotes: 3
Reputation: 131
The reason why @Value returns null sometimes is because when you try to use 'application.properties' contents for static variables which is not allowed in spring. Follow this: https://mkyong.com/spring/spring-inject-a-value-into-static-variables/ and it should work fine.
Upvotes: 13
Reputation: 59
I had the same issue with doing the @Value in my service file. I was making a new service in my controller file
NOT WORKING:
UserController.java
UserService userService = new UserService();
String user = userService.getUser(); // NULL!!
UserService.java
public class UserService {
@Value("${hello.world}")
String hello;
public String GetUser() {
return hello; // NULL!!
}
}
and that was overriding my injection in my UserService file.
So instead, I did the @Value injection in my Controller file, and passed that variable along into my service constructor.
WORKING:
UserController.java
@Value("${hello.world}")
String hello;
UserService userService = new UserService(hello);
UserService.java
public class UserService {
private String hello;
// constructor
public UserService(@Value("${hello.world}") String hello) {
this.hello = hello;
}
}
Upvotes: 0
Reputation: 691
Okay, i solved it with the top answer of this Question. I put the variables and @Values in the signature of the constructor and not as class variables.
Upvotes: 14
Reputation: 1151
I've added your code into a Spring boot project and it is in a working condition.
Checkout this 53482633 repository and follow the instructions to get it up and running.
Also compare your code against this application to figure out what was going wrong at your end.
In case if you still face any issues, please post it here.
Upvotes: 1
Reputation: 1148
Controller.java
With Lombok
package com.example.demo;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/hsm")
@Data
public class Controller {
@Value("${hsm.ip}")
private String ip;
@Value("${hsm.port}")
private String port;
@Value("${hsm.name}")
private String name;
@Value("${hsm.timeout}")
private String timeout;
@Value("${hsm.provider}")
private String provider;
}
Without Lombok ( generated by Intelliji - Refactor DeLombok )
package com.example.demo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/hsm")
public class Controller {
@Value("${hsm.ip}")
private String ip;
@Value("${hsm.port}")
private String port;
@Value("${hsm.name}")
private String name;
@Value("${hsm.timeout}")
private String timeout;
@Value("${hsm.provider}")
private String provider;
public Controller() {
}
public String getIp() {
return this.ip;
}
public String getPort() {
return this.port;
}
public String getName() {
return this.name;
}
public String getTimeout() {
return this.timeout;
}
public String getProvider() {
return this.provider;
}
public void setIp(String ip) {
this.ip = ip;
}
public void setPort(String port) {
this.port = port;
}
public void setName(String name) {
this.name = name;
}
public void setTimeout(String timeout) {
this.timeout = timeout;
}
public void setProvider(String provider) {
this.provider = provider;
}
public boolean equals(final Object o) {
if (o == this) return true;
if (!(o instanceof Controller)) return false;
final Controller other = (Controller) o;
if (!other.canEqual((Object) this)) return false;
final Object this$ip = this.getIp();
final Object other$ip = other.getIp();
if (this$ip == null ? other$ip != null : !this$ip.equals(other$ip)) return false;
final Object this$port = this.getPort();
final Object other$port = other.getPort();
if (this$port == null ? other$port != null : !this$port.equals(other$port)) return false;
final Object this$name = this.getName();
final Object other$name = other.getName();
if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;
final Object this$timeout = this.getTimeout();
final Object other$timeout = other.getTimeout();
if (this$timeout == null ? other$timeout != null : !this$timeout.equals(other$timeout)) return false;
final Object this$provider = this.getProvider();
final Object other$provider = other.getProvider();
if (this$provider == null ? other$provider != null : !this$provider.equals(other$provider)) return false;
return true;
}
protected boolean canEqual(final Object other) {
return other instanceof Controller;
}
public int hashCode() {
final int PRIME = 59;
int result = 1;
final Object $ip = this.getIp();
result = result * PRIME + ($ip == null ? 43 : $ip.hashCode());
final Object $port = this.getPort();
result = result * PRIME + ($port == null ? 43 : $port.hashCode());
final Object $name = this.getName();
result = result * PRIME + ($name == null ? 43 : $name.hashCode());
final Object $timeout = this.getTimeout();
result = result * PRIME + ($timeout == null ? 43 : $timeout.hashCode());
final Object $provider = this.getProvider();
result = result * PRIME + ($provider == null ? 43 : $provider.hashCode());
return result;
}
public String toString() {
return "Controller(ip=" + this.getIp() + ", port=" + this.getPort() + ", name=" + this.getName() + ", timeout=" + this.getTimeout() + ", provider=" + this.getProvider() + ")";
}
}
DemoApplication.java
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class DemoApplication {
@Autowired
Controller controller;
public static void main(String[] args) {
try (ConfigurableApplicationContext ctx = SpringApplication.run(DemoApplication.class, args)) {
DemoApplication app = ctx.getBean(DemoApplication.class);
app.run(args);
} catch (Exception e) {
e.printStackTrace();
}
}
public void run(String... args) throws Exception {
System.out.println(controller);
}
}
Output:
Controller(ip=127.0.0.1, port=3001, name=TestHsm, timeout=1000, provider=software)
Upvotes: 0
Reputation: 3814
Judging by your package structure, those properties should definitely be loaded. Only possible option is that you have instantiated your Controller
class as new Controller()
instead of letting spring injecting the class (using @Autowired
or constructor injection).
Upvotes: 19
Reputation: 15878
I had the same issue before and @Value was not working for controller but working for component classes so i had used below solution.
You can @Autowire Environment environment
and then environment.getProperty("hsm.provider")
.
Note: This is just a workaround solution.
Upvotes: 0