Saturday 26 February 2011

AOP demystified

How often do you hear the acronym AOP? Aspect-oriented programming - aspects are quite a buzzword in the world of software development these days. I gave AOP a quick spin using the Spring framework in Java. According to the Spring framework reference documentation of AOP (http://static.springsource.org/spring/docs/2.5.x/reference/aop.html), "Aspects enable the modularization of concerns such as transaction management that cut across multiple types and objects." I'll show you just how easy implementing AOP can be by presenting a very minimalist example Spring-based Java application. By the end of this blog post, if you read it carefully, you should have a clear idea how you could benefit from AOP, what are the different ways of implementing aspects in your applications and, no doubts, you will feel a certain hype about this. You'll probably want to chuck some AOP into your next piece of development just because it's "so cool" :-)

 

The sample application

The sample application is, as I mentioned earlier, minimalist and completely fictitious. I removed all extra stuff from the application on purpose, just to make sure it does not contain more than is absolutely necessary.

Note there are only three referenced libraries (jars) - spring, it's commons-logging dependency, and aspectjweaver.

package main.abstractions;

public interface Greeter {
    void greet();
}

The interface above is as simple as it gets - one method, no parameters, no return value, so we focus on demystifying AOP. This is the only interface in our tiny system. We have two different implementations of this interface, as follow:

package main.implementations;

import main.abstractions.Greeter;

public class PoliteGreeter implements Greeter {

    @Override
    public void greet() {
      System.out.println("Good afternoon!");
    }
}

...what a nice chap. We have also another implementation of a Greeter:

package main.implementations;

import main.abstractions.Greeter;

public class NaughtyGreeter implements Greeter {

    @Override
    public void greet() {
      System.out.println("Leave me alone!");
    }

}

Below comes the Main class, with the entry point - public static void main method.

package main;

import main.abstractions.Greeter;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

    private Greeter[] greeters;

    public void setGreeters(Greeter[] greeters) {
      this.greeters = greeters;
    }

    private void run() {
      for (Greeter greeter : greeters) {
        greeter.greet();
      }
    }
    
    public static void main(String[] args) {
      ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
      ((Main) context.getBean("main")).run();
    }  

}

What's missing is the Spring XML wiring, as I chose to demonstrate how you could implement cross-cutting aspects of your application with the Spring framework, without touching your existing code. All the magic will be performed by Spring and we'll orchestrate the whole symphony from XML. There are other alternatives and many find those much more convenient. However I just wanted to present a simple example and we can discuss the alternatives in later sections of this blog entry.

I decided to separate the AOP-related mark-up into an XML file of its own, so we'll have two XMLs instead of just one, but that's only to show you how you can easily manage your spring contexts without ending up maintaining a huge pile of convoluted mark-up. The basic application context is in this file, note that the first element inside the beans element is an "import", that's how we can link more Spring context files together.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">

 <import resource="aop.xml" />

 <bean id="politeGreeter" class="main.implementations.PoliteGreeter" />
 <bean id="naughtyGreeter" class="main.implementations.NaughtyGreeter" /> 

 <bean id="main" class="main.Main">
  <property name="greeters">
   <list>
    <ref bean="politeGreeter" />
    <ref bean="naughtyGreeter" />
   </list>
  </property>
 </bean>
</beans>

As you can see, half of the mark-up is boilerplate XML stuff and fluff. We define a polite greeter bean and a naughty greeter bean, then we'll declare that the main bean will need these two above-mentioned beans injected into its greeters property, which is an array of Greeter, so we define it as a list element, Spring can do the magic of dependency injection.

 

The Advisor enters the scene

So far no huge surprises. A ridiculously simple application. Now, the really interesting bits come in the next piece of XML, and in the Java code fragment in the next section.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">

 <!-- no id - will never be referred to directly. The Spring container will recognise it as a BeanPostProcessor -->
 <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />

 <bean id="greeterAdvice" class="main.advices.GreeterAdvice" />

 <bean id="greeterAdvisor" class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor">
  <property name="advice" ref="greeterAdvice"></property>
  <property name="expression" value="execution(* *.greet(..))" />
 </bean>

</beans>

Surprisingly, the aop.xml file does not contain tons of mark-up. We simply stated that there is an advice for the application lurking somewhere in our code base (the last bits of Java code that will be listed in this post). And we also indicated that there exists an advisor bean that we would like the Spring container take into consideration. This single bean is probably the most interesting, as it contains not only a reference to the advice being applied to our application execution (the "what" and the "when" of the aspect we're implementing), but also the places "where" we would like the Spring container to interfere with our application's execution, intercept the access to particular join points and enable us to perform the cross-cutting trickery we have in mind :-)

There is also one other exciting line of mark-up, which is post processor bean that will enable auto-proxying of our target classes, but more on that a bit further down this post. I aim to demystify the scary terms, and so demystify I will! But hang on...

 

Glossary of terms in AOP

Now, I have thrown quite a bit of jargon into the mix, which is not what I like to do, but what is important to do in this case. There are certain terms in the area of AOP that you will need to familiarise yourself with, so next comes a brief glossary:
Aspect
The merger of advice and pointcuts. All information about where, when and what job is to be done.
Advice
The job of an aspect. Defines the what and when of an aspect.
Pointcut
Pointcuts help narrow down the joinpoints advised by an aspect. Define the where of an aspect.
Joinpoint
A point in the execution of an application where an aspect can be plugged in. All the opportunities for advice to be applied.
Introduction
Allows us to add new methods and attributes to existing classes without having to change them.
Target
Object being advised.
Proxy
The object created after applying advice to the target object. To the client making use of the target object the proxy looks the same.
Weaving
Process of applying aspects to a target object to create a new, proxied object.

 

An AOP Advice demystified

Here is the last piece of code I mentioned before on several occasions:

package main.advices;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;

public class GreeterAdvice implements MethodBeforeAdvice, AfterReturningAdvice {

    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
      System.out.printf("%s is about to greet you: \n>>>", target.getClass().getSimpleName());
    }

    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
      System.out.println("DONE");
    }

}

Wow, that wasn't that huge, was it? I mean, it really isn't that very mind-boggling piece of code. We basically just implement the what and the when of an aspect. As to "what", the code inside the individual methods is the "what". It's the extra bits of logic to be tacked onto your application's logic in a cross-cutting manner. The "when" of this aspect is the actual methods you used in order to implement the advice. You could have used a before / after / on exception / after (finally) / or an "around advice". In our particular example, we used only the before (something happens in our application) and the after. In a different setup you could perhaps be interested in reacting to exceptions thrown.

Say, maybe you would like to log every exception thrown within your system (or just a particular kind of exception within a particular layer of your system) in a special error log. A bit of code into the right place in your Advice class, and a tiny bit of XML mark-up is all you need to do. Can you feel the power of AOP yet? And how relatively simple that could be. The extra complexity added, once you have overcome the initial shock and swallowed all the definitions and the concepts introduced by using Spring as application framework, you'll be able to do great things by a wave of the magic wand (couple of lines of XML and Java code).

Let us have a look at the advice implemented above: a message is printed to the console before a method is invoked, and a message is printed after the method returns. So we now know when and what is going to happen, we still don't know where (and "how", which is mysterious auto-proxying mechanism, courtesy of the Spring framework). Back to the aop.xml Spring context file - in it you will find the definition of the advisor bean.

 

Defining the pointcut

It defines which Advice is to be used, and also where to apply this advice to our application. Since we (wisely) chose the advisor bean to be of type org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor, we'll be using an AspectJ expression to define the pointcut. The expression injected into the advisor bean is this: execution(* *.greet(..))
The primitive pointcut used in this case - execution - "Picks out each method execution join point whose signature matches MethodPattern." (http://www.eclipse.org/aspectj/doc/released/progguide/semantics-pointcuts.html). The MethodPattern we have provided in our example case is quite simple, of course: a method called "greet" of any visibility, in any package, taking any number and kind of arguments will cause Spring to apply the advice accordingly (before it's invoked or after or both or on exception). There's a lot more to the method patterns in the AspectJ pointcut expression syntax, so feel free to rummage the website to find out more details.

 

How does it work? Proxies

Given this complete definition of the Advisor bean, we are now so very close to demystifying the whole lot. The one unanswered question remaining is the "how". By sheer black magic, I tells ya. :-) You can either add a pretty bit of confusing mark-up to your XML application contexts or you can use the Spring's auto-proxying capabilities. Dynamic proxies will be generated for your application. These will wrap implement the interface of our greeters, so will look like the real thing, but of course these will be fakes that will apply the advice as and when we the advice specifies.
We are using the org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator BeanPostProcessor that will, according to the documentation, "creates AOP proxies based on all candidate Advisors in the current BeanFactory". A long story short, it will figure out which objects need to be proxied (where to sneak in an extra thin layer of indirection) in order for our good-hearted advice to be applied.
I believe a picture says a thousand words:


Every method call matching the AspectJ pointcut expression will be intercepted by a proxy, forwarded to you advice, then executed, then pass back through your advice and then returns.

So... if you cared to scroll all the way back up to the code listing for our Main class, you could see that the expected output of running the application would be two lines: one, a greeting from the polite greeter, and the other an abrupt message from the naughty greeter. However, if you copy-pasted code carefully, when you run the application, the following output is produced:

PoliteGreeter is about to greet you:
>>>Good afternoon!
DONE
NaughtyGreeter is about to greet you:
>>>Leave me alone!
DONE

That's amazing! Our code was kindly advised to pre-output a short description of what's about to happen before each call to the greet() method on a greeter, and also to make it quite explicit that a greeter is done greeting us, by printing "DONE". That is the aspect of our application. One could then present this wonderful piece of software to a client a say: "One of the awesome aspects of our system is that the user is always notified of everything that is about to happen and also is told right-away when an action has finished executing."

Realistically, this aspect is quite useless, just like the application itself, but consider this: You have developed a complete application and you can tell your client "One important aspect of the system is that every operation on the service layer is atomic - wrapped in a transaction. It either succeeds or fails as a unit and whenever any failure is encountered, an entry is made into the error log and the transaction is rolled back."

 

Uses and benefits of AOP

It is a good idea to wrap your service methods in transactions. You will often want your operations to behave transactionally and fail with grace. Instead of sowing transaction-related code into every corner of your service layer, why not implement transactionality as an aspect, a cross-cutting concern? Get rid of all the "transaction = TransactionManager.beginTransaction(); try { doA(); doB(); ... transaction.commit();} catch (Exception) {logger.log(...); transaction.rollback();} " and keep your service methods rather nice and neat and organized, with focus on "what" the service does, not a myriad other aspects of how it's supposed to be done. You can implement the transactional aspect in separation from that - on top of that - AOP-style, and it's not that complicated. Just implement an "around advice" to start a transaction before a method is invoked, and to handle unhandled exceptions thrown and roll back / commit the transaction as necessary.

By defining your pointcut carefully, you could then advise this transactional behaviour to all of the public service methods and stay cool.

 

Other ways of doing AOP

There's, of course, a variety of ways one could go about implementing AOP. In the recent years, annotations have become quite a useful feature in Java. You can quite successfully avoid having all that XML in your project and use annotations to define your aspects (advices, pointcuts, etc) but I chose to provide you with a highly flexible approach, as you could use XML to wire aspects into your application without touching the existing code base. You don't have to add as much as a single annotation to your classes, doing it the way I have demonstrated above. However, I hear that doing AOP with annotations is sweet and much more convenient - so don't hesitate and give it a go! How hard can it be? Now that you already know almost all about it :-) (far from it, but I don't mean to discourage you).
Happy coding!

Wednesday 23 February 2011

Java Beans demystified

Welcome, this is my first blog post on Blogger. This article is intended for those learning Java, and those shifting to Java from a different programming ecosystem. I will try my best at providing a clear explanation of what JavaBeans are, since not even Wikipedia could explain this to me well enough. To quote Wikipedia:


Practically, [JavaBeans] are classes written in the Java programming language conforming to a particular convention. [...] A JavaBean is a Java Object that is serializable, has a nullary constructor, and allows access to properties using getter and setter methods.

Coffee metaphor

Now it's my turn to elaborate: It's called a bean to follow a certain symbolic. Java is (among other things) coffee. As Wikipedia explains: "In the United States the term "Java" by itself is, in general, slang for coffee". To make a perfect cuppa, you'll need to grind some beans. People behind Java find the term bean a good metaphor for a well-encapsulated building block of Java code. Coffee beans, when roasted, have a hardened outside that protects the goodness inside. While it could be considered witty to use the term bean to denote an encapsulated reusable piece of Java code, from my experience it's not the best term for a software component, but I guess it's a necessary evil to have such a term, as you'll see later.

JavaBeans are meant to be used by frameworks/containers/tools/etc. and not just by the code in the project you're currently working on. If you wrote an entire Java application yourself, from scratch, without using any framework, any container and did not intend your code to be used by any visual designer tools etc. then you could well not need the definition of a JavaBean. You could just go on ahead and write plain Java classes any way you choose (assuming the code works and is at least somewhat elegant) and not care the least about JavaBeans.

This is more or less what I have been doing for the last four years at Uni. I wrote code. Code that would run. Code that could be read and marked by a teacher. Not code that I would have intentions to reuse.

The important difference

If you want frameworks, containers, and code that others have written interacting with your objects, you'll want your objects to be written in a certain way. To make it easy for frameworks to instantiate objects from your classes, it makes sense to provide a constructor that takes no arguments. It also makes sense to apply a certain naming convention to your classes' properties' getters and setters, so frameworks/containers that you'll be plugging your code into can query and change the state of your objects' properties with ease.

Properties

Frameworks/containers picking up your beans will be using reflection to instantiate your classes and to determine the names of properties in your classes. What are properties? Well, in Java world, it's a little less explicit than in, say C# or Delphi. You can look at Java properties as private fields that you are exposing via a pair of accessor/mutator methods, also called getters and setters.

Here I'll make a short detour into C#:
To define a basic property in C#, with no extra logic in its getter and/or setter, one line will suffice:

public string MyProperty {get; set; }

Alas! there's no such convenient way for defining properties in Java. Properties, in both C# and Java, share the same concept - they consist of a backing field (usually with private visibility level) and an accessor/mutator method pair. C# has a predefined syntax for declaring properties and then generates the necessary getter and setter methods that are used under the hood (in CIL).

In Java, in order to have properties, developers must adhere to a naming convention and write the getXXX() and setXXX() methods for each (private) backing field they would like to expose as a property. The same MyProperty declared earlier in C# would then have to look like the following in Java:

private String myProperty;

public String getMyProperty() {
    return myProperty;
}

public void setMyProperty(String value) {
    myProperty = value;
}

For properties of a boolean type, things get even more tangled, since according to the JavaBeans naming conventions, the accessor method would be called isXXX(). Luckily this is not an absolute must, it's just considered good practice; getXXX() can still be used even for boolean properties.

Note, also, that the visibility levels of the getters and setters must be public. Is that really so? (Am I trying to confuse you or make things clear?) Of course you could have these getters and setters as private or protected or leave them with the default visibility level... but then your field would be just a field and your non-public getters and setters would be just some methods of your class and the three together (field+getter+setter) would NOT FORM A PROPERTY.

As I mentioned previously, there's nothing stopping you from not caring about the specification of JavaBeans, as long as you don't care to have your code used by other code.  Getters and setters will have to be declared public and adhere to the JavaBeans naming convention in order to be successfully discovered and used by other frameworks/containers/tools/etc.


Containers may use XML to configure your beans

You will often want to configure your objects in a declarative manner using XML. Some piece of software will then read this XML configuration and will work its magic on your classes. For example, you may want to set a particular String property of a class (e.g. lastName) to "Wolfeschlegelsteinhausenbergerdorff".

The lastName property has private visibility on purpose. All assignments to the lastName property are supposed to go through a setter method that may contain some logic, for example how to deal with names above a certain length. The code trying to configure your class instance will want to use this setter to mutate the value stored in the lastName property.

It will have to rely on JavaBeans naming conventions to figure out the name of the appropriate setter method to invoke. It will use Java Reflection API to interrogate the class's members and find the method called setLastName that will be invoked by this third-party piece of code to achieve our goal of having an instance of our class configured with the name "Wolfeschlegelsteinhausenbergerdorff" as last name.

Serialisation

Another aspect of JavaBeans is that they should be serializable - it should be possible to use the standard Java serialization mechanism to store and restore the internal state of a Java bean to/from a file (or network stream, etc.)

The following is an excerpt from sun's java.net Web site:

"When programmers assemble, configure, and connect Beans using an IDE, the JavaBeans components must be "live," dynamically created objects. The IDE must be able to save the worksheet's state at the end of the day and restore it at the start of a subsequent session. That is, a Bean's state must persist via external storage."

When your properties are of primitive or Serializable types, making a JavaBean serializable is as easy as tagging the class with a Tag Interface java.io.Serializable.

public class MyBeanClass implements java.io.Serializable { ... }

When your properties are of other types, make sure those types are Serializable. You could also provide your own custom serialization logic but that falls outside the scope of this article.

Event model

There are further restrictions on naming methods for registering and unregistering event handlers with/from a Java bean, however delving into these particulars would not add much value to this post.

I believe I said enough. I hope it is now clear what beans are in the world of Java.