Search
Calendar
June 2025
S M T W T F S
« May    
1234567
891011121314
15161718192021
22232425262728
2930  
Archives

Posts Tagged ‘AOP’

PostHeaderIcon 🚀 Making Spring AOP Work with Struts 2: A Powerful Combination! 🚀

Spring AOP (Aspect-Oriented Programming) and Struts 2 might seem like an unusual pairing, but when configured correctly, they can bring cleaner, more modular, and reusable code to your Struts-based applications.

The Challenge:

  • Struts 2 manages its own action instances for each request, while Spring’s AOP relies on proxying beans managed by the Spring container. This means Struts actions are not Spring beans by default, making AOP trickier to apply.
  • The Solution: Making Struts 2 Actions Spring-Managed
  • To make Spring AOP work with Struts 2, follow these steps:


✅ Step 1: Enable Spring integration with Struts 2


Ensure your `struts.xml` is configured to use Spring:

“`<constant name=”struts.objectFactory” value=”spring”/>“`

This makes Struts retrieve action instances from the Spring context instead of creating them directly.

✅ Step 2: Define Actions as Spring Beans


In your applicationContext.xml or equivalent Spring configuration, define your Struts actions:

“`
<bean id=”myAction” class=”com.example.MyStrutsAction” scope=”prototype”/>
“`
Setting the scope to “prototype” ensures a new instance per request, preserving Struts 2 behavior.


✅ Step 3: Apply AOP with `@Aspect`

Now, you can apply Spring AOP to your Struts actions just like any other Spring-managed bean:

“`
@Aspect
@Component
public class LoggingAspect {

@Before(“execution(* com.example.MyStrutsAction.execute(..))”)
public void logBefore(JoinPoint joinPoint) {
System.out.println(“Executing: ” + joinPoint.getSignature().toShortString());
}
}
“`

This will log method executions before any `execute()` method in your actions runs!

Key Benefits of This Approach
🔹 Separation of Concerns – Keep logging, security, and transaction management outside your action classes.
🔹 Reusability – Apply cross-cutting concerns like security or caching without modifying Struts actions.
🔹 Spring’s Full Power – Leverage dependency injection and other Spring features within your Struts 2 actions.
🔥 By integrating Spring AOP with Struts 2, you get the best of both worlds: Struts’ flexible request handling and Spring’s powerful aspect-oriented capabilities. Ready to make your legacy Struts 2 app cleaner and more maintainable? Let’s discuss!

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.