Spring


From Ben Northrop, Consultant

What could be simpler than property files? In an enterprise application, it turns out, many things! In this post I’ll take a look at a few subtle complexities to managing properties in an enterprise Java Spring application, and hopefully demonstrate how a little fore-thought in design can yield big savings in terms of time, confusion, bugs, and gray hair down the road.

Types of Properties

Before designing an approach to managing property files, it’s critical first to understand the types of properties are to be managed. Here are four characteristics to consider:

  • Are some properties environment specific – in other words, do they have a different value in one environment than another? For example, a database connection string would differ in the TEST environment than it would the PROD environment.
  • Do any properties contain sensitive information, like passwords or credentials, that can’t sit in plain text in the deployment unit (e.g. WAR, EAR)?
  • Do any properties need to be located external from the deployment unit (e.g. on the file system rather than in the WAR, perhaps to be managed by a systems administrator)?
  • Should properties be dynamic, in the sense that they can be updated at runtime (i.e. without requiring a restart of the application)?
  • Each of these special characteristics adds a degree of complexity to applications – necessitating additional infrastructure beyond the simple Java Properties class.

    Spring’s PropertyPlaceholderConfigurer

    Fortunately for us, the Spring framework, with the PropertyPlaceholderConfigurer and PropertyOverrideConfigurer, provides the features and hooks we need to manage these cases (with the exception “dynamic” properties). And true to its philosophy, Spring makes simple things simple, and complicated things possible.

    The PropertyPlaceholderConfigurer allows properties to be pulled in to the application context file. For example, in the simplest case, a property “db.user” defined in database.properties could be pulled into the ${db.user} placeholder:

    <bean id="propertyPlaceholderConfigurer"
    class="edu.cmu.s3.core.service.resource.PropertyPlaceholderConfigurer">
      <property name="locations">
        <list>
          <value>classpath:database.properties</value>
        </list>
      </property>
    </bean>
    
    <bean id="dataSource">
      <property name="user" value="${db.user}"/>
      <property name="password" value="${db.password}"/>
      ...
    </bean>
    

    The PropertyOverrideConfigurer works in the opposite way, pushing properties from property files into properties in the context file (without having to specifically define a place holder – e.g. ${db.user}). These are both well documented in the Spring API and documentation.

    Tips

    Given the different possible types of properties, and Spring’s property framework, here are a few tips for managing them:

    1) Consider using a JVM System property that sets the environment of the machine (e.g. “my.env=TEST”), telling the configurer which property file to use. For example:

      <context:property-placeholder location="classpath:db-${my.env}.properties"/>
    

    If the “my.env” property was set to “TEST”, then obviously the PropertyPlacementConfigurer would look for a file called “db-TEST.properties”. For Tomcat, this property can be set in the admin console or defined in a startup script (e.g. “-Dmy.env=TEST”) – neither of which is very elegant. Alternatively, it is possible to use JNDI with Tomcat, defining “my.env” in the server.xml and the context.xml of the web app. (Note, there are of course many other ways to solve this environment-specific problem, but this is an easy and relatively straight-forward one.)

    2) It may be necessary to set the ignoreUnresolvablePlaceholders to true for any PropertyPlaceholderConfigurer, which will ensure that a configurer won’t fail if it can’t find a property. Why would this be a good thing? Oftentimes, one context file will import other context files, and each may have their own configurer. If ignoreUnresolvablePlaceholders is set to false (the default), then one configure would fail if it couldn’t find the property, even if another configurer down-stream could find it (see good explanation here). Beware, however, since this will suppress warnings for legitimate missing properties, making for some tough-to-debug configuration problems.

    3) To encrypt properties, subclass the PropertyPlacementConfigurer and override the convertPropertyValue() method. For example:

    protected String convertPropertyValue(String strVal) {
      //if strVal starts with “!!” then return EncryptUtil.decrypt(strVal)
      // else return strVal
    }
    

    4) Consider using the systemPropertiesMode property of the configurer to override properties defined in property files with System properties. For one-off environment specific properties this can be a helpful solution, however, for defining many properties, this configuration can be cumbersone.

    5) For properties that need to be managed outside of the WAR, consider using a System property to define where the file is located. For example, the property ${ext.prop.dir} could define some default directory on the file system where external property files are kept:

    <context:property-placeholder location="file:///${ext.prop.dir}db.properties"/>
    

    This entails, however, that this property is set for any process that leverages the Spring container (e.g. add the param to the Run Configuration for integration/unit tests, etc.), otherwise the file would not be found. This can be a pain. To circumvent, the configurer can be overridden – changing the behavior such that it looks to the external directory only if the System property is set, otherwise it pulls from the classpath.

    6) Beware of redundancy of environment-specific properties. For example, if the solution is to have one property file for each environment (e.g. “db-test.properties”, “db-dev.properties”, etc.), then maintaining these properties can be a bit of a nightmare – if a property “foo” is added, then it would have to be added to the property file for each environment (e.g. DEV, TEST, PROD, etc.). The PropertyOverrideConfigurer is appropriate to eliminate this redundancy, setting the default value in the application context itself, but then the overriding value in a separate file. It’s important, however, to document this well, since it can look a bit “magical” to an unsuspecting maintenance developer who sees one value specified in the context file, but another used at runtime.

    Conclusion

    Managing properties for an enterprise application is a little trickier than one might expect. With Spring’s property configurers, however, the toughest part is just knowing what you need – the rest comes out of the box, or with some minor extensions.

Advertisements

Have some option configure to get Data sources.

1. Data sources are defined by JDBC driver:

<bean id=”dataSource” class=”DriverManagerDataSource”>
<property name=”driverClassName” value=”jdbcDriver” />
<property name=”url” value=”url” />
<property name=”username” value=”user” />
<property name=”password” value=”pass” />
</bean>

Use DriverManagerDataSource class.

Returns a new connection every time that a connection is requested.

2. Data sources are gotten from pool connections:

– Data sources are looked up by JDNI.

Before use it .You have to register an AutowiredAnnotationBeanPostProcessor instance in the IOC container.

-Have two way to register:

1. <context:annotation-config>

2. <bean class=”org.springframework.beans

.factory.annotation.AutowiredAnnotationBeanPostProcessor” />

Different  between @Autowired and @Resource:

– @Autowired wires by Type and specified by Spring . If you want to use wires by Name . Add @Qualifier.

-@Resource wires by Name and specified by Java

Spring provides two type of Spring IOC container : BeanFactory and ApplicationContext.

Bean Factory

  • Bean instantiation/wiring

Application Context

  • Bean instantiation/wiring
  • Automatic BeanPostProcessor registration
  • Automatic BeanFactoryPostProcessor registration
  • Convenient MessageSource access (for i18n)
  • ApplicationEvent publication

Before (Spring 2.0 and earlier):

<bean id="propertyConfigurer">
 <property name="location">
  <value>file:${user.home}/env.properties</value>
 </property>
</bean>

After (Spring 2.5):

1.Loading 1 property file:

<context:property-placeholder location=”file:${user.home}/env.properties”/>

2.Loading multiple properties files:

<bean class=”org.springframework.beans.factory.config.PropertyPlaceholderConfigurer”>

<property name=”locations”>

<list>
<value>classpath:file1</value>
<value>classpath:file2</value>
</list>

</property>

</bean>

*Other property:

-ignoreResourceNotFound

-ignoreUnresolvablePlaceholders

Spring application context loading tricks
By Ben, on May 13th, 2008
The Spring classpath:-notation

As most of you probably know, the Spring Framework can load all sorts of resources into its application context from all sorts of sources. Especially it can do this from the classpath and the people over at SpringSource have even introduced their own URI “protocol” to make this easy: you can identify resources using the classpath-URIs, like so:

classpath:

Most of you are probably familiar with this notation, because it is often used when loading the application context files themselves using the ContextLoaderListener.

What many people don’t realize, is that the classpath:-notation is far more versatile than just for use as a standard URI, because you can use wildcards. In fact I only recently learned this myself from a colleague (at least in part) — which is kind of dumb, because it’s mentioned quite clearly in the documentation.

The first thing you can do above and beyond loading resources by their full path (relative to the classpath) is use all the Ant-style wildcards. So instead of loading as follows:

contextConfigLocation

classpath:businessContext.xml
classpath:persistenceContext.xml
classpath:webFlowBeansContext.xml
classpath:etc.

you can simply load as follows:

contextConfigLocation

classpath:*Context.xml

or, as the case may be:

contextConfigLocation

classpath:**/*Context.xml

There is a catch to this strategy, however: if you have multiple resource repositories (directories, databases, online resources, whatever) on your classpath containing files that match your wildcard pattern, Spring will only look for matching resources in one of these locations. To illustrate this for yourself, try using maven to create a standard project structure, then put a context file in src/main/resources and src/test/resources and try to load both at the same time with a wildcard — you’ll only get one.

The classpath*:-notation

Of course the Spring guys wouldn’t be the Spring guys if they didn’t have a simple solution for this problem. It’s called the classpath*:-notation. Simply put, if you rewrite the snippet from above like so:

contextConfigLocation

classpath*:**/*Context.xml

then Spring will load every matching context file from the entire classpath.

As the documentation points out, the combination of the classpath*:-notation with Ant-style wildcards makes it possible to organize your application into a neat component-assembly style: you can put all the code for each individual problem from your problem domain into its own component (a jar, say) and then “slot” as many jars into place as you like to make your application. You can even add components later on without making major adjustments to any other component (if you think about it carefully). Just make sure each component has an application context file that follows the general naming schema. Think of the possibilities if you include OSGi or even the new Service Provider spec.

Caveat emptor

There is a very specific sort of naming pattern that you can also create using the classpath*:-notation. This is the naming pattern whereby all application context files within the application have exactly the same name (e.g. classpath*:myAppContext.xml). This pattern allows you to expand your context completely transparently to all others without even having to think very hard about the naming convention.

DO NOT EVER, EVER, EVER, EVER, EVER, EVER, EVER, EVER, EVER, EVER, EVER, EVER DO THIS!!!

If you give all your context files the same name, you lose precise control over what gets loaded and what doesn’t. This can hurt if you create components that you want to reuse across applications (especially if you are using Maven and have transitive dependenciesto deal with) and it can hurt in creating integration tests that involve partially loaded contexts. It also makes it harder to find naming conflicts in your contexts if you introduce them accidentally (especially if you are not the only developer on your project). Always make sure each context file on the classpath has a unique name!
Conclusion

The Spring Framework includes a very flexible notation for loading resources from the classpath, using wildcards to identify resources. This notation, if used correctly, gives you considerable freedom in creating component-assembly style applications. However, you must still guard against using unwise naming of your context files.

Next Page »