Spring Transaction in JSF - spring

Using Spring 3.1,Mojarra ,Hibernate
applicationContext.xml
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
...
</bean>
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<context:component-scan base-package="mypackage"/>
TestBean.java
#Component
#Scope("session")
public class TestBean {
#Autowired private #Getter #Setter HibernateTemplate hibernateTemplate=null;
public String submit(){
try{
this.test();
}catch (RuntimeException ex) {
FacesUtil.addWarn("Error");
}
return null;
}
#Transactional
public String test() {
Device d1=new Device();
hibernateTemplate.persist(d1);
if(1==1)
throw new RuntimeException("Testing");
Device d2=new Device();
hibernateTemplate.persist(d2);
return null;
}
}
This works(rolled back) ,but shows exception in browser
<h:commandButton value="Submit" action="#{testBean.test}"/>
Tried to show faces message ,but this commits d1
<h:commandButton value="Submit" action="#{testBean.submit}"/>
Calling some other bean's(DAO) transactional method too works,but I would like to have the code in managed bean itself.How should I handle transaction in JSF?

Either move transactional methods to yet another layer or use TransactionTemplate if you wish to avoid it for some reason:
public String test() {
TransactionTemplate txTemplate = new TransactionTemplate(transactionManager);
try {
txTemplate.execute(new TransactionCallbackWithoutResult() {
#Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
// your transactional code here;
}
});
} catch (Exception e) {
// handle exception here
}
return null;
}

Better go for layered architecture Service and DAO layer, directly handling transactions in managed bean defeats the purpose of Single Responsibility Principle of a class.
Managed Bean soul purpose should be for navigation handling and gateway for data from view layer to service layer where you can perform main business logic or use case and delegate data persistence to DAO layer.
As far as messages to UI are concerned you can catch exceptions from service layer and populate required message accordingly.
This way things are more manageable and maintainable and testable. Mock your service layer, test DAO for data persistence and Managed Bean for view layer.
Spring uses proxy/AOP for magical #Transactional to take place and its better you code to interface as it has its own issues if you dont code to interface i.e direct proxy to an interface or CGLIB subclass for injection. Look in docs for tag for proxy setting for better understanding what I mean by code to interface.
Note: HibernateTemplate is considered an Anti Pattern and removed from Hibernate 4 support just a pointer so you can act accordingly if on Hibernate 3.
Hope this helps !!!!!

Related

EJB with spring : transaction issue in JPA flush

I have an issue with an injected EntityManager in my MessageDriven Bean that use spring bean as services (the bootstrap is done with the SpringBeanAutowiringInterceptor.
Here is the code :
#MessageDriven(name = "ProcessMDB")
#Interceptors(SpringBeanAutowiringInterceptor.class)
public class ProcessMDB implements MessageListener {
#Autowired
private ProcessService processService;
#Override
public void onMessage(Message message) {
try {
id = message.getLongProperty("ID");
processService.process(id);
} catch (Exception e) {
// Handle error.
}
}
The process service has a DAO where the EntityManager is injected with the annotation #PersistentContext...
The problem is that if a JPA error occurs in the processService, it may occur during the entityManager.flush() call... so the try catch block is gone and the //Handle error stuff is not done.
So I tried to add manually the flush.
#MessageDriven(name = "ProcessMDB")
#Interceptors(SpringBeanAutowiringInterceptor.class)
public class ProcessMDB implements MessageListener {
#Autowired
private ProcessService processService;
#PersistenceContext
private EntityManager em;
#Override
public void onMessage(Message message) {
try {
id = message.getLongProperty("ID");
processService.process(id);
em.flush();
} catch (Exception e) {
// Handle error.
}
}
But it seems that the flush has no effect.
I've try to add the em.flush in the underlying DAO (just after the persist for instance) and it works! The exception is well raised and the catch block is executed. But it doesn't work if I put the em.flush() at the MessageDrivenBean level.
I think that it's transaction manager problem... The entitymanager in spring beans is not in the same tx than the injected entity manager in my ejb.
If I make em.find in the onMessage() method, the fetched object holds old values (the one in the database), not values that are changed in the service method.
I've configured my database as followed :
<jee:jndi-lookup id="emf" jndi-name="persistence/PUnit" />
and my tx manager as followed :
<tx:annotation-driven/>
<tx:jta-transaction-manager />
What do I wrong?
Can someonee help me?
Thanks
Stéphane
You have injected EntityManager in ProcessMDB, but the object is being persisted in ProcessService.
Now, how can any operation in ProcessMDB can affect ProcessService, both will have probably their own individual EntityManager.
Scope of PersistenceContext is upto associated EntityManager. The object will be in the context of ProcessService & not in ProcessMDB, therefore calling flush on later will have no effect & this is expected behaviour.

"HibernateException: No Session found for current thread" when calling DAO from Transactional service method

I have a service bean that loads objects from the database after instantiation into an object cache. If I label the service method that calls my DAO object method as #Transactional, then I get the "HibernateException: No Session found for current thread" error. However, if I label the DAO class as #Transactional, I get no such error and it works fine.
The problem is that I can't then make multiple DAO calls from the same method in the service object and have it be one transaction. Are there any thoughts on what might cause this?
I am using Spring 3.1 and Hibernate 4.
DAO Example:
#Repository
public class HibernateObjectDao implements ObjectDao {
SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public List<Object> getObjects() {
return sessionFactory.getCurrentSession()
.createQuery("from Object").list();
}
}
Service Bean example:
#Service
public class MyServiceBean implements AbstractMyServiceBean
{
#Resource
private ObjectDao objectDao;
private HashMap<String,Object> objectCache;
public MyServiceBean() {
this.objectCache = new HashMap<String,Object>();
}
#Autowired
public void setObjectDao(ObjectDao objectDao) {
this.objectDao = objectDao;
}
#Transactional
public void initialize() {
loadObjectCache();
}
public void loadObjectCache() {
objectCache.put("stuff",this.objectDao.getObjects())
}
}
ApplicationContext.xml excerpt:
<bean id="objectDao" class="com.example.persistence.HibernateObjectDao">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="myServiceBean"
class="com.example.service.MyServiceBean"
init-method="initialize">
<property name="objectDao" ref="objectDao" />
</bean>
Methods are transactional when they're called from the outside of the bean, using an injected instance of the bean, which is in reality a transactional proxy around the actual bean instance.
Spring calls the initialize method directly on the bean instance, not on the transactional proxy, so the methods are not called in a transaction.
Put an initialize method in another bean, which will use an injected MyServiceBean and call its initialize() method.
The problem is that there is no transactional proxy around the bean when Spring calls initialize. This is on purpose, as the philosophy is that the bean is not ready for use until it is init'd.
Some solutions:
In this special case of init-time data processing, do manual transaction handling via TransactionTemplate or session.beginTransaction(). If you use JPA/Hibernate, use code like this to add the EntityManager to the Transaction Synchronizer:
EntityManager em = entityManagerFactory.createEntityManager();
TransactionSynchronizationManager.bindResource(entityManagerFactory, new EntityManagerHolder(em));
Create another bean for all initializing type events in your application and let that call other beans. By that time, all the other beans will be ready and Spring will put a transactional proxy around them. Note: do not call the method set as an init-method from this bean as this way that particular bean will be initialized twice, which is not always healthy :) Create another method for this purpose.
Use an ApplicationListener. With this one, you can register a callback and handle the ContextRefreshedEvent as a sign that the context initialization is done.

Spring + Hibernate = "manual" transactions how-to

My webapp (Spring3 + Hibernate3) always worked with services class-annotated with #Transactional and this configuration:
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="mySessionFactory" />
</bean>
Now... I'm on Google AppEngine. For some nasty reason I don't know yet, #Transactional does not work. It uses some class in javax.naming, which is not whitelisted. It ends up with:
Error creating bean with name 'mySessionFactory': Post-processing of
the FactoryBean's object failed; nested exception is
java.lang.SecurityException: Unable to get members for class
org.hibernate.impl.SessionFactoryImpl
Please don't ask me why.... :-\
Using Spring's HibernateTemplate instead of my dao (which uses raw session factory) solved the problem, but I know it's a little obsolete.
So, I want to try using manual old style transactions. Questions:
where? I'd like to keep the transactions in the service layer.
how?
SessionFactoryImpl dependency is not in Google App Engine whitelist. There is a number of Google hits discussing it.
As far as "what to do", you have options:
Depend on on another JPA provider
Don't use ORM at all, and go native with Spring's JdbcTemplate (my favorite)
I am not sure why you need to use a programmatic transaction management since Hibernate is the root of your problem, but if you just like to know how, here is a draft:
public class SomeService implements SomeInterface {
private SomeDao thisDaoWrapsJdbcTemplate;
private PlatformTransactionManager transactionManager;
public void setTransactionManager( PlatformTransactionManager transactionManager ) {
this.transactionManager = transactionManager;
}
public void doBusiness( Business: business ) {
TransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction( def );
try {
// do business here
Money money = Money.LOTS_OF
...
// wire the money in..
thisDaoWrapsJdbcTemplate.depositLotsOfMoney( money )
transactionManager.commit( status );
} catch ( DataAccessException dae ) {
transactionManager.rollback( status );
throw dae;
}
return;
}

Spring3 's #Transactional #Scheduled not committed to DB?

This is my 1st time trying Spring3's #Scheduled , but found I cannot commit to DB. This is my code :
#Service
public class ServiceImpl implements Service , Serializable
{
#Inject
private Dao dao;
#Override
#Scheduled(cron="0 0 * * * ?")
#Transactional(rollbackFor=Exception.class)
public void hourly()
{
// get xxx from dao , modify it
dao.update(xxx);
}
}
I think it should work , I can see it starts-up hourly and load xxx from DB , but data is not committed to DB.
There's been tx:annotation-driven in spring's xml :
<bean id="entityManagerFactoryApp" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="myapp"/>
</bean>
<bean id="transactionManagerApp" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoryApp" />
</bean>
<tx:annotation-driven transaction-manager="transactionManagerApp" />
Can somebody tell me what I missed here ?
I have one 'dirty' solution :
#Service
public class ServiceImpl implements Service , Serializable
{
#Inject
private Dao dao;
#Inject
#Qualifier("transactionManagerApp")
private PlatformTransactionManager txMgrApp;
#Override
#Scheduled(cron="0 0 * * * ?")
#Transactional(rollbackFor=Exception.class)
public void hourly()
{
final TransactionTemplate txTemplateApp = new TransactionTemplate(txMgrApp);
txTemplateApp.execute(new TransactionCallbackWithoutResult()
{
#Override
protected void doInTransactionWithoutResult(TransactionStatus status)
{
//get xxx from dao
dao.update(xxx);
}
});
}
}
It works fine here , but it is so redundant , making the code harder to read.
I wonder why TransactionManager is not injected (and opened) in the previous code snippets?
Thanks a lot !
You probably have figured this out or moved on (I hope so), but for the benefit of others:
The #Transactional annotation tells Spring to wrap your original ServiceImpl bean with a dynamic proxy that also implements 'Service' (by default Spring proxies the interface, not the implementation). This proxy will transparently handle the creation and commit/rollback of the transaction when you call hourly() on the proxy. However, if you call hourly() directly on your implementation (which is what is happening above), the proxy is bypassed, so there is no transaction.
http://blog.springsource.org/2012/05/23/understanding-proxy-usage-in-spring/
The solution is to either
Demarcate the transaction programmatically as you are doing in your 'dirty' solution (you don't need the annotations is this case).
Make sure that your #Scheduled method makes its call to dao.update(xxx); via the Service interface, not directly on your implementation (thereby going through the proxy). Basically you need to move the #Scheduled method to another bean.
I hope that is clear enough!
When you use annotation-driven support, it only works on classes created within that context. My bet is that ServiceImpl is not created in the same context as your transaction manager (either directly or by annotation scanning).
I had the same problem and after spending time on it, I realized that I got an exception after the dao.update() call in some unrelated code that didn't check null value - so it simply broke the transaction.
There was no stackTrace printing because it has been treated well by spring (some catch block).
I spent a while on that.
So - just verify that your transaction method completes till its end.
Hope it will help someone.
Yosi Lev

Spring #Autowiring with generic factory-built beans

I have a set of classes with a complex initialization scheme. Basically, I start with the interface I need to get a hold of, and then make a bunch of calls, and I end up with an object that implements that interface.
In order to handle this, I made a factory class that can, given an interface, produce the final object. I made this factory into a bean, and in XML I specified my various service beans as being instantiated via this factory object with a parameter of the interface that they will implement.
This works great, and I totally get exactly the beans I need. Unfortunately, I would like to access them from my controller classes, which are discovered via component scanning. I use #Autowired here, and it appears that Spring has no idea what type of object these are, and since #Autowired works by type, I'm SOL.
Using #Resource(name="beanName") here would work perfectly, however it seems odd to use #Resource for some beans and #Autowired for others.
Is there a way to get Spring to know what interface the factory will be creating for each of these beans without having a different factory method for each type?
I'm using Spring 2.5.6, by the way, otherwise I'd just JavaConfig the whole thing and forget about it.
Factory class:
<T extends Client> T buildService(Class<T> clientClass) {
//Do lots of stuff with client class and return an object of clientClass.
}
app context:
<bean id="serviceFactoryBean" class="com.captainAwesomePants.FancyFactory" />
<bean id="userService" factory-bean="serviceFactoryBean" factory-method="buildService">
<constructor-arg value="com.captain.services.UserServiceInterface" />
</bean>
<bean id="scoreService" factory-bean="serviceFactoryBean" factory-method="buildService">
<constructor-arg value="com.captain.services.ScoreServiceInterface" />
</bean>
my controller:
public class HomepageController {
//This doesn't work
#Autowired #Qualifier("userService") UserServiceInterface userService;
//This does
#Resource(name="scoreService") ScoreServiceInterface scoreService;
}
I suggest you take the factory pattern one step further and implement your factories as Spring FactoryBean classes. The FactoryBean interface has a getObjectType() method which the contain calls to discover what type the factory will return. This gives your autowiring something to get its teeth into, as long as your factory returns a sensible value.
I had a similar problem, but for me I wanted to use a single factory for creating mocked-out implementations of my auto-wired dependencies using JMockit (the testing framework that I am required to use).
After finding no satisfactory solution on the interwebs, I threw together a simple solution that is working really well for me.
My solution uses a Spring FactoryBean as well, but it only uses a single factory bean for creating all my beans (which the original asker seems to have wished to do).
My solution was to implement a factory-of-factories meta-factory that serves-up FactoryBean wrappers around the real, single factory.
Here is the Java for my JMockit mock bean factory:
public class MockBeanFactory<C> implements FactoryBean<C> {
private Class<C> mockBeanType;
protected MockBeanFactory(){}
protected <C> C create(Class<C> mockClass) {
return Mockit.newEmptyProxy(mockClass);
}
#Override
public C getObject() throws Exception {
return create(mockBeanType);
}
#Override
public Class<C> getObjectType() {
return mockBeanType;
}
#Override
public boolean isSingleton() {
return true;
}
public static class MetaFactory {
public <C> MockBeanFactory<C> createFactory(Class<C> mockBeanType) {
MockBeanFactory<C> factory = new MockBeanFactory<C>();
factory.mockBeanType = mockBeanType;
return factory;
}
}
}
And then in the Spring context XML file, you just can simply create the meta factory that creates the specific bean-type factories:
<bean id="metaFactory" class="com.stackoverflow.MockBeanFactory$MetaFactory"/>
<bean factory-bean="metaFactory" factory-method="createFactory">
<constructor-arg name="mockBeanType" value="com.stackoverflow.YourService"/>
</bean>
To make this work for the original asker's situation, it could be tweaked to make the FactoryBeans into wrappers/adapter for the serviceFactoryBean:
public class FancyFactoryAdapter<C> implements FactoryBean<C> {
private Class<C> clientClass;
private FancyFactory serviceFactoryBean;
protected FancyFactoryAdapter(){}
#Override
public C getObject() throws Exception {
return serviceFactoryBean.buildService(clientClass);
}
#Override
public Class<C> getObjectType() {
return clientClass;
}
#Override
public boolean isSingleton() {
return true;
}
public static class MetaFactory {
#Autowired FancyFactory serviceFactoryBean;
public <C> FancyFactoryAdapter<C> createFactory(Class<C> clientClass) {
FancyFactoryAdapter<C> factory = new FancyFactoryAdapter<C>();
factory.clientClass = clientClass;
factory.serviceFactoryBean = serviceFactoryBean;
return factory;
}
}
}
Then in the XML (notice the userServiceFactory id and the userService bean id are necessary only to work with the #Qualifier annotation):
<bean id="metaFactory" class="com.stackoverflow.FancyFactoryAdapter$MetaFactory"/>
<bean id="userServiceFactory" factory-bean="metaFactory" factory-method="createFactory">
<constructor-arg name="clientClass" value="com.captain.services.UserServiceInterface"/>
</bean>
<bean id="userService" factory-bean="userServiceFactory"/>
<bean id="scoreServiceFactory" factory-bean="metaFactory" factory-method="createFactory">
<constructor-arg name="clientClass" value="com.captain.services.ScoreServiceInterface"/>
</bean>
<bean id="scoreService" factory-bean="scoreServiceFactory"/>
And that's it, just one little Java class and a smidge of boiler-plate configuration and your custom bean factory can create all of your beans and have Spring resolve them successfully.
You should be able to achieve this using:
<bean id="myCreatedObjectBean" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass">
<value>com.mycompany.MyFactoryClass</value>
</property>
<property name="targetMethod">
<value>myFactoryMethod</value>
</property>
</bean>
Then you can use either #Resource or #Autowired + #Qualifier to inject into your object directly.

Resources