1

I have looked at a few other postings to try and solve this issue.

Clarification around Spring-AOP pointcuts and inheritance

Spring AOP pointcut that matches annotation on interface

I have a scenario where we have some base interfaces that define some high level methods for data access (strongly typed via generics). I then have an interface that implements essentially overrides/reimplements the same methods in order to strongly type them and to provide JAX-WS annotations. The interesting point is that even though I redefine the methods within this interface, the Spring AOP pointcuts will not accept the pointcut and start a Transaction...so I get an error via Spring/JPA/Hibernate "Caused by: javax.persistence.TransactionRequiredException: no transaction is in progress".

We have other "services" that utilize Spring AOP successfully, but they don't inherit Generic methods from a super interface.

This is the top level class:

public interface BaseCoreDataService<O extends Comparable<O>, T extends DomainModel<O>> extends BaseService {

    @WebMethod(exclude = true)
    BaseDao<O, T> getBaseDao();

    O save(T model);

}

Which is inherited/extended by this interface (adding another method):

public interface BaseSimpleDataService<O extends Comparable<O>, T extends DomainModel<O>> extends
        BaseCoreDataService<O, T> {
    T get(O id);
}

Which is finally inherited/extended with this interface that strongly types the Generic and provide the JAX-WS annotations:

public interface UserDataService extends BaseSimpleDataService<Long, User> {

    @RequestWrapper(localName = "GetUserById", className = "com.foo.UserDataService.GetUserById", targetNamespace = "http://foo.com")
    @ResponseWrapper(localName = "GetUserByIdResponse", className = "com.foo.UserDataService.GetUserByIdResponse", targetNamespace = "http://foo.com")
    @WebResult(targetNamespace = "http://foo.com", name = "User")
    @WebMethod(operationName = "getUserById")
    User get(@WebParam(targetNamespace = "http://foo.com", name = "Id") Long id)
            throws ValidationException;

    @RequestWrapper(localName = "SaveUser", className = "com.foo.UserDataService.SaveUser", targetNamespace = "http://foo.com")
    @ResponseWrapper(localName = "SaveUserResponse", className = "com.foo.UserDataService.SaveUserResponse", targetNamespace = "http://foo.com")
    @WebResult(targetNamespace = "http://foo.com", name = "Id")
    @WebMethod(operationName = "saveUser")
    Long save(
            @WebParam(targetNamespace = "http://foo.com", name = "User") User model)
            throws ValidationException;
}

So if I include the following pointcut, the invocation blows an exception that a transaction does not exist:

<bean id="GlobalDataTransactionManager" class="org.springframework.transaction.jta.WebLogicJtaTransactionManager"
    p:transactionManagerName="javax.transaction.TransactionManager"/>

<tx:advice id="GlobalDataTxAdvice" transaction-manager="GlobalDataTransactionManager">
    <tx:attributes>
        <tx:method name="get*" timeout="60" no-rollback-for="javax.persistence.NoResultException,javax.persistence.NonUniqueResultException,org.springframework.dao.EmptyResultDataAccessException"/>
        <tx:method name="find*" timeout="60" no-rollback-for="javax.persistence.NoResultException,javax.persistence.NonUniqueResultException,org.springframework.dao.EmptyResultDataAccessException"/>
        <tx:method name="search*" timeout="60" no-rollback-for="javax.persistence.NoResultException,javax.persistence.NonUniqueResultException,org.springframework.dao.EmptyResultDataAccessException"/>
        <tx:method name="*" timeout="60"/>
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:advisor advice-ref="GlobalDataTxAdvice" pointcut="execution(* com.foo..UserDataService.*(..))"/>
</aop:config>

But if I add in an additional advisor/pointcut for the parent classes, the transaction works and saves/gets essentially succeed:

<aop:config>
    <aop:advisor advice-ref="GlobalDataTxAdvice" pointcut="execution(* com.foo..UserDataService.*(..))"/>
    <aop:advisor advice-ref="GlobalDataTxAdvice" pointcut="execution(* com.foo.core.*DataService.*(..))"/>
</aop:config>

I am not sure if the issue revolves around inheritance of interfaces? The odd thing is that in this final interface UserDataService, I have all the methods redefined...but this still fails when invoking save/get with a "no transaction in progress", even though the stacktrace includes Spring AOP classes.

So adding the additional advisor/pointcut fixes it, I just want to understand why?

Community
  • 1
  • 1
Jay Blanton
  • 574
  • 2
  • 10
  • 26

0 Answers0