how to rollback in entitymanager createNativeMethod - java

I am using native method of entity manager and I want to rollback when some error occurs.For this I tried #Transactional annotation but this does not rollback.Below is my sample code
controller
#Autowired
ServiceImpl ServiceImpl;
#RequestMapping("/saveinfo")
#ResponseBody
#Transactional
public String saveinfo(Long id)
{
ServiceImpl.saveInfo(id);
}
Service class
#Autowired
DAOImpl daoImpl;
#Transactional
public String saveinfo(Long id)
{
daoImpl.saveInfo1(id);
daoImpl.saveInfo12(id);
daoImpl.saveInfo12(id);
}
DAO class
#Override
public BigInteger saveInfo11() {
Query query = entityManagerUtil.entityManager().createNativeQuery("insert query");
return (BigInteger)query.getSingleResult();
}
#Override
public BigInteger saveInfo12() {
Query query = entityManagerUtil.entityManager().createNativeQuery("insert query");
return (BigInteger)query.getSingleResult();
}
#Override
public BigInteger saveInfo13() {
Query query = entityManagerUtil.entityManager().createNativeQuery("insert query");
return (BigInteger)query.getSingleResult();
}
Now in the above codes,
If I have some runtime error in saveInfo3() then I want to rollback methods of
saveInfo1() and saveInfo2()
This is the way I did but it did not rollback,so Please tell me how to do
EDIT
I tried using
#Transactional(rollbackFor=MyException.class,propagation = Propagation.REQUIRED) and #Transactional(propagation = Propagation.REQUIRED) and
#Transactional(rollbackFor=MyException.class))
In all the 3 cases ,it did not rollback
Update
applicationcontext.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.0.xsd">
<!--<context:annotation-config />-->
<context:spring-configured/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="dataSource" ref="dataSource"/>
<property name="persistenceUnitName" value="persistenceUnit"/>
</bean>
<bean id="messageDigestPasswordEncoder" class="org.springframework.security.authentication.encoding.MessageDigestPasswordEncoder">
<constructor-arg value="SHA-256" />
</bean>
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
<property name="driverClassName" value="${database.driverClassName}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
<context:property-placeholder location="classpath*:META-INF/database.properties"/>
<context:property-placeholder location="classpath*:META-INF/project.properties"/>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="propertiesUtil" class="com.work.project.utils.PropertiesUtil">
<property name="locations" >
<list>
<value>classpath*:META-INF/*.properties</value>
</list>
</property>
</bean>
<context:component-scan base-package="com.work.project">
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>
<task:executor id="myexecutor" pool-size="5" />
<task:annotation-driven executor="myexecutor"/>
</beans>
modified controller method
#Autowired
ServiceImpl ServiceImpl;
#RequestMapping("/saveinfo")
#ResponseBody
//Now I dont use transactional annotation in controller class
public String saveinfo(Long id)
{
ServiceImpl.saveInfo(id);
}
If any more information is required please ask

The problem seems to be that the EntityManager is not injected by Spring. The EntityManager instance is created by your utility class entityManagerUtil.entityManager(). This means, that everytime when you use a new EntityManager, they are not part of your method transaction.
In order to solve this problem: let Spring inject correctly the EntityManager (try for example injecting it directly in your original bean with #PersistenceContext and do those three methods directly in the same single method).
UPDATE:
The problem was that the code that threw the exception was in a try/catch block, this way, the transaction was not rolled-back by Spring. Transaction is rolled-back only when the transactional method exits with an RuntimeException (by default).

You need to change your method to have rollbackFor property for your #Transactional annotation, so that
#Transactional(rollbackFor=MyException.class)
public String saveinfo(Long id)
Keep in mind, that MyException should be unchecked exception, as checked exceptions thrown from #Transactional method will not result transaction to be rolled back.
Update:
To make sure everything is correct
Check that Spring indeed creates proxy and your method is being executed in transaction (e.g. use TransactionSynchronizationManager.isActualTransactionActive())
Check that MyException.class is indeed unchecked exception (subclass of java.lang.RuntimeException or java.lang.Error)
Check that your exception is indeed thrown (e.g. not catched somehow)
And why your controller saveInfo() is marked as transactional? This it not recommended, only service layer should be marked as transactional. See this post for example.

Maybe the entityManagerUtil (which you use within your DAO implementation) uses or creates an entity manager, that is not running in the surrounding transaction context. Please have a look at following tutorial: Here the JPA EntityManager is injected with #PersistenceContext

Can you make sure that your persistenceUnit has configured the following, transaction type(optional) and hibernate.connection.autocommit to false, if not please do so.
<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="hibernate.connection.autocommit" value="false" />
</properties>
</persistence-unit>
I have excluded other properties for brevity

Related

#Transactional don't work, maybe bad configuration for sessionfactory.getCurrentSession() [duplicate]

I'm getting the above exception with Spring3 and Hibernte4
The following is my bean xml file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<context:annotation-config/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/GHS"/>
<property name="username" value="root"/>
<property name="password" value="newpwd"/>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<props>
<prop key="dialect">org.hibernate.dialect.MySQL5Dialect</prop>
</props>
</property>
<property name="packagesToScan">
<list>
<value>com.example.ghs.model.timetable</value>
</list>
</property>
</bean>
<bean id="baseDAO"
class="com.example.ghs.dao.BaseDAOImpl"/>
</beans>
My BaseDAO class looks like this
public class BaseDAOImpl implements BaseDAO{
private SessionFactory sessionFactory;
#Autowired
public BaseDAOImpl(SessionFactory sessionFactory){
this.sessionFactory = sessionFactory;
}
#Override
public Session getCurrentSession(){
return sessionFactory.getCurrentSession();
}
}
The following code throws the exception in the title
public class Main {
public static void main(String[] args){
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("dao-beans.xml");
BaseDAO bd = (BaseDAO) context.getBean("baseDAO");
bd.getCurrentSession();
}
}
Does anyone have an idea about how to solve this problem?
getCurrentSession() only makes sense inside a scope of transaction.
You need to declare an appropriate transaction manager, demarcate boundaries of transaction and perform data access inside it. For example, as follows:
<bean id = "transactionManager" class = "org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name = "sessionFactory" ref = "sessionFactory" />
</bean>
.
PlatformTransactionManager ptm = context.getBean(PlatformTransactionManager.class);
TransactionTemplate tx = new TransactionTemplate(ptm);
tx.execute(new TransactionCallbackWithoutResult() {
public void doInTransactionWithoutResult(TransactionStatus status) {
// Perform data access here
}
});
See also:
10. Transaction Management
13.3 Hibernate
I came across same problem and got solved as below
Added #Transactional on daoImpl class
Added trnsaction manager in configuration file:
<tx:annotation-driven/>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
I'll just add something that took me some time to debug : don't forget that a #Transactional annotation will only work on "public" methods.
I put some #Transactional on "protected" ones and got this error.
Hope it helps :)
http://docs.spring.io/spring/docs/3.1.0.M2/spring-framework-reference/html/transaction.html
Method visibility and #Transactional
When using proxies, you should apply the #Transactional annotation
only to methods with public visibility. If you do annotate protected,
private or package-visible methods with the #Transactional annotation,
no error is raised, but the annotated method does not exhibit the
configured transactional settings. Consider the use of AspectJ (see
below) if you need to annotate non-public methods.
Which package u have put the BaseDAOImpl class in.. I think It requires a package name similar to the one u have used in the application context xml and it requires a relevant annotation too.

Cannot inject sessionFactory

While trying to get sessionFactory.getCurrentSession() debugger shows that sessionFactory is null. I assume Spring 3 fails to inject sessionFactory into this class although all configuration seems to be in place. How to fix it?
ServiceOrderDAO:
#Transactional
public class ServiceOrderDAO{
#Autowired
static
SessionFactory sessionFactory;
public static List<ServiceOrderEntity> search(params...){
Session localSession = sessionFactory.getCurrentSession();
...
}
}
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<context:annotation-config />
<mvc:annotation-driven/>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="" />
<property name="suffix" value=".jsp" />
</bean>
<context:component-scan base-package="controller" />
<context:component-scan base-package="dao" />
<context:component-scan base-package="service" />
<context:property-placeholder location="classpath:dbConnection.properties" />
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="model" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!--<bean id="persistenceExceptionTranslationPostProcessor" class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.user}" />
<property name="password" value="${jdbc.pass}" />
</bean>
<bean id="jdbcTemplateBean" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
There are a few things I think you'll want to touch up:
SessionFactory shouldn't be static, nor should your search method be static if you're trying to treat that class as a Spring bean.
Add a #Component or #Repository annotation to the class. I don't think Spring will autowire classes that are missing a stereotype annotation on the class.
You should consider moving your #Transactional annotation to the method so you can provide more fine-grained propagation. For example, your search method may not require a transaction so you may want to use #Transactional(propagation = Propagation.SUPPORTS). Check out the Spring documentation for additional info that explains the various annotations and where/how to annotate transactions.
sessionFactory being static definitely is the cause of the problem. You can't inject static fields with spring.
Going under the covers, the static fields gets initialized by classloader, before the constructor gets called, and therefore before spring gets chance to inject anything.
And your service class should be transactional, not your dao. And yes you need to annotate with #Component or #Service or similar.

lazy loading entities in spring with jpa and hibernate

I'm using Spring with JPA and Hibernate. I've got some DAO-Classes that are annotated with #Repositoy and some Controller-Classes. When I call one of the dao's methods in my controller to load some entities I get back the Entity and after that, I want to get some other entities that are stored in a field of the first loaded entity. But at that time spring has already closed the session and lazy loading is no longer possible.
My db.xml configuration:
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd" default-autowire="byName">
<!-- Scans within the base package of the application for #Components to configure as beans -->
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:db.properties" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="jpaVendorAdapter" />
</bean> -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="true" />
<property name="databasePlatform" value="${db.dialect}" />
</bean>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${db.driver}" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" />
</beans>
The method in the Dao is annotated as follows:
#Transactional(readOnly = true, propagation=Propagation.REQUIRED)
now I wanna do something like this:
#Controller
public class HomeController{
#Autowired
private UserDao userDao;
#RequestMapping(value = "/", method = RequestMethod.GET)
public ResponseEntity<String> home(){
...
User user = userDao.findUser(id);
Set<Order> orders = user.getOrders();
...
String myResult = ...;
return jsonService.generateResponse(myResult);
}
}
#Repository
public class UserDao{
#PersistenceContext
private EntityManager entityManager;
public User findUser(Integer id){
return entityManager.find(User.class, id);
}
}
The set of orders should be lazy-loaded but i get the following exception: org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role:...,no session or session was closed
root cause: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: ..., no session or session was closed
I tried to annotate the method in Controller wirt #Transactional and also to set mode="aspectj" in annotation-driven property in the db.xml, but nothing did work. Is there any way to lazy load the orders of the user?
For any help, thanking you in anticipation!
You can use special filter to get session in web view. Add to your web.xml
<filter>
<filter-name>jpaFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>jpaFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
the filter works as follows:
The filter intercepts a servlet request
The filter opens an EntityManager and binds it to the current thread
Web controller is called
Web controller calls service
Transaction interceptor begins a
new transaction, retrieves the thread-bound EntityManager and binds
it to the transaction
Service is called, does some stuff with
EntityManager, then returns
Transaction interceptor flushes the
EntityManager then commits the transaction
Web controller prepares
view, then returns
View is built
Filter closes the EntityManager and
unbinds it from current thread

NullPointerException occured when I use the EntityManagerFactory

My goal is to instanciate the EntityManagerFactory from applicationContext.xml file to get all posts registered in SQL database.
Here's the content of the main files :
applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- Properties files linkers -->
<context:property-placeholder location="/WEB-INF/resources/database/jdbc.properties"/>
<context:property-placeholder location="/WEB-INF/resources/database/hibernate.properties"/>
<!-- Config database - initialization -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- Three main layers definition -->
<context:annotation-config />
<context:component-scan base-package="com.zone42"/>
<!-- Transaction sub-system initialization -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
(WEB-INF/classes/)persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="post-unit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.zone42.model.Post</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
</persistence-unit>
</persistence>
PostDAO.java
public class PostDAO extends GenericDAOEntity<Post> implements IPostDAO
{
}
GenericDAOEntity.java
#Transactional
public class GenericDAOEntity<T> implements IGenericDAO<T>
{
/**
* Properties
*/
#Autowired
#PersistenceContext(unitName="post-unit")
private EntityManagerFactory entityManagerFactory/* = Persistence.createEntityManagerFactory(persistence_unit_name)*/;
//Get all posts
#SuppressWarnings("unchecked")
public List<T> findAll(Class<T> obj) {
EntityManager entityManager = this.entityManagerFactory.createEntityManager();
Query query = entityManager.createQuery("from " + obj.getSimpleName());
return (query.getResultList());
}
/**
* Accessors
*/
public EntityManagerFactory getEntityManagerFactory() {
return entityManagerFactory;
}
#PersistenceContext(unitName="post-unit")
public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
this.entityManagerFactory = entityManagerFactory;
}
}
I tried several config combinations but without success. The NullPointerException comes from the findAll method when I want to create an instance of EntityManager from the entityfactory instance. I think I have a configuration problem. I want to precise that the code works whn I instanciate the EntityManagerFactory using operator new directly in the class. Now I just want to allocate my factory choosing another way, the one using xml from appicationContext.xml file. Can anyone help me? Thanks in advance.
You need to either mark the field/setter as #Autowired or explicitly wire the reference up in your XML:
<bean class="PostDAO">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

Use Spring annotations to automatically apply Hibernate Interceptor?

In my service class I need the hibernate session available. I currently do this in the beans.xml:
<bean id = "userDao" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref bean="userDaoTarget" />
</property>
<property name="proxyInterfaces">
<value>com.app.dao.UserDao</value>
</property>
<property name="interceptorNames">
<list>
<value>hibernateInterceptor</value>
</list>
</property>
<qualifier value="proxy" />
</bean>
...
<bean id="hibernateInterceptor"
class="org.springframework.orm.hibernate3.HibernateInterceptor">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
<bean>
(copied by hand, may be some typos..)
I'm moving to using annotations over XML, I was wondering if there was a way to use them to configure the proxy as I have above including the hibernate interceptor? If not - is there a way that I can reduce the amount of XML (with about 7 DAOs it makes it very cluttered)
Ok, Let's go. You said
I am moving to using annotations over XML
Enable an aspect as follows
package br.com.ar.aop;
#Aspect
public class HibernateInterceptorAdvice {
#Autowired
private HibernateInterceptor hibernateInterceptor;
/**
* I suppose your DAO's live in com.app.dao package
*/
#Around("execution(* com.app.dao.*(..))")
public Object interceptCall(ProceedingJoinPoint joinPoint) throws Throwable {
ProxyFactory proxyFactory = new ProxyFactory(joinPoint.getTarget());
proxyFactory.addAdvice(hibernateInterceptor);
Class [] classArray = new Class[joinPoint.getArgs().length];
for (int i = 0; i < classArray.length; i++)
classArray[i] = joinPoint.getArgs()[i].getClass();
return
proxyFactory
.getProxy()
.getClass()
.getDeclaredMethod(joinPoint.getSignature().getName(), classArray)
.invoke(proxyFactory.getProxy(), joinPoint.getArgs());
}
}
But keep in mind It just works if your DAO's implements some interface (For instance, UserDAOImpl implements UserDAO). Spring AOP uses JDK dynamic proxy in this case. If you does not have any interface, you can rely on your IDE To refactor your code by using Extract interface
Declare your xml as follows (Be aware i am using Spring 2.5 xsd schema)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<!--SessionFactory settings goes here-->
<bean class="org.springframework.orm.hibernate3.HibernateInterceptor">
<property name="sessionFactory" ref="sessionFactory"/>
<bean>
<!--To enable AspectJ AOP-->
<aop:aspectj-autoproxy/>
<!--Your advice-->
<bean class="br.com.ar.aop.HibernateInterceptorAdvice"/>
<!--Looks for any annotated Spring bean in com.app.dao package-->
<context:component-scan base-package="com.app.dao"/>
<!--Enables #Autowired annotation-->
<context:annotation-config/>
</beans>
Do not forget To put in the classpath besides Spring libraries
<SPRING_HOME>/lib/asm
<SPRING_HOME>/lib/aopalliance
<SPRING_HOME>/lib/aspectj
Have a look at the #Autowired annotation.

Categories