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

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

Related

Wiring multiple beans with the same dependency via Spring Boot #Configuration

In older Spring MVC apps, where you'd specify application.xml and declare your app's beans so that Spring DI could instantiate them and wire them together, you might have something like this:
<bean id="chargeFactory" class="com.example.myapp.ChargeFactory" />
<bean id="paymentService" class="com.example.myapp.DefaultPaymentService">
<ref id="chargeFactory"/>
</bean>
<bean id="chargeAuditor" class="com.example.myapp.ChargeAuditor">
<ref id="chargeFactory"/>
</bean>
Which might help wire up the following code:
public interface PaymentService {
public void makePayment(Payment payment);
}
public class DefaultPaymentService implements PaymentService {
#Autowired
private ChargeFactory chargeFactory;
#Override
public void makePayment(Payment payment, String key) {
Charge charge = chargeFactory.createCharge(key);
charge.doCharge(payment);
}
}
public class ChargeAuditor {
#Autowired
private ChargeFactory chargeFactory;
public void auditAllCharges(String key) {
List<Charge> charges = chargeFactory.getAllCharges(key);
// blah whatever
}
}
How do you accomplish the same bean wiring in Spring Boot with the #Configuration class? For example:
#Configuration
public class MyAppInjector {
#Bean
public ChargeFactory chargeFactory() {
return new ChargeFactory();
}
#Bean
public PaymentService paymentService() {
return new DefaultPaymentService(chargeFactory());
}
#Bean
public ChargeAuditor chargeAuditor() {
return new ChargeAuditor(chargeFactory());
}
}
This might work but introduces some issues:
It would force me to have to write value constructors for all my classes, which goes against everything I see in literally every tutorial/article I've come across. Plus, if I had to do that, then there's no real value to #Autowired anyways...
At this point I'm essentially doing "DIY DI", which is OK, except I'm trying to deliberately use Spring DI :-)
Every time I call chargeFactory() I'm getting a new (prototype-style) ChargeFactory instance. Maybe I want a singleton. Using this approach I have to hand-roll my own singleton implementation.
Sure, I can do all of this, but I feel like I'm flagrantly misusing/misunderstanding how #Configuration is supposed to be used, because it seems like I'm introducing a whole lot of DIY/homegrown code to solve something Spring DI should be able to do for me.
How would I reference the chargeFactory bean and wire it into both the "provider methods" for the paymentService and chargeAuditor beans? Again, looking for the Java-based #Configuration solution instead of writing an XML document to define the wirings.
I found this article which seems to be the only tutorial/documentation (surprisingly) on wiring Spring Boot apps via #Configuration (which leads me to believe there might be other/better methods...), but it does not address:
How to specify singleton vs prototype bean instantiation patterns
If multiple instances of a bean-class exist, how do I specify which instance gets wired into which dependency?
How do I get around not defining value constructors for all my classes, and just let Spring/#Autowired inject fields automagically?
When you call chargeFactory() , spring won't create new instance everytime. Give it a try and see. Same object will be returned. Anyways
You can do something like this.
#Bean
public PaymentService paymentService(ChargeFactory chargeFactory) { return new DefaultPaymentService(chargeFactory); }

What are advantages of spring DAOSupport

I read about Spring framework's DAOSupport classes. But I could not understand the advantages of these DAOSuport classes. In DAOSupport classes we call getXXXTemplate() method to get the specific template object and then use it further for DB access.
Even without extending DAOSupport we can inject XXXTemplate in our class.
Rest of this things will remain same.
Then what is advantage of extending DAOSupport class?
EDIT:- Adding example
Class extends spring's SimpleJdbcDaoSupport
public class JdbcDao extends SimpleJdbcDaoSupport {
public int create(Bb obj) {
getSimpleJdbcTemplate().update("insert into ..... ") //insert query
}
Bean of this class can be defined as :-
<bean id="jdbcDao" class="example.dao.support.JdbcDao">
<property name="dataSource"><ref local="dataSource"/></property>
</bean>
We can create a custom class without extending SimpleJdbcDaoSupport which will have property of type JdbcTemplate
public class MyDAO {
public myJdbcTemplate; // ant its getter and setter
public int create(Bb obj) {
getMyJdbcTemplate().update("insert into ..... ") //insert query
}
It's bean wil be defined as :-
<bean id="jdbcDao" class="MyDAO">
<property name="myJdbcTemplate"><ref local="jdbcTemplateBean"/></property>
</bean>
As you can see both classes do same thing. While extending SimpleJdbcDaoSupport we are injecting DataSource and without it we are injecting directly jdbcTemplate bean. That's it. No more difference.
So I do not see any much advantage with this much use of DAOSupport classes. Any additional functionality given by DAOSupport classes ?
When you use HibernateDAOSupport you can see the difference.
1. Config the transaction to optimize the performance of the application on the applicationContext :
select : read only
create/update : read and write.
You use one session only(with getHibernateTemplate() and the sessionFactory)
When we update some data on the database we do only merge the modifications whith the method impleted on HibernateDAOSupport.
There are many method already implemented on the DAOSupport and we can use this to our need.

"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;
}

EntityManager injected by Spring but null on first use

I am just working on a basic webapp that implements spring + hibernate entitymanager
I set up my dao and context exactly as described by this post:
http://blog.springsource.com/2006/08/07/using-jpa-in-spring-without-referencing-spring/
And created a test for it as shown here:
http://lstierneyltd.com/blog/development/examples/unit-testing-spring-apps-with-runwithspringjunit4classrunner-class/
For some reason when I try to access the entitymanager for creating a query, its null.
However from setting a breakpoint inside the setter method for the entitymanager I can see that Spring is injecting it correctly, and the field is being initialized.
Any clue as to why the entitymanager might be getting nullified after the setter has returned ?
Edit:
The dao code where I am setting the breakpoint:
public class ProductDaoImpl implements ProductDao {
private EntityManager entityManager;
#PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this. entityManager = entityManager;
}
public Collection loadProductsByCategory(String category) {
return entityManager.createQuery("from Product p where p.category = :category")
.setParameter("category", category).getResultList();
}
}
The <tx:annotation-driven/> that I presume you do have, tells Spring to put transactional advice on any class or method that has an #Transactional annotation on it.
Transactions should be defined on the Service/Business layer, hence your ProductDaoImpl is usually called from within a service, which will have #Transactional. e.g.
pubic class ProductService {
#Resource(...) // inject it the way you like e.g. #Autowired / Setter / Constructor injection, etc..
ProductDao yourProductDao;
#Transactional
public List<Product> findCarProducts {
yourProductDao.loadProductsByCategory( "car" );
}
}
(alternatively, you can use an XML based transaction configuration)
Now the actual call to your DAO will be within a transaction => which is very important for entityManager / Hibernate Session. Otherwise you'll see all the usual errors: e.g. entityManager is null, entityManager is closed, etc..
In case you'd like to test a DAO in solo, you have to make sure that your test case is wrapped within a transaction via #TransactionConfiguration. For example, if your transaction manager bean is defined as:
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
Your DAO test would include this bean name:
#ContextConfiguration
#TransactionConfiguration(transactionManager="txManager", defaultRollback=false)
public class ProductDaoTransactionalTests {
// your use cases here..
}
You can read more about transactional tests in Spring Documentation

Resources