10

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?

CL So
  • 3,647
  • 10
  • 51
  • 95

2 Answers2

11

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;
Community
  • 1
  • 1
tinker
  • 1,396
  • 11
  • 20
1

You can just declare your maps with <util:map> in the applicationContext.xml.

Scope should be singleton

Type/class may be java.util.HashMap

You can then @Autowired that bean in your components.

<util:map id="utilmap" map-class="java.util.HashMap">
    <entry key="key1" value="value1"/>
    <entry key="key2" value="value2"/>
</util:map>
Stefaan Neyts
  • 2,054
  • 1
  • 16
  • 25
  • you can use listener for the same – Programmer Mar 21 '15 at 20:50
  • Is there any non xml soluation? – CL So Mar 21 '15 at 22:03
  • U can hard code them in a @Component annotated class. But then you can't consider it as settings any more, then it is part of your application. – Stefaan Neyts Mar 21 '15 at 22:23
  • This doesn't answer the whole question or even the main part about the complex objects. And settings can definitely be in code, it's considered equivalent, just because it is XML doesn't make it special/different. Even in XML it is "hard-coded" so how is it any different?! The whole reason they introduced it, and that it is becoming the preferred config style in most new apps, is that OOP is extremely useful for large complex configurations which can become verbose and unmanageable in XML. – tinker Mar 21 '15 at 22:50