Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Value is null when loading constructor

Tags:

java

spring

Instead of using Properties inside the constructor I saw @Value annotation should do the trick.

It works in another implementation that I have but here it doesn't

Controller:

@Autowired
private Customer customer;

My Class

@Service
public class Customer {

    /** The soap GW endpoint. */
    @Value("${soapGWEndpoint}")
    private String soapGWEndpoint;

    /** The soap GW app name. */
    @Value("${soapGWApplName}")
    private String soapGWAppName;

    /** The soap GW user. */
    @Value("${generic.user}")
    private String soapGWUser;

    /** The soap GW password. */
    @Value("${generic.user.password}")
    private String soapGWPassword;

    public Customer () {
        // All parameters are null:
        login(soapGWEndpoint, soapGWAppName, soapGWUser, soapGWPassword);
    }
}

But they are on the application.properties file.

Why in this occasion I cannot use @Value?

like image 692
user10867569 Avatar asked Jan 04 '19 13:01

user10867569


3 Answers

Spring won't inject the preoperties' values until the object is fully instantiated (The first thing that Spring will do is call your constructor, since its the default way to create a new object). You should call login() in a @PostConstruct method so Spring calls it automatically after initializing the object:

@Service
public class Customer {

    /** The soap GW endpoint. */
    @Value("${soapGWEndpoint}")
    private String soapGWEndpoint;

    /** The soap GW app name. */
    @Value("${soapGWApplName}")
    private String soapGWAppName;

    /** The soap GW user. */
    @Value("${generic.user}")
    private String soapGWUser;

    /** The soap GW password. */
    @Value("${generic.user.password}")
    private String soapGWPassword;

    public Customer () {
    }

    @PostConstruct
    public void init() {
      login(soapGWEndpoint, soapGWAppName, soapGWUser, soapGWPassword);
    }
}
like image 114
gbandres Avatar answered Oct 10 '22 15:10

gbandres


Another option is to use constructor injection like this

@Service
public class Customer {

  private String soapGWEndpoint;
  private String soapGWAppName;
  private String soapGWUser;
  private String soapGWPassword;

  @Autowired
  public Customer(@Value("${soapGWEndpoint}") String soapGWEndpoint,
                @Value("${soapGWApplName}") String soapGWAppName,
                @Value("${generic.user}") String soapGWUser,
                @Value("${generic.user.password}") String soapGWPassword) {
    this.soapGWEndpoint = soapGWEndpoint;
    this.soapGWAppName = soapGWAppName;
    this.soapGWUser = soapGWUser;
    this.soapGWPassword = soapGWPassword;
    login(soapGWEndpoint, soapGWAppName, soapGWUser, soapGWPassword);
  }
}
like image 37
Ivan Avatar answered Oct 10 '22 14:10

Ivan


You can use @PostConstruct after the object is initialised. Please, have a look into the sample code that I write earlier:

@Configuration
public class BrinkWebserviceConfig {

    private static final Logger LOG = LoggerFactory.getLogger(BrinkWebserviceConfig.class);

    private String accessToken;
    private String locationToken;
    private String domain;

    @Value("${brink.soap.settingsAPI}")
    String BRINK_SETTINGS_API;

    @Value("${brink.soap.sales2API}")
    String BRINK_SALES2_API;

    @Value("${brink.soap.orderingAPI}")
    String BRINK_ORDERING_API;

    @Value("${brink.soap.settings2API}")
    String BRINK_SETTINGS2_API;

    @PostConstruct
    public void init() {
        LOG.info("Loading the access and location tocken for using in the configuration and setting the clients URLs");

        loadCredentialsAndDomainURL();
        loadClientsAPI();
    }

    public ClientInterceptor brinkHeaderInterceptor(Logger LOG) {

        return new ClientInterceptorAdapter() {
            @Override
            public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
                TransportContext context = TransportContextHolder.getTransportContext();
                HttpUrlConnection connection = (HttpUrlConnection) context.getConnection();
                try {
                    connection.addRequestHeader("AccessToken", accessToken);
                    connection.addRequestHeader("LocationToken", locationToken);
                } catch (IOException e) {
                    LOG.error("header interceptor error", e);
                    return false;
                }

                return true;
            }
        };
    }

    private void loadCredentialsAndDomainURL() {

        String s = "src/test/resources/brink.properties";
        Resource r = new FileSystemResource(s);

        Properties props = new Properties();

        try {
            props.load(r.getInputStream());

//            accessToken = props.getProperty("token");
//            locationToken = props.getProperty("appId");

            accessToken = props.getProperty("password");
            locationToken = props.getProperty("username");
            domain = props.getProperty("domain1");

        } catch (IOException e) {
            LOG.error("We have an error for reading the access and location tokens for Brink web-service config");
        }
    }

    private void loadClientsAPI() {

        BRINK_SETTINGS_API = domain + BRINK_SETTINGS_API;
        BRINK_SALES2_API = domain + BRINK_SALES2_API;
        BRINK_ORDERING_API = domain + BRINK_ORDERING_API;
        BRINK_SETTINGS2_API = domain + BRINK_SETTINGS2_API;
    }
}

At the time of calling loadCredentialsAndDomainURL()`` andloadClientsAPI()methods, the object is ready and can read the property values from theapplication.properties``` file.

like image 21
Heisenberg Avatar answered Oct 10 '22 14:10

Heisenberg