CL So CL So - 1 month ago 14
Java Question

How to set global config/variable in Spring MVC 4?

I am using Spring MVC 4.1.4

I have some global settings to share in whole application

These setting should only be loaded when start the server

I know I can use context-param

<context-param>
<param-name>configA</param-name>
<param-value>valueA</param-value>
</context-param>
<context-param>
<param-name>configB</param-name>
<param-value>valueB</param-value>
</context-param>


But I want store some complex object, like this

HashMap myConfig = new HashMap();

String[] cfgB={"b1", "b2"};

HashMap<String, String> cfgC=new HashMap<String, String>();
cfgC.put("C1", "1");
cfgC.put("C2", "2");

MyConfigD cfgD = new MyConfigD();

myConfig.put("configA", "A");
myConfig.put("configB",cfgB);
myConfig.put("configC",cfgC);
myConfig.put("configD",cfgD);


context-param is not possible to do that, what else I can use in Java or Spring?

Answer

If you are not restricted and have the flexibility to decide how your properties are set, there are two options.

First is to just define Beans in Java code in an @Configuration class. For most objects, you can have Beans that are @Autowired. All the beans are only loaded at runtime. For Maps (and Lists and such), you define them as beans and then access them with @Resource annotation. Note that you cannot access Maps with @Autowired, Spring uses @Resource for these types.

Contrary to a comment on the other answer, I argue that settings can also be defined in code, just because it is written in XML doesn't make it any different, they are considered equivalent. By writing your config and settings in Java you get the power of OOP which is fantastic when you have complex configurations.

Example Bean declaration:

@Bean
public MyConfig myConfig() {
    final MyConfig myConfig = new MyConfig();
    myConfig.put("configA", "A");
    ...
    return myConfig;
}

@Bean
public Map<String, String> myMap() {
    final Map<String, String> myMap = new HashMap<>();
    myMap.put("A", "a");
    return myMap;
}

Example usage:

@Autowired
private MyConfig myConfig;

@Resource(name = "myMap")
private Map<String, String> myMap;

Second is to use global system properties, defined in a properties file. You can write properties in YAML or a map type config. Details in the link provided. Edit You can namespace your properties and then reference them using @Value annotation. You can have collections in YAML as well.

application.properties

myConfig.configA:A
myConfig.configB:B
myConfig.coll.cA:['a','b','c']
myConfig.coll.cB:{a:A,b:B,c:C}
...

In code

@Value("${myConfig.configA}")
private String configA;