Note that there are some explanatory texts on larger screens.

plurals
  1. POSpring AOP and Interfaces with Generics (Inheritance)
    primarykey
    data
    text
    <p>I have looked at a few other postings to try and solve this issue.</p> <p><a href="https://stackoverflow.com/questions/7727454/clarification-around-spring-aop-pointcuts-and-inheritance">Clarification around Spring-AOP pointcuts and inheritance</a></p> <p><a href="https://stackoverflow.com/questions/2847640/spring-aop-pointcut-that-matches-annotation-on-interface">Spring AOP pointcut that matches annotation on interface</a></p> <p>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".</p> <p>We have other "services" that utilize Spring AOP successfully, but they don't inherit Generic methods from a super interface.</p> <p>This is the top level class:</p> <pre><code>public interface BaseCoreDataService&lt;O extends Comparable&lt;O&gt;, T extends DomainModel&lt;O&gt;&gt; extends BaseService { @WebMethod(exclude = true) BaseDao&lt;O, T&gt; getBaseDao(); O save(T model); } </code></pre> <p>Which is inherited/extended by this interface (adding another method):</p> <pre><code>public interface BaseSimpleDataService&lt;O extends Comparable&lt;O&gt;, T extends DomainModel&lt;O&gt;&gt; extends BaseCoreDataService&lt;O, T&gt; { T get(O id); } </code></pre> <p>Which is finally inherited/extended with this interface that strongly types the Generic and provide the JAX-WS annotations:</p> <pre><code>public interface UserDataService extends BaseSimpleDataService&lt;Long, User&gt; { @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; } </code></pre> <p>So if I include the following pointcut, the invocation blows an exception that a transaction does not exist:</p> <pre><code>&lt;bean id="GlobalDataTransactionManager" class="org.springframework.transaction.jta.WebLogicJtaTransactionManager" p:transactionManagerName="javax.transaction.TransactionManager"/&gt; &lt;tx:advice id="GlobalDataTxAdvice" transaction-manager="GlobalDataTransactionManager"&gt; &lt;tx:attributes&gt; &lt;tx:method name="get*" timeout="60" no-rollback-for="javax.persistence.NoResultException,javax.persistence.NonUniqueResultException,org.springframework.dao.EmptyResultDataAccessException"/&gt; &lt;tx:method name="find*" timeout="60" no-rollback-for="javax.persistence.NoResultException,javax.persistence.NonUniqueResultException,org.springframework.dao.EmptyResultDataAccessException"/&gt; &lt;tx:method name="search*" timeout="60" no-rollback-for="javax.persistence.NoResultException,javax.persistence.NonUniqueResultException,org.springframework.dao.EmptyResultDataAccessException"/&gt; &lt;tx:method name="*" timeout="60"/&gt; &lt;/tx:attributes&gt; &lt;/tx:advice&gt; &lt;aop:config&gt; &lt;aop:advisor advice-ref="GlobalDataTxAdvice" pointcut="execution(* com.foo..UserDataService.*(..))"/&gt; &lt;/aop:config&gt; </code></pre> <p>But if I add in an additional advisor/pointcut for the parent classes, the transaction works and saves/gets essentially succeed:</p> <pre><code>&lt;aop:config&gt; &lt;aop:advisor advice-ref="GlobalDataTxAdvice" pointcut="execution(* com.foo..UserDataService.*(..))"/&gt; &lt;aop:advisor advice-ref="GlobalDataTxAdvice" pointcut="execution(* com.foo.core.*DataService.*(..))"/&gt; &lt;/aop:config&gt; </code></pre> <p>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.</p> <p>So adding the additional advisor/pointcut fixes it, I just want to understand why?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload