Saturday, July 23, 2011

Java enterprise framework developers' tools

Wanna develop your own framework? Developing your own framework is sure geeky. Fortunately, in Java, doing so is not as difficult as it seems. But, why develop a framework when there are too many of them already available there? Well, firstly its fun, but more importantly, the existing frameworks might not right away give you all you need. In that case, it might be a good idea to at least extend those frameworks to meet your needs.

Please note that there are so many things you can use and my list is definitely not exhaustive. It just gives idea about a few good ones that come bundled with Java SE.

Reflection: Reflection is something that is absolutely essential for developing an enterprise framework. Most framework depend on configuration provided either in the form of XML or recently in the form of Java annotations. With the help of reflection, you can load a class dynamically (by using the name as a String), create its objects, access its properties and invoke its methods. Virtually all available frameworks use reflection.

Loading a class dynamically, creating its objects and calling its methods: An example program equals a thousand words (and I'm too lazy to type a thousand word). Hence, here is an example program.

The code is commented to explain what's going on. The static method forName() in class java.lang.Class returns a reference to a given class. The method getMethod() in class java.lang.Class returns the reference to a method object as specified by the method name and argument list. You can also call getMethod() to get an array of Method objects all defined/declared in the Class or in the predecessors. However, only public methods are returned.

But, what if the class does not have a default constructor (i.e. a no argument constructor)? In that case, we need to get a reference to a Constructor, just like the way we got reference to a Method. The following code example shows it.

Note that the methods in Class class are varargs. That means, they accept a variable number of arguments. In java, internally, those arguments are clubbed together into an array. It is also possible to pass an array of objects instead of the objects being passed separately.

Annotation: Now that we know about reflection, we can start learning annotation. Virtually all enterprise frameworks nowadays, like EJB 3, Spring 3, hibernate 3 (yes its amazing they all have same current major version number) all use annotation for configuration parallel to XML. Whether we should use annotations for configuration is still a burning question - you know, if we do that, we need to recompile our programs every time we change our configurations. However, in practice, there are a lot of configurations that never change in a project (For example, a stateless session bean and a stateful session bean are written completely differently. A stateless session bean does not maintain any instance variables, a stateful bean invariably does that. Hence, a session bean will not overnight change its statefulness, not at least without recompilation anyway. But for a EJB container, its just a matter of configuration). Annotation has a serious advantage over XML configuration that the developer sees the configurations right inside the code, which makes it really easy for him/her to understand.

Again, let us learn by example.

First, let us look at the definition of the annotation ValueList. An annotation is an interface, but not an ordinary interface. It is defined with the keyword @interface, to let the compiler know that we are defining an annotation instead of an interface.

Here we have defined only one method values() that returns an array of Strings. There is a restriction as to what a method in an annotation might return - primitive types, String, Class and single dimensional arrays of them. These methods must also not accept any arguments. In reality, what we are defining here is an attribute called value. What does that mean? Well, keep reading.

There are two annotations on the definition of the annotation. They configure the annotation we are defining. @Retention(RetentionPolicy.RUNTIME) asks the compiler to preserve the annotation in the generated class file. @Target(ElementType.METHOD) specifies that our annotation is only applicable on methods. Runtime annotations may also appear on classes and fields. Let us now check how the annotation is applied in Its simple, just put the @annotation before the method applied on. We are also providing the value for value attribute. Note that value almost looks like a field here. When we will access the value attribute from the annotation through reflection, the values assigned here would be available.

One more word here, the value attribute is the default attribute while using the annotation. Hence the code could also be written @ValueList({"Value1","Value2"}).

The annotation can be accessed through reflection as shown in The reflection classes Class, Method, Field, all have getAnnotation() method which can be used to access a particular annotation. To get all annotations, use getAnnotations().

Dynamic Proxy: Dynamic proxy is a way to dynamically implement a collection of interfaces. The implementation is provided by an instance of and implementation of InvocationHandler. Again, let's see an example.

First let us check the getProxy() method. It simply gets a reference to the interface and then calls the Proxy.newInstance() to create an object of the implementation of the interface. Note that an array of interface is passed. So, multiple interfaces can be passed together. If the classes passed are not interfaces, an IllegalArgumentException is thrown.

An implementation of InvocationHandler (i.e. ValuesInvocationHandler) is also passed as an argument. Every method call to the proxy will be dedicated to this invocation handler's invoke () method. The object the proxy method is called on, is passed as the first argument of the invoke method. The arguments of the proxy method are passed as an array as the last argument of the invoke method. The rest I already explained.

Node the we have achieved a method injection - meaning we have created a method implementation simply by configuration. Where is XML? Although XML is heavily used to create configurations, parsing XML is too vast to fit in here. I may to write an article later.


Anonymous said...

awesome....really a learning experience...keep up sharing ur precise knowledge...ll watch d space fr more....

sekhar said...

hey dude...its really good but big and boring....

Nisha K I said...

hi sekhar....its for techies.....if u understand d technology it cant be boring...keep it up debasish....:)

Namrata said...

really a good article!! keep writing..

Debasish Ray Chawdhuri said...

Thanks for those inspiring comments. :)

TK said...

A True Techie among thousands of mere mortals. Cheers! this blog is going into Dopelist@normalreaction

Post a Comment