Spring Framework: Best Programming Practices Part 2

 

This is the second part of Spring Best Practices series as per Best practices introduction post. This second part is also related with the best practices when using Spring’s Core classes and other utilities. You can refer the other four posts through this links… Part 1, Part 3, Part 4 and Part 5. I am expecting the corrections (if any)as well as the new best ways from my readers.

  • Configuring Spring Application context for different locations:

If the configuration is the same for all the environments except for the developer’s machine, then make (a) separate configuration file(s) with the configuration that is different. Let this different configuration overwrite the definition(s) in the original file(s).Make sure this different configuration will never be placed in the other environments!!!Example of how to achieve this if you use the org.springframework.context.support.ClassPathXmlApplicationContext:Note: I give every example file below a unique name, so I can easily refer to it.Contents of beanRefContext.xml

   1: <beans>
   2:     <bean id=”aBeanId”class=”org.springframework.context.support.ClassPathXmlApplicationContext”>
   3:         <constructor-arg>
   4:             <list>
   5:                 <value>
   6:                     /spring/applicationContext-forAllTheEnvironments.xml    
   7:                 </value>
   8:                 <value>
   9:                    /spring/applicationContext-local.xml
  10:                 </value>
  11:             </list>
  12:         </constructor-arg>
  13:         <constructor-arg>
  14:             <ref bean=”frameworkApplicationContextId”/>
  15:         </constructor-arg>
  16:     </bean>
  17: </beans>

Beans defined in the config locations (first constructor-arg) overwrite the beans in the parent application context (second constructor-arg).Quote from the JavaDoc of this class “In case of multiple config locations, later bean definitions will override ones defined in earlier loaded files. This can be leveraged to deliberately override certain bean definitions via an extra XML file.

  • 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.

  • 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).Example:

   1: <bean id=”crudInterceptor” class=”com.mycompany.CrudInterceptor”/>
   2:  
   3: <bean id=”crud”class=”org.springframework.aop.support.RegexpMethodPointcutAdvisor”>
   4:     <property name=”advice”>
   5:         <ref local=” crudInterceptor “/>
   6:     </property>
   7:     <property name=”patterns”>
   8:         <value>
   9:             .*create.*,.*destroy.*,.*get.*,.*update.*
  10:         </value>
  11:     </property>
  12: </bean>

  • 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

   1: <bean id=”myProxy” class=”org.springframework.aop.framework.ProxyFactoryBean” abstract=”true”>
   2:     <property name=”interceptorNames”>
   3:         <list>
   4:             <value>interceptor1</value>
   5:             <value>interceptor2</value>
   6:         </list>
   7:     </property>
   8: </bean>
   9:  
  10: <bean id=”mybean” parent=”myProxy”>
  11:     <property name=”proxyInterfaces”>
  12:         <value>com.mycompany.mybean</value>
  13:     </property>
  14:     <property name=”target”>
  15:         <bean class=”com.mycompany.MyBeanImpl”>
  16:             <property name=”name”>
  17:                 <value>Dave</value>
  18:             </property>
  19:             <property name=”description”>
  20:                 <value>Good Boy</value>
  21:             </property>
  22:         </bean>
  23:     </property>
  24: </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 :

   1: <bean id=”bnProxyCreator” class=”org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator”>
   2:     <property name=”beanNames”>
   3:         <value>bean1,mybean*</value>
   4:     </property>
   5:     <property name=”interceptorNames”>
   6:         <list>
   7:             <value>advisor1</value>
   8:             <value>interceptor1</value>
   9:         </list>
  10:     </property>
  11: </bean>

DefaultAdvisorAutoProxyCreator :

   1: <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:

   1: <bean id=”businessBean” class=”org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource”>
   2:     <property>
   3:         <props>
   4:             <prop key=”businessMethod1″>
   5:                 PROPAGATION_REQUIRES_NEW,ISOLATION_REPEATABLE_READ,-RollBackBusinessException
   6:             </prop>
   7:         </props>
   8:     </property>
   9: </bean>

You can even mark runtime exceptions as positive to prevent rollbacks but be careful while doing so as it could have adverse affects.

  • 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:

   1: public class CountingMethodAdvice implements MethodInterceptor {
   2:  
   3:     // The next serial number to be assigned
   4:     private static long nextSerialNum = 0;
   5:  
   6:     private static ThreadLocal serialNum = new ThreadLocal() {
   7:         protected synchronized Object initialValue() {
   8:             return new Long(nextSerialNum++);
   9:         }
  10:     };
  11:     
  12:     private static long getCount() {
  13:         if(serialNum!=null){
  14:             return ((Long) (serialNum.get())).longValue();
  15:         }
  16:     }
  17:     public Object invoke(MethodInvocation methodInvocation) throws Throwable {
  18:         System.out.println(”This method is called ” + getCount + ” times”);
  19:     }
  20: }

Technorati Tags: , ,

9 thoughts on “Spring Framework: Best Programming Practices Part 2

  1. Hello,
    I am new to Spring, and would like to use it in my existing application. I am still in the process of understanding the concepts, but I have a doubt which hopefully you could help me clarify.
    All the examples I have seen, the parameters are hard-coded in the xml file. How do we pass values to get the correct object with the run time parameters?
    For example
    APIServer: Abstract class
    BalanceServer extends APIServer : Abstract class
    ClientBalanceServer extends BalanceServer

    In normal scenario:
    I would have a factory to get the correct BalanceServer based on client ID

    How can I achieve the same using Spring?

    Thank you in advance
    Sarvesh

  2. Your XML and Java code looks a little rough – I think it would be really nice if WordPress came with a built in code rendering option! I find that preformatted + quote works pretty well.

    We are building a web service incorporating Axis2, Spring and Hibernate, hunting around for some best practises for this.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: