Spring+JPA #Transactional not committing - spring

I understand the similar question have been asked before here, but I couldn't find the solution to my problem. Basically, I am trying to use JPA through Hibernate in Spring, but the data is not being persisted for some reason.Turning on debug on spring transaction reveals nothing - EntityManager open and closed, but nothing shows up as far as transaction manager concerns ... I am sure I miss something big, any help is appreciated! see the following for more details.
TIA
Oliver
The basic layout is as follows: class FooDaoJPA’s save function calls out entityManager.persist(object) to persist the object.
class FooServiceImpl implements the service interface by:
#Transactional(rollbackFor = DataAccessException.class,
readOnly = false, timeout = 30,
propagation = Propagation.SUPPORTS,
isolation = Isolation.DEFAULT)
public void saveFoo(Foo foo) throws DataAccessException {
fooDao.save(foo);
}
Noted that fooDao is injected by Spring IoC
Finally controller is injected a FooService and call saveFoo() to persist data.
JPA configuration
<!-- JPA Entity Manager Factory -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:dataSource-ref="feDataSource"/>
<!-- Transaction Config -->
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="entityManagerFactory"/>
<tx:annotation-driven mode="aspectj"
transaction-manager="transactionManager"/>

Note the mode="aspectj" in your configuration. It requires additional configuration and usually you shouldn't use it unless you understand what does it mean and why do you need it. See 10.5.6 Using #Transactional.

The first thing that looks like a potential issue is your setting for propagation. Here is documentation showing the values you can specify:
http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/transaction/annotation/Propagation.html
Note that you've specified SUPPORTS which "Support a current transaction, execute non-transactionally if none exists". You probably want REQUIRED, which is the default, and will either use an existing transaction or create one if one does not currently exist.

In my case:
Using JPA with Spring MVC - all of my tests and code ran fine without error - symptom was that commits would simply not save to the database no matter what I tried.
I had to add
to my applicationContext.xml and cglib-nodep-2.1_3.jar aopalliance-1.0.jar
Definitely the fix in my case. Without annotation-driven Spring will not scan for the #Transactional annotation

Related

singleton="false" is no longer supported in Spring 4.3.8. Need solution

We are upgrading from Spring 3.2.4 to Spring 4.3.8 in which singleton="false" is no longer supported. What is the way to set singleton 'false' in Spring 4.3.8?
If singeton="false" then does it means that spring bean scope has become "Prototype"?
You can use #Scope for specifying prototype bean.
Example:
#Bean #Scope("prototype")
public Person personPrototype() {
return new Person();
}
for further reading follow link
As far as I remember, singleton=false was kept for some compatibility reasons, also indicated in some older docs, eg 3.0.0.M3:
<bean id="accountService" class="com.foo.DefaultAccountService"/>
the following is equivalent, though redundant (singleton scope is the default); using spring-beans-2.0.dtd
<bean id="accountService"> class="com.foo.DefaultAccountService" scope="singleton"/>
the following is equivalent and preserved for backward compatibility in spring-beans.dtd
<bean id="accountService"> class="com.foo.DefaultAccountService" singleton="true"/>
Anyway, the default spring scope is singleton, so even when unspecified, but can be changed to prototype (or whatever you need) with:
XML: scope="prototype"
Java DSL: #Scope("prototype") or #Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
Correct, scope="prototype" is the direct equivalent of singleton="false".
The equivalent of singleton="false" is scope="prototype".
another alternative is to use the annotation #Scope("prototype")
The equivalent of singleton="true" would be to eliminate this attribute in the spring config, since scope="singleton" would be the default.

Activiti JNDI Datasource Configuration

I am installing Activiti 5.17.0's Activiti Explorer and would like to use a JNDI-based datasource configuration to connect to an Oracle DB. The documentation I found here: http://www.activiti.org/userguide/#jndiDatasourceConfig is very explicit about making this change but unfortunately the docs seems to be obsolete.
In particular, I found no activiti-standalone-context.xml and no activiti-context.xml at the mentioned places. I assume it got changed to activiti-custom-context.xml, but the whole content of this Spring configuration is commented out (which makes me wonder where the actual Spring config might come from).
I tried to configure the datasource in this file anyway using this approach:
<jee:jndi-lookup id="dataSource"
jndi-name="jdbc/activiti-ds"
expected-type="javax.sql.DataSource" />
and this approach as well:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="proxyInterface" value="javax.sql.DataSource"/>
<property name="jndiName"><value>jdbc/activiti-ds</value></property>
</bean>
but both my attempts ended up in the same ClassCastException, claiming that the generated Proxy class is not an instance of javax.sql.DataSource:
java.lang.ClassCastException: org.springframework.jndi.JndiObjectFactoryBean$$EnhancerBySpringCGLIB$$69ba43af cannot be cast to javax.sql.DataSource
at org.activiti.explorer.conf.ActivitiEngineConfiguration$$EnhancerBySpringCGLIB$$5db7207e.dataSource(<generated>)
at org.activiti.explorer.conf.ActivitiEngineConfiguration.processEngineConfiguration(ActivitiEngineConfiguration.java:91)
Any hints how to accomplish to this task? Maybe a pointer to an up-to-date documentation?
For further reference, I solved the problem by editing the Spring JavaConfig in ActivitiEngineConfiguration.java and replacing the dataSource bean creation there with the following code:
#Bean
public DataSource dataSource() {
final JndiDataSourceLookup dsLookup = new JndiDataSourceLookup();
dsLookup.setResourceRef(true);
DataSource dataSource = dsLookup.getDataSource("jdbc/activiti-ds");
return dataSource;
}
After recompiling the module and deploying, it seems to work flawlessly.
Thanks a lot to Greg Harley above whose questions and commented helped to solve the problem!
The Activiti users guide includes updated instructions for how to configure a JDBC datasource here: http://www.activiti.org/userguide/#jndiDatasourceConfig
You will need to configure a datasource bean in the ActivitiEngineConfiguration class of your web application and update the following line of code to reference your new datasource:
processEngineConfiguration.setDataSource(dataSource());
If you want to continue to use the Spring XML configuration, you can still define your custom beans in the activiti-custom-context.xml.

Using Spring+Hibernate for testing purposes

I want to clarify my problem a bit more:
I understand the purposes of using SPring Framework (i.e. container-managed object lifecycle) and also Hibernate (using ORM between Javaobjects and relational database systems - impedance mismatch resolution).
I understand how we autowire an object and Spring takes over the creation and destruction of the object during runtime by looking at the applicationContext.xml file (in addition to persistence.xml file if using Hibernate or any other persistence provider).
What I want to do is the following:
I would like to implement my own shopping service. I already have entity (item) annotated with #Table, #Id, #Column, etc. to tell JPA that this is what will be stored in the database.
I already have a DAO interface (currently only add and delete methods) implemented by a DaoImpl class where I have done the following:
#Repository
#Transactional
public class MyShopDbDaoImpl implements MyShopDbDao {
// The following named unit will be in my persistence.xml file
// Which will be placed in src/main/resources/META-INF folder
#PersistenceContext(unitName="myShopDbDao")
private EntityManager em;
// Getters for em (simply returns em)
// Setters for em (simply assigns an em supplied in the args.)
// Other query method
}
I also have a ShopDbController controller class that uses:
#Autowired
// defined in the applicationContext.xml file
private MyShopDbDao myShopDbDaoImpl
What I am struggling with is the "Understanding" of EntityManagerFactory and EntityManager relationships along with how the transactions must be managed. I know that the following hierarchy is the main starting point to understand this:
Client talks to a controller.
Controller maps the request and gets the entitymanager to do queries and stuff to the database (either a test/local database with JUNIT test etc. or an actual SQL-type database).
What I do know is that transactions can be managed either manually (i.e. beginning, committing, and closing a session) or through Spring container (i.e. using bean defs in applicationContext.xml file). How can I get more information about the entitymanagers and entitymanagerfactory in order to setup my system?
I didn't find the online documentation from Oracle/Spring/Hibernate very helpful. I need an example and the explanation on the relationship between entitymanagerfactory, sessionfactory, entitymanager, and transactionmanager. Could someone please help me with this?
I don't need people to hold my hand, but just put me in a right direction. I have done Spring projects before, but never got to the bottom of some stuff. Any help is appreciated.
EntityManagerFactory will obtain java.sql.Connection objects, through opening/closing new physical connections to the database or using a connection pool (c3p0, bonecp, hikari or whatever implementation you like). After obtaining a Connection, it will use it to create a new EntityManager. The EntityManager can interact with your objects and your database using this Connection and can manage the transaction through calling EntityManager#getTransaction and then calling EntityTransaction#begin, EntityTransaction#commit and EntityTransaction#rollback that internally works with Connection#begin, Connection#commit and Connection#rollback respectively. This is plain vanilla JPA and Spring has nothing to do up to this point.
For transaction management, Spring helps you to avoid opening/closing the transactions manually by using a transaction manager, specifically a class called JpaTransactionManager. This transaction manager will make use of your EntityManagerFactory to open and close a transaction for the EntityManager created for a set of operations. This can be done either using XML configuration or #Transactional annotation on your classes/methods. When using this approach, you won't directly work with your specific classes anymore, instead Spring will create proxies for your classes using cglib and make use of the transaction manager class to open the transaction, call your specific method(s) and execute a commit or rollback at the end, depending on your configuration. Apart of this, Spring provides other configurations like read-only transactions (no data modification operation allowed).
Here's a basic configuration of the elements explained above using Spring/Hibernate/JPA:
<!--
Declare the datasource.
Look for your datasource provider like c3p0 or HikariCP.
Using most basic parameters. It's up to you to tune this config.
-->
<bean id="jpaDataSource"
class="..."
destroy-method="close"
driverClass="${app.jdbc.driverClassName}"
jdbcUrl="${app.jdbc.url}"
user="${app.jdbc.username}"
password="${app.jdbc.password}" />
<!--
Specify the ORM vendor. This is, the framework implementing JPA.
-->
<bean id="hibernateVendor"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
showSql="false"/>
<!--
Declare the JPA EntityManagerFactory.
Spring provides a class implementation for it.
-->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
persistenceXmlLocation="classpath*:META-INF/persistence.xml"
persistenceUnitName="hibernatePersistenceUnit"
dataSource-ref="jpaDataSource"
jpaVendorAdapter-ref="hibernateVendor"/>
<!--
Declare a transaction manager.
Spring uses the transaction manager on top of EntityManagerFactory.
-->
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager"
entityManagerFactory-ref="entityManagerFactory"/>
From what i see, your em reference should be a functioning proxy object to your database (this EntityManager is the thing that should be a spring bean, having configured everything, like DB url, driver, etc. Apart from this none of your code should depend on what DB you have). You don't need to know about the classes you mention (entitymanagerfactory sessionfactory transactionmanager). Easy example is:
List<MyBean> bean = (List<MyBean>)em.createNamedQuery("select * from mydb").getResultList();
It should be this easy to run a select * query and get your MyBean typed objects straight ahead, without any explicit conversion by you (this is what hibernate is for).
Similar for insert:
em.persist(myBean);
where myBean is something annotated for Hibernate.
Briefly about transactions, i found best to annotate #Transactional on service METHODS (you did it on a whole dao).
To be very very general:
an entitymanagerfactory is an object responsible of the creation of the entitymanager and it comes from the JPA specifications.
SessionFactory is the hibernate implementation of entitymanagerfactory
session is the hibernate implementation of entitymanager
A transacation manager is an object who manages transaction when you want to define a transaction manually.
So if you want to use hibernate, use SessionFactory and session. And if you want you to stay "generic" use the EntityManagerFactory.
http://www.javabeat.net/jpa-entitymanager-vs-hibernate-sessionfactory/
http://www.theserverside.com/tip/How-to-get-the-Hibernate-Session-from-the-JPA-20-EntityManager

spring testing: Another CacheManager with same name 'myCacheManager' already exists in the same VM

Before you mark this as duplicate please read the question first. I've read all the stuff about this exception however it does not solve the issue for me. And I do get a slightly different exception eg Another CacheManager with same name 'myCacheManager' already exists instead of Another unnamed CacheManager already exists.
Spring config:
<cache:annotation-driven cache-manager="cacheManager"/>
<bean id="cacheManager"
class="org.springframework.cache.ehcache.EhCacheCacheManager"
p:cacheManager-ref="ehcache"/>
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:configLocation="ehcache.xml"
p:cacheManagerName="myCacheManager"
p:shared="true"/>
ehcache
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false" name="myCacheManager">
</ehcache>
The Problem is that I have 1 (in the future more) test classes that test security. these classes also load a SecurityContext.xml
So most test classes have this annotations:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:ApplicationContext.xml")
However the class causing the issue:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {
"classpath:ApplicationContext.xml",
"classpath:SecurityContext.xml"
})
It seems since locations are different the context is loaded again but ehcacheManager is still active from previous test.
Note: this happens only when running multiple tests (eg. like clean + build). Running this test class separately works perfectly fine.
Whats the issue? How can I solve it?
Add #DirtiesContext annotation to your test class:
#ContextConfiguration(...)
#RunWith(...)
#DirtiesContext // <== add e.g. on class level
public class MyTest {
// ...
}
This annotation indicates that the application context associated with a test is dirty and should be closed. Subsequent tests will be supplied a new context. Works on class-level and method-level.
I don't know if the question/issue are still relevent, but here's a simple/proper solution (Don't need to add #DirtiesContext in all your tests). Avoid #DirtiesContext allows you to have only one shared context for all integration tests (via run by maven for example, or run all tests in an IDE). That avoids multiple problems caused by multiple contexts started in same times.
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:configLocation="ehcache.xml"
p:cacheManagerName="myCacheManager"
p:shared="${ehcacheManager.shared:true}"
p:acceptExisting:"${ehcacheManager.acceptExisting:false}"/>
In your tests (integration tests), set those properties
ehcacheManager.acceptExisting=true
ehcacheManager.shared=false
It allows Spring to create an EhcacheManager (ehcache) for each test, but if an
EhcacheManager with the same name exist, Spring will just reuse it. And Spring will also not destroy/shutdown it in the context annotated with #DirtiesContext.
The idea is simple, you prevent the destroy of EhcacheManager when using #DirtiesContext.
It's applicable if you use Spring 4 and EhCache:2.5+. With Spring 3, you must an extends of EhCacheManagerFactoryBean to add these two properties.
Don't forget to clear your cache before each test :)
You can run your tests with caching disabled even if your code has methods with #Cacheable annotations.
That way you do not have to slow your test run down by marking all of your tests with #DirtiesContext.
Put the cache related Spring configurations in their own Spring config file, eg. applicationContext-cache.xml file.
Include that applicationContext-cache.xml file only when running the application live, but not in your tests.
If you specifically want to test caching, then you need the #DirtiesContext annotation.
This happens because during testing, there are ultiple Spring application contexts existing at the same time. However, ehcache is JVM-global.
You can essentially disable Spring context caching, by creating spring.properties file on your classpath:
spring.test.context.cache.maxSize=1
Make sure that the cache manager is properly unregistered when a context is destroyed.
This solved my testing issue:
spring.cache.type=none
Slightly longer version:
Julien Dubois:
I would just do spring.cache.type=none as:
it's much simpler
it would work as in the previous versions
I prefer to have the cache disabled when I do my tests - then of
course there could be a very long discussion here - so that's also my
favorite solution.
Detailed version (not exactly same, but similar issue):
Read this.

No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here

I have problem with:
No Hibernate Session bound to thread, and configuration does not allow
creation of non-transactional one here
when testing my project.
I use Spring 2.0.7(this is must in that project) and Hibernate 3. I have
SessionFactory defined
Transaction manager defined(with session factory injected)
<tx:annotation-driven transaction-manager="transactionManager"/> -
annotations for transactions switched on
I have annotated my tests with:
#Test
#Transactional
and inherited AbstractAnnotationAwareTransactionalTests
=> I got this error:No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
Only way I can overcome it is to use: TransactionStatus transaction = transactionManager.getTransaction(transactionDefinition);
in test before I call
sessionFactory.getCurrentSession().save(myObject);
Any suggestions? Or better: how it works? Why it can not create transactional session ? Why no hibernate session is bound ? I have read something about it but it is still not clear to me. I think that I did everything to make it working but obviously it was not sufficient.
Thx in advance,
Stepik
I think the problem consist in that you extend your class from AbstractAnnotationAwareTransactionalTests. Try to remove inheritance (it should work without it). Or try to extend your class from AbstractTransactionalJUnit4SpringContextTests class.
You can look here at similar post.
In my case a base-package was missed. One like:
<context:component-scan base-package="com.companyname" />

Resources