Friday, November 30, 2007

Spring 2.5 - Too much auto-wired?

Concept to auto-wire relationships among spring enabled beans has always been there. The idea with auto-wiring is to get away from the tedious task of specifying and more importantly maintaining explicit wiring. Originally it was supported to be done by name, by type, by constructors or auto-detect and then you had the option to auto-wire all or specific beans within a context. But now with Spring 2.5 the auto wiring concept has taken a whole new meaning and so is the debate if we really want to do auto-wiring. Spring 2.5 has a new @Autowire annotation. @Autowire annotation let us do much fine grained auto-wiring then was possible before and also it make us much more explicit then was possible in pre Spring 2.5 times Lets consider few examples #1

@Autowired
public void init(AccountDao accountDao, CustomerDao customerDao) {
   this.accountDao = accountDao;
   this.customerDao = customerDao;
}
Do not need to have setters with one parameter to inject dependencies, any method with any name and any number of parameters will do. Can be applied to fields and constructors as well and obviously to the favorite setters :) #2
@Autowired
private BaseDao[] daos;
or
@Autowired
private Set daos;
Create an array or collection with all the possible beans available in the context.. #3
@Autowired(required=false)
private AccountDao accountDao = new AccountDao();
Find it do it, if not leave it. Moving on we can even fine control this by using another annotation @Qualifier. Again lets see some more examples #4
@Autowired
@Qualifier("bankService")
private BankService bkService;
We are doing by-name auto-wiring by providing a bean name within the annotation. This might help by letting you declare the name of the property different from the name of the bean. #5 – Example of custom qualifier annotations to take care of the case when we have more then one implementation which we want to auto-wire Define an annotation like this
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Category {
   String value();
}
Custom qualifier on autowired fields can be applied like this
public class BookList {
   @Autowired
   @Category("Technical")
   private Book technicalBook;

   @Autowired
   @Category("Management")
   private Book managementBook;

}
and then do the bean definitions like this
<bean name="book" class="example.Book">
    <qualifier type="Category" value="Technical"/>
    <!-- This implementation specific properties -->
</bean>
<bean name="book" class="example.Book">
    <qualifier type="Category" value="Management"/>
    <!-- This implementation specific properties -->
</bean>
And if this is not enough we can always create a custom auto-wire configurer or may be use the new @Resource annotation for further auto-wiring stuff. That is that for auto-wiring but Spring 2.5 introduces a concept of auto-detection of spring components on the classpath where we do not have to even define the beans (with the name and bean class) in the context. Spring does a component scanning on the classpath (which can be configured using filters) by detecting classes which are stereotyped and then registering them as spring enabled beans. Yes it provides a lot of flexibility and a much greater control as can be seen from all of the above examples but still I feel it should be done with a lot of caution and I-am-going-to-be-consistent attitude.

Sunday, November 18, 2007

Controlling Classloading with Spring

The Spring Framework provides tons of functionality for someone wanting to use dependency injection; so much so that it can be difficult to know everything you can do.

Many times when dealing with a framework or a web application, it becomes important to track down JAR files and class files at runtime, and load them, often times in their own ClassLoader object.

Just to remind everyone out there, classes loaded in one ClassLoader are not visible to a parent or sibling ClassLoader (unless you are using some nightmare ClassLoader object that breaks the hierarchical semantics of core Java classloading).

ClassLoaderA
| (ClassA, ClassB, ClassC)
|
|__ ClassLoaderB (Child of A)
|   (ClassD, ClassE)
|
|__ ClassLoaderC (Child of A)
   (ClassF, ClassG)

Using this diagram as an example, ClassLoaderB can see ClassA, ClassB, ClassC, ClassD, and ClassE, but it cannot see ClassF or ClassG. Likewise, ClassLoaderC cannot see the classes loaded by ClassLoaderB. And finally, ClassLoaderA can only see it's own classes.

Thankfully, objects loaded by child/sibling classloaders can be dealt with in classes loaded by parent/peer classloaders (this can be seen when you put one of your objects in to an ArrayList object - the ArrayList may not be able to reference your class, but it can still deal with the objects inside of that class.

Considering the above, what if we want to use a Spring XMLBeanFactory object (created by ClassLoaderA) to load a bean definition in an XML file that is referring to ClassD which is inside ClassLoaderB?

Thankfully, it is a fairly simple process; it simply involves understanding the two pieces at work. We have:

  1. A Bean Definition Reader - This is the object that reads the bean definition from the source (redundant, aren't I?); in other words, in this case this is the XML parser and magical finder of Class objects when you type ....
  2. A Bean Factory - This is the implementation of the factory that handles the construction of beans after they have been defined by the reader. This is the stage in the process where AOP, autowiring, property setting, singletons, prototypes, etc is all plugged in.
So now, being infinitely more educated on the Spring bean factories, it is just a short hop to plugging in the correct class loader ClassLoaderB for the task at hand.

The BeanDefinitionReader is where classes are found when Spring is parsing/interpreting a bean definition source (such as a bean XML file). There is a method on the interface - BeanDefinitionReader.getBeanClassLoader() that provides the correct class loader to the BeanFactory (this defaults to Thread.currentThread().getContextClassLoader()). There is also a method on the abstract base implementation - AbstractBeanDefinitionReader.setBeanClassLoader(ClassLoader) so we can set our class loader to the correct implementation.

'But wait R.J.!', you say - 'There is no BeanDefinitionReader that I can see on the XmlBeanFactory class - you're a liar! I'm never reading Coffee-Bytes again!'. Don't pull away from me yet! While it is true that the XmlBeanFactory class doesn't provide visibility to the bean definition reader, that doesn't mean it's not there! In reality, the XmlBeanFactory is just a convenience implementation of two seperate objects:

XmlBeanFactory factory = new XmlBeanFactory([xml resource here!]);
// == to
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader();
DefaultListableBeanFactory factory = new DefaultListableBeanFactory(reader);
reader.loadBeanDefinitions([xml resource here!]);

Do I think it is frustrating that you can't get to the bean definition reader without forgoing the XmlBeanFactory class for it's super class? Absolutely! Do I have commit rights to Spring? Unfortunately for them, no (hint, hint). So, that's that... oh, you still don't feel that sweet cut/paste solution beckoning to you? Am I leaving you patient readers hanging without a clean solution to your problems? Ok, ok...

XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader();
reader.setBeanClassLoader([Class LoaderB here!]);
DefaultListableBeanFactory factory = new DefaultListableBeanFactory(reader);
reader.loadBeanDefinitions([xml resource here!]);

Thursday, November 15, 2007

Runtime Exception in Spring

Spring does throw runtime exceptions instead of checked exceptions. Runtime exceptions must not be catched and if they happen and if they are not catched your application will stop running with a standard java stack trace. Checked exceptions must be catched. If you do not catch a checked exception in your code, it can not be compiled. As it is a tedious task to catch all the exceptions for example when using EJB technology and there are bad developers catching exceptions without giving any feedback to the user, the Spring developers decided to throw runtime exceptions, so that if you do not catch an exceptions your application will break and the user gets the application exception. Their second reasoning is that most exceptions are unrecoverable so your application logic can not deal with them anyway. This is true to some extend but in my opinion at least the user should not see a Java stack trace from an exception when using the application. Even if they are right and most exceptions are unrecoverable, I must catch them at least in the highest level (dialogues) of my application, if I do not want a user to see a Java Exception stack trace. The problem is that all IDEs recognizes checked exceptions and tell me that I must still for example catch a DataBaseNotAvailable exception and a doubleEntryForPrimaryKey exception. But in this case I can decide that the user application will stop for the first exception and will continue to the edit dialogue for the second exception to allow the user to input a different value for the primary key. Eclipse even creates the try catch method for me. Using RuntimeExceptions I must know which exception can happen and write my code manually. I do not know if I catched all the important runtime exceptions where I could allow the application to continue running. And this is what I really dislike about this strategy. But anyway, I came across a lot of very nice design patterns in Spring and it will help even mediocre developers as me ;- ) to write nice code.