简体   繁体   中英

@Value in Springboot returns null

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);
    }
}

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.

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.

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).

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)

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.

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;
    }

}

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.

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

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.

@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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM