Search
Calendar
March 2024
S M T W T F S
« Sep    
 12
3456789
10111213141516
17181920212223
24252627282930
31  
Your widget title
Archives

Posts Tagged ‘AOP’

PostHeaderIcon Proxying without AOP

Case

You have many operations to execute on each method call. At first glance, this is the perfect case to write an AOP mechanism (such as in this example Transaction Management with Spring in AOP).
Anyway, sometimes AOP won’t work, for instance when OSGi jars and their inherent opacity prevent you from cutting method calls.
Yet, I suggest here a workaround. In the following example, we log each method call, with inputs and outputs (returned values ; you can improve the code sample to handle raised exceptions, too).

Solution

Starting Point

Let’s consider an interface MyServiceInterface. It is actually implemented by MyServiceLogic.
An EJB MyServiceBean has a field of type MyServiceInterface, and the concrete implementation is of type MyServiceLogic.
Without proxying nor AOP, the EJB should look like:

public MyServiceBean extends ... implements ...{
  private MyServiceInterface myServiceLogic;

   public MyServiceBean() {
        this.myServiceLogic = new MyServiceLogic();
   }
}    

We have to insert a proxy in this piece of code.

Generic Code

The following piece of code is technical and generic, which means it can be used in any business context. We use the class InvocationHandler, that is part of package java.lang.reflect since JDK 1.4
(in order to keep the code light, we don’t handle the exceptions ; consider adding them as an exercise 😉 )

public class GenericInvocationHandler<T> implements InvocationHandler {
    private static final String NULL = "<null>";

    private static final Logger LOGGER = Logger.getLogger(GenericInvocationHandler.class);

    private final T invocable;

    public GenericInvocationHandler(T _invocable) {
        this.invocable = _invocable;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        final Object answer;
        LOGGER.info(">>> " + invocable.getClass().getSimpleName() + "." + method.getName() + " was called with args: " + arrayToString(args));
        answer = method.invoke(invocable, args);
        // TODO handle throwables
        if (method.getReturnType().equals(Void.class)) {
            LOGGER.info("<<< (was a void method) ");
        } else {
            LOGGER.info("<<< " + invocable.getClass().getSimpleName() + "." + method.getName() + " returns: " + (answer == null ? "<null>" : answer.toString()));
        }
        return answer;
    }

    private static String arrayToString(Object... args) {
        final StringBuilder stringBuilder;
        stringBuilder = new StringBuilder();
        for (Object o : args) {
            stringBuilder.append(null == o ? NULL : o.toString());
        }
        return stringBuilder.toString();
    }
}

Specific Code

Let’s return to our business requirement. The EJB has to be modified, and should be like:

public MyServiceBean extends ... implements ...{
  private MyServiceInterface myServiceLogic;

    public MyServiceBean() {
        final MyServiceInterface proxied;
        proxied = new MyServiceLogic();
        this.myServiceLogic = (MyServiceInterface) Proxy.newProxyInstance(proxied.getClass().getClassLoader(),
                proxied.getClass().getInterfaces(),
                new GenericInvocationHandler<MyServiceInterface>(proxied));
    }

From now and then, all the methods calls will be logged… All that without AOP!

PostHeaderIcon Transaction Management with Spring in AOP

Case

You have a couple of Hibernate DAOs, in which a huge amount of code is duplicated: begin transactions, try/catch, close transactions, etc.
You would like to factorize your code.

Fix

  • Define a SessionFactory, let’s say hibernateSessionFactory, with your own settings.
    <bean id="hibernateSessionFactory"
    class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">(...)</bean>
  • Define a TransactionManager:
    <bean id="hibernateTransactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory">
    <ref local="hibernateSessionFactory" />
    </property>
    </bean>
  • Define transactions advices:
    <tx:advice id="hibTxManager" transaction-manager="hibernateTransactionManager">
    <tx:attributes>
    <tx:method name="*" propagation="NEVER" read-only="true" isolation="READ_COMMITTED" rollback-for="find*" no-rollback-for="dontFind*"/>
    </tx:attributes>
    </tx:advice>
    • name="*" –> the aspect will apply to all methods. You may filter on patterns such as find*, get*, save*, etc.
    • propagation="NEVER" –> hints the propagation level. Available options are
    • REQUIRED, SUPPORTS, MANDATORY,REQUIRES_NEW, NOT_SUPPORTED, NEVER, NESTED.
    • isolation="READ_COMMITTED" –>
    • rollback-for="find*" –> rollback all transactions following the given pattern
    • no-rollback-for="dontFind*" –> exceptions for rollbacks
  • Define the AOP configuration:
    <aop:config>
    <aop:pointcut id="hibOperation"
    expression="execution(* com.lalou.jonathan.dao.hibernate.Hibernate*.*(..))" />
    <aop:advisor pointcut-ref="hibOperation" advice-ref="hibTxManager" />
    </aop:config>

Many thanks to Jean-Pierre ISOARD for his help on this subject.