2

I am in serious trouble due to a situation. Here's my problem.

PROBLEM: Need to inject a simple static string field /property in an enum class FROM spring config XML. Here's some similar code I tested :

public enum AppProperty {
    NUMBER_OF_ACCOUNTS("accounts"), NUMBER_OF_USERS("users");

    private AppProperty(String cuser) {
        this.current_user = cuser;
    }

    private final String current_user;
    private static final String PROPERTY_FILE = "application.properties";

    static {
        init();
    }

    public static String appContext; // **PROBLEM** : need to populate this ONLY
                                        // from spring config XML via property
                                        // injection.

    public static void init() {

        if (appContext.equals("statement")) {
            // do something..... generate statement et...
        } else {
            // do some other process... generate balance etc
        }
    }

    ..........  few more static methods...
    ..... few more non-static methods
}// end of class

I tried mostly everything for this simple problem but strangely nothing seems working for Spring 3.1 :(

Injecting a property via property setter etc not working at all.. String appContext always turns out NULL... tried ..

 @Autowired(required = true)
   setAppConfig( String context){
AppProperty.appContext = context
)
}

and tried every wiring and autowiring.... mostly either returns null or exception "AppProperties.init() cannot be called as no default constructor ...." (even tried a default constructor for god's sake but don't work...!!!

So thought lets get this single property from a property file and get it done but that also don't work and same problem.

<context:component-scan base-package="com.my.package" /> 
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>classpath:application.properties</value>
        </list>
    </property>
</bean>

and used this in java class over propert .. @Value("${appContext}")

This also demands to instantiate AppProperty.init() which is not achievable by me.

I think the ONLY way to inject a property from config xml seems using MethodInvokingFactoryBean (How to make spring inject value into a static field)

I tried this also but my hard luck it's also not working!!!! Only thing i think I may do wrong is not using the @value tag properly

In config file I used :

<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="staticMethod" value="com.my.package.setAppContext"/>
    <property name="arguments"  value ="testing"/>
</bean>

In java file AppProperty I used

public static  String appContext;
  public void setAppContext(String appContext) {
    AppProperty.appContext = appContext;
    }

Request : Please provide your answer with exact code which I can use as I may be using right solution but Syntex and configuration are missing .. Shall I use @Component over my AppProperty class!! etc... please provide details and get my blessings...

Note: I NEED to Inject this property via Spring Config XML so that I can change the context at runtime.. As I am not allowed to change existing implementation of this class. So please don't suggest to remove enum class with something else... Thanks in advance.

Community
  • 1
  • 1
supernova
  • 3,111
  • 4
  • 33
  • 30
  • Sorry, but you're out of luck, Spring can inject anything **after** creating an instance of the class. Before that, Spring doesn't have that control. What you can do is to hack this field through reflection to inject it with the desired value from Spring (but is so dirty and nasty that you should avoid it). – Luiggi Mendoza Apr 24 '14 at 20:04
  • @LuiggiMendoza Actually I tried that too .. and It worked... What I did was.. In AppProperty class itself I read the property file using InputStream/ Java IO etc... and I was able to read the property... The requirement for my application is to change the behavior of loading this class AT RUNTIME .. – supernova Apr 24 '14 at 20:42
  • but in UAT I have different spring Config file and Production I have another . I wanted to add this property to spring XML so that I can read it from the xml of environment it's deployed. – supernova Apr 24 '14 at 20:43
  • It is a futile requirement, it cannot be done with Spring, use another strategy. Period. – Luiggi Mendoza Apr 24 '14 at 20:43
  • @LuiggiMendoza Nothing is impossible my friend. See my solution below.. tested and it works fine now. Sometime we are bounded to give functionality to existing code... so need to adapt solution according to existing codebase... be it good or bad...just cannot refactor an application to bring solution into a piece of code.... especially when you are a new joiner to the job :) – supernova Apr 28 '14 at 00:04

1 Answers1

2

After no help from SO ..did some some self struggle and found following solution , if it could help somebody:

I realized that Spring Context was getting initialized even before the static block.

So to get the context indirectly , created a class to get the context.

public class SpringBean  {

@Autowired
private  ApplicationContext applicationContext;

private static SpringBean bean = new SpringBean();

public static SpringBean getInstance() {
    return bean;
}


public ApplicationContext getApplicationContext() {
    return applicationContext;
}

public Object getBean(String beanName) {
    if (applicationContext == null) {
        throw new IllegalStateException("No context  initialised.");
    }
    return applicationContext.getBean(beanName);
} 

} 

Note: Same class could be created implimenting ApplicationContextAware interface by SpringBean.

declare this in spring config file as :

  <context:annotation-config/>      
  <bean    class="com.db.icestation.server.pd.common.SpringBean"
    factory-method="getInstance"/>

Also created a String SWITCH variable 'appContext' in spring config , this is the varibale which was my objective to inject in AppProperty class.

   <bean id="appContext" class="java.lang.String"> 
   <constructor-arg value="Atlast..Injecting this string in a static block..."/> 
    </bean> 

Finally.... get this value in your main class "AppProperty" above .....

public static String appContext;    // My problem .. see question above...now resolved

 static{
  appContext = SpringBean.getInstance().getBean("appContext").toString();
  init();
  }
supernova
  • 3,111
  • 4
  • 33
  • 30