Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configure Spring to set system properties 'before' a bean is initialised

In a Spring MVC web application, i have a bean configured in the configuration file as:

<bean class="com.callback.CallbackService"/>

In the service class, the bean is initialised as shown below:

@Autowired
CallbackService service

The CallbackService shown above gets its connection properties by making the following three calls (This cannot be changed for now):

System.getProperty("user");
System.getProperty("password");
System.getProperty("connectionURL");

The service class in which the instance of CallbackService is declared has access to the above three values by reading from the properties file as shown below:

@Value("${user}")
protected String userName;

@Value("${password}")
protected String password;

@Value("${connection}")
protected String connectionString;  

All i need to set the properties for the CallbackService is to set the system properties (after they have been initialised) as shown below:

System.setProperty("user", userName);
System.setProperty("password", password);
System.setProperty("connectionURL", connectionString);

The problem i am having however is the order in which the objects are being initialized. The properties are being initialised but it looks like the System.setProperty calls happen before Spring has ready them from the properties file.

I have tried several solutions but it seems the CallbackService object is instantiated before the values have been read from the properties files and the calls to System.setProperty is called.

The properties file is eventually being read as i can see the values if i access them from one of the @Controller methods. The problem is the point in which the properties are initialised and the CallbackService instance is intantiated.

After several hours googling, i tried the following solutions but none seem to populate the System properties before initialization/Instantiation of the CallbackService instance

  1. Implementing InitiazingBean and setting the system properties within the afterPropertiesSet() method.
  2. Implementing ApplicationListener and setting the system properties within the onApplicationEvent() method.
  3. Setting lazy-init=true for the CallbackService bean definition in the XML.
  4. Setting system properties as described here Set System Property With Spring Configuration File

Point 4 above seems to be what i want but i didn't see any difference when i added the following (with the three properties i need) to my context file.

<bean id="systemPrereqs"
    class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetObject" value="#{@systemProperties}" />
    <property name="targetMethod" value="putAll" />
    <property name="arguments">
        <!-- The new Properties -->
        <util:properties>
            <prop key="java.security.auth.login.config">/super/secret/jaas.conf</prop>
        </util:properties>
    </property>
</bean>

How can i ensure that the values are read from the properties file before the calls to System.setProperty are executed and only then should the CallbackService instance be instantiated?

Thanks

like image 798
ziggy Avatar asked Jan 06 '13 18:01

ziggy


1 Answers

You can let the CallbackService depend on another bean that initializes the system properties, e.g.

 class SystemPropertiesInitializer {

      SystemPropertiesInitializer(@Value("${user}") String userName, 
              @Value("${password}") String password, 
              @Value("${connection}" String connectionString) {

          System.setProperty("user", userName);
          System.setProperty("password", password);
          System.setProperty("connectionURL", connectionString);
      }
 }

Next,

 <bean id="systemPropertiesInitializer" class="com.callback.SystemPropertiesInitializer"/>
 <bean class="com.callback.CallbackService" depends-on="systemPropertiesInitializer"/>

Alternatively, you can use the @DependsOn annotation:

 @Component
 @DependsOn("systemPropertiesInitializer")
 class CallbackService { 
     // implementation omitted
 }
like image 169
matsev Avatar answered Nov 08 '22 05:11

matsev