My Developer Connection

Knowledge Base for Software Developers

Spring Best Practices


General:

Spring Best Practices:
  1. BeanFactory or ApplicationContext? : Prefer ApplicationContext over BeanFactory. BeanFactory is a simple factory implementation to create and destroy spring beans. ApplicationContext is an advanced beanfactory which supports i18N text message resolution, resource loading and capable to posting events to listener beans. BeanFactory should be preferred when there is limitation on resources and size of the application. Singleton beans are loaded differently in BeanFactory and ApplicationContext. A bean factory lazily loads all beans, deferring bean creation until the getBean() method is called. An application context loads all singleton beans upon context startup. Your application won’t have to wait for them to be created if you are using ApplicationContext.
  2. Non singleton bean :  By default all beans defined in spring are singleton. However you can ask spring to create unique instance of a particular bean setting "singleton" property of the bean to false. Such beans are called prototype. A new instance of a prototype bean will be created each time getBean() is invoked with the bean’s name. Protype beans incur hit on permance during creation. It should be avoided completely or designed carefully if  it uses resources such as database or network connections. They are useful for factory to create new bean instances.
  3. Avoid spring interfaces:  Avoid spring interfaces whenever possible. Spring is a great framework but the greatest advantage of spring is POJOs which makes it vendor independent. Avoid NameAware, BeanFactoryAware, and ApplicationContextAware interfaces.
    Example: To inialize or destroy a bean you can specify init-method and destroy-method in application context. It might be tempting to use Spring's InitializingBean and DisposableBean to avoid specifying these methods and spring takes care of it. Still you don't want to get locked with spring interface unless you want to make your business objects spring dependent.
  4. Inner Beans:  Use Inner beans when you don't want a particular bean to available without its parents bean. Although it doesn't look pleasing to most eyes, it is still worth if you don't want beanfactory to use this bean. example: target for AOP proxy.
  5. Avoid using autowiring : Spring can autowire dependencies through introspection of the bean classes so that you do not have to explicitly specify the bean properties or constructor arguments. Bean properties can be autowired either by property names or matching types. Constructor arguments can be autowired by matching types. You can even specify the autodetect autowiring mode, which lets Spring choose an appropriate mechanism.
    Example :

    <bean id="orderService" class="com.lizjason.spring.OrderService" autowire="byName"/>

    The property names of the OrderService class are used to match a bean instance in the container. Autowiring can potentially save some typing and reduce clutter. However, you should not use it in real-world projects because it sacrifices the explicitness and maintainability of the configurations. It seems like a good idea to make the XML configuration file smaller, but this will actually increase the complexity down the road, especially when you are working on a large project where many beans are defined. Spring is bad is resolving ambiguities. Autowiring byType or byConstructor might result in ambuiguity exception. You should mix autowiring with explicit wiring and never rely completly on autowiring by default. Autowiring byName is more dangerous as bean names might be changed over time, leaving several beans unwired or wired to wrong beans.
  6. Use naming conventions : This is the same philosophy as for Java code. Using clear, descriptive, and consistent name conventions across the project is very helpful for developers to understand the XML configurations. For bean ID, for example, you can follow the Java class field name convention. The bean ID for an instance of OrderServiceDAO would be orderServiceDAO.For large projects, you can add the package name as the prefix of the bean ID.
  7. Import vs ApplicationContext : Like imports in Ant scripts, spring import elements assemble bean definitions.
    Example:

    <beans>
        <import resource="billingServices.xml"/>
        <import resource="shippingServices.xml"/>
        <bean id="orderService" class="com.lizjason.spring.OrderService"/>
    <beans>

    However, instead of pre-assembling them in the XML configurations using imports, it is more flexible to configure them through the ApplicationContext. Using ApplicationContext also makes the XML configurations easy to manage. You can pass an array of bean definitions to the ApplicationContext constructor as follows:
    String[] serviceResources = {"orderServices.xml", "billingServices.xml", "shippingServices.xml"};
    ApplicationContext orderServiceContext = new ClassPathXmlApplicationContext(serviceResources);

    But the later approach sacrifice declarative feature of spring.
  8. Use ids as bean identifiers : You can specify either an id or name as the bean identifier. Using ids will not increase readability, but it can leverage the XML parser to validate the bean references. If ids cannot be used due to XML IDREF constraints, you can use names as the bean identifiers. The issue with XML IDREF constraints is that the id must begin with a letter (or one of a few punctuation characters defined in the XML specification) followed by letters, digits, hyphens, underscores, colons, or full stops. In reality, it is very rare to run into the XML IDREF constraint problem.
  9. Use dependency-check at the development phase : You can set the dependency-check attribute on a bean definition to a value other than the default none, such as simple, objects, or all, so that the container can do the dependency validation for you. It is useful when all of the properties (or certain categories of properties) of a bean must be set explicitly, or via autowiring.

    <bean id="orderService" class="com.lizjason.spring.OrderService" dependency-check="objects">
        <property name="companyName" value="jason"/>
        <constructor-arg ref="orderDAO"/>
    </bean>
    In this example, the container will ensure that properties that are not primitives or collections are set for the orderService bean. It is possible to enable the default dependency check for all of the beans, but this feature is rarely used because there can be beans with properties that don't need to be set.
  10. Use shortcut forms :  The shortcut form is less verbose, since it moves property values and references from child elements into attributes.
    Example:

    <bean id="orderService" class="com.lizjason.spring.OrderService">
        <property name="companyName"><value>lizjason</value></property>
        <constructor-arg><ref bean="orderDAO"></constructor-arg>
    </bean>

    Can be rewritten in the shortcut form as:

    <bean id="orderService" class="com.lizjason.spring.OrderService">
        <property name="companyName"value="lizjason"/>
        <constructor-arg ref="orderDAO"/>
    </bean>

    There is no shortcut form for <ref local="...">. The shortcut form not only saves you some typing, but also makes the XML configuration files less cluttered. It can noticeably improve readability when many beans are defined in a configuration file.
  11. Prefer type over index for constructor argument matching : Spring allows you to use a zero-based index to solve the ambiguity problem when a constructor has more than one arguments of the same type, or value tags are used.
    Example:

    Instead of:
    <bean id="billingService" class="com.lizjason.spring.BillingService">
        <constructor-arg index="0" value="lizjason"/>
        <constructor-arg index="1" value="100"/>
    </bean>
    It is better to use the type attribute like this:
    <bean id="billingService" class="com.lizjason.spring.BillingService">
        <constructor-arg type="java.lang.String" value="lizjason"/>
        <constructor-arg type="int" value="100"/>
    </bean>

    Using index is somewhat less verbose, but it is more error-prone and hard to read compared to using the type attribute. You should only use index when there is an ambiguity problem in the constructor arguments.
  12. Use <null/> for null property :  Use <null/> to initialize any property to null. Although simply leaving property without setting any value defaults to null but the property might be set to some other default value within bean or if you are using auto wiring.
  13. Constructor vs Setter injection : The following table contains some points to consider in each method's favor.
    Constructor injection Setter injection
    Strong dependency contract. Bean cannot be instantiated without being given all of
    its dependencies. Ready to use if all arguement contructor is used. Good for bean with one or two properties.
    Suitable for beans with several properties which makes c'tor injection very lengthy.
    Less code lines as setters could be avoided. Provides flexibility to create  a valid object.
    Facilitates immutable property. Setters are self explaining. Contructor arguement with same type might not be clear.
  14. Autowiring :  Spring is bad is resolving ambiguities. Autowiring byType or byConstructor might result in ambuiguity exception. You should mix autowiring with explicit wiring and never rely completly on autowiring by default. Autowiring byName is more dangerous as bean names might be changed over time, leaving several beans unwired or wired to wrong beans.
  15. Seperate deployment details from application context : Try to seperate deployment details out of application context in other xml or properties file.
    Example :  You can specify datasource details in a property file using Spring's PropertyPlaceHolderConfigurer or through JNDI.
            Property file:  -
            <bean id="propertyConfigurer" class="org.springframework.beans. factory.config.PropertyPlaceholderConfigurer">
                <property name="location"><value>datasource.properties</value></property>
            </bean>
            <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
                <property name="url"><value>${database.url}</value></property>
                <property name="driverClassName"><value>${database.driver}</value></property>
                <property name="username"><value>${database.user}</value></property>
                <property name="password"><value>${database.password}</value></property>
            </bean>
          
            datasource.properties should contain the following entries: -

                                            database.url=jdbc:hsqldb:mydb
                                            database.driver=org.hsqldb.jdbcDriver
                                            database.user=hsql
                                            database.password=password

            Jndi : -
            <bean id="myDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
                <property name="jndiName" value="jdbc/myDataSource" />
            </bean>
  16. Spring AOP or AspectJ AOP? :  Spring provides proxy based aop implementation based on interceptor chains. It is also called dynamic AOP as changes in point cuts or joins doesn't require recompilation. AspectJ works at byte code level and doesn't require any framework once byte code is decorated with AOP capabilities. Here are some pros and cons of spring AOP which will help you to decide, which one to use:
    Pros:
    • Spring AOP doesn't require any special java compiler or special build process. AspectJ requires special compiler.
    • Different advice could be applied to different instance of the same class. This is not possible with AspectJ.
    • Target object is not modified. AspectJ modiefies target object behavior.
    • It is possible to programmatically create proxies.
                Cons:
    • Spring AOP can not be applied to final methods. Spring generates subclass of the target class and weave advuce around overriden method.
    • Spring only supports method joinpoints. AspectJ and JBoss AOP supports field joinpoints as well.
    • Targets are not proxied which means that the method calls on this object is not advised.
  17. Use a narrow window to add advice :  It is recommonded not to use a borader advice when your rquirement could be fulfilled with a more narrow advice.  MethodBeforeAdvice or ThrowsAdvice should be preferred over more generic MethodInterceptor if possible.
  18. Be aware of thread safe issues with AOP advice : Advice instances are most often shared among threads, so we need to consider thread safety issues. For example if the method interceptor is responsible for generating unique id or count, then consider using ThreadLocal variable with synchronized method for incrementing the count. 
    Example:
    public class CountingMethodAdvice implements MethodInterceptor {
        //  The next serial number to be assigned
        private static long nextSerialNum = 0;
       
        private static ThreadLocal serialNum = new ThreadLocal() {
            protected synchronized Object initialValue() {
                return new Long(nextSerialNum++);
            }
        };

        private static long getCount() {
        if(serialNum!=null){
            return ((Long) (serialNum.get())).longValue();
        }
        }
      
        public Object invoke(MethodInvocation methodInvocation) throws Throwable {
    System.out.println("This method is called " + getCount + " times");
        }
    }
  19. Use regular expression advisors to fine tune interceptor scope :  Instead of using broad method point cuts and filtering target methods in interceptor, use more sophisticated and elegant regular expression at the application context level. Spring supports three types of regex method point cuts:
    • org.springframework.aop.support.JdkRegexpMethodPointcut : Java 1.4 regular expression for the fully-qualified method names to match.
    • org.springframework.aop.support.Perl5RegexpMethodPointcut : Perl5 regular expression for the fully-qualified method names to match
    • org.springframework.aop.support.RegexpMethodPointcutAdvisor :  Convenient class for regexp method pointcuts that hold an Advice, making them an Advisor.  By default, JdkRegexpMethodPointcut will be used on JDK 1.4+, falling back to Perl5RegexpMethodPointcut on JDK 1.3 (requiring Jakarta ORO on the classpath).
  20.     Example:
            <bean id="crudInterceptor"  class="com.mycompany.CrudInterceptor"/>
            <bean id="crud"  class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
                <property name="advice">
                    <ref local=" crudInterceptor "/>
                </property>
                <property name="patterns">
                     <value>.*create.*,.*destroy.*,.*get.*,.*update.*</value>
                  </property>
           </bean>
  21. Prefer static pointcut over dynamic point cut : In Spring's book of definitions static point cut refers to a pointcut that can be evaluated when a proxy is created. Criteria for static point cuts can not changed afterwards. Dynamic point cuts depend on runtime information such as arguement values or call stack.Dynamic pointcuts are slower to evaluate than static pointcuts and allow less potential for optimization. It's always necessary to evaluate them on each invocation.
  22. Use autoproxying for large applications :  ProxyFactoryBean works well for small application but it requires more verbose configuration. It allows control over every aspect of  the proxy. Spring ease the use of ProxyFactoryBean by providing dedicated proxies such as TransactionProxyFactoryBean and LocalStatelessSessionProxyFactoryBean. Proxies also saves code duplication in configurations.
    Example:   <bean id="myProxy" class="org.springframework.aop.framework.ProxyFactoryBean" abstract="true">
        <property name="interceptorNames">
            <list>
                <value>interceptor1</value>
                <value>interceptor2</value>
            </list>
        </property>
    </bean>
    <bean id="mybean" parent="myProxy">
        <property name="proxyInterfaces"><value>com.mycompany.mybean</value></property>
        <property name="target">
                <bean class="com.mycompany.MyBeanImpl">
                    <property name="name"><value>Dave</value></property>
                    <property name="description"><value>Good Boy</value></property>
            </bean>
        </property>
    </bean>
    Here number of child bean definitions can "extend" the myProxy definition, specifying a target, usually inner bean. They can optionally add further properties, such as proxy interfaces. Autoproxying means that depending on some configuration, proxying is applied consistently to a number of objects. Autoproxy can be created using BeanNameAutoProxyCreator or DefaultAdvisorAutoProxyCreator. BeanNameAutoProxyCreator is good for replacing several ProxyFactoryBean. DefaultAdvisorAutoProxyCreator is powerful. It examines all advisors defined in current context for mathcing pointcut methods on target object. Both advisor and advices and be used in  BeanNameAutoProxyCreator interceptor list.  DefaultAdvisorAutoProxyCreator strictly requires Advisors. Examples:
    BeanNameAutoProxyCreator :
    <bean id="bnProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
      <property name="beanNames"><value>bean1,mybean*</value></property>
      <property name="interceptorNames">
            <list>
              <value>advisor1</value>
              <value>interceptor1</value>
            </list>
      </property>
    </bean>

    DefaultAdvisorAutoProxyCreator :
    <bean id="daaProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/ > An autoproxy creator bean definition is intended to change the effect of other bean definitions, not for access by application code or other framework objects. Autoproxy can be used to define transactions as well. 15. Specify Transaction Rollback :  By default transactions are rolled back only on runtime exceptions and not on checked exceptions. However it is a good practice to choose specific checked exceptions where you want the transaction to be rolled back based on business needs. Exceptions marked with negative (-) sign cause transaction to be rolled back.
    Example:
    <bean id="businessBean" class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource"><props>
            <prop key="businessMethod1">PROPAGATION_REQUIRES_NEW,ISOLATION_REPEATABLE_READ,-RollBackBusinessException</prop>
        </props>
    </property> </bean>
    You can even mark runtime exceptions as positive to prevent rollbacks but becareful while doing so as it could have adverse affects.
  23. Use bean inheritance to reduce XML :  Using the parent attribute of the <bean> element, you can specify that a bean be a child of some other bean, inheriting the parent bean’s properties.  This helps is reducing XML for specify AOP advice or transaction. Example:
    <bean id="abstractTxDefinition" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" lazy-init="true">
        <property name="transactionManager">
            <ref bean="transactionManager"/>
        </property>
        <property name="transactionAttributeSource">
            <ref bean="attributeSource"/>
        </property>
    </bean>
    <bean id="myService" parent="abstractTxDefinition">
        <property name="target">
            <bean class="com.mycompany.MyServiceImpl">
        </property>
    </bean>

    Note: Auto proxying also helps is reducing xml definitions but auto proxying is not declarative and it is somewhat difficult to identify affected beans.

  24. Scability and Remoting best practices: Please refer to arendsen's presentation on spring remoting and scalability.