Search code examples
springspring-bootinversion-of-control

property value injection into spring beans


i want to know why @Value property injection works on classes with @Service annotation but not on classes with @Bean within @Configuration annotated class.

Works means that the property value is not null.

This value is also injected into two other service which i see during debugging in DefaultListableBeanFactory.doResolveDependency. But i dont see the bean WebserviceEndpoint.

Configuration

@Configuration
public class WebserviceConfig {

   // do some configuration stuff

   @Bean
   public IWebserviceEndpoint webserviceEndpoint() {
      return new WebserviceEndpoint();
   }

}

Webservice interface

@WebService(targetNamespace = "http://de.example/", name = "IWebservice")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public interface IWebserviceEndpoint {
    @WebMethod
    @WebResult(name = "response", targetNamespace = "http://de.example/", partName = "parameters")
    public Response callWebservice(@WebParam(partName = "parameters", name = "request", targetNamespace = "http://de.example/") Request request) throws RequestFault;
}

Webservice class

public class WebserviceEndpoint implements IWebserviceEndpoint {

   @Value("${value.from.property}")
   private String propertyValue;

}

application.yml

value:
 from:
  property: property-value

When does the injection of @Value happen in this case.


Solution

  • Basically propertyValue is null because Spring injects value after bean's creation. So when you do:

    @Bean
    public IWebserviceEndpoint webserviceEndpoint() {
      return new WebserviceEndpoint();
    }
    

    Spring creates a new instance with propertyValue=null. You can initialize your instance attribue with @ConfigurationProperties

    @Bean
    @ConfigurationProperties(prefix=...)
    public IWebserviceEndpoint webserviceEndpoint() {
       return new WebserviceEndpoint();
    }
    

    Note that propertyValue should have a setter.

    You have several ways to solve this problem, usually it's good to centralize properties in one utils class.

    @Component
    public class Configs {
      @Value("${propery}"
      String property;
    
      String getProperty(){ 
        return property;
      }
    }
    

    And then:

    @Bean
    @ConfigurationProperties(prefix=...)
    public IWebserviceEndpoint webserviceEndpoint() {
        WebserviceEndpoint we = new WebserviceEndpoint();
        we.setProperty(configs.getProperty())
       return we;
    }
    

    Again there are many many different ways to solve this problem