I'm new to Spring and I'm wondering if its possible to use numerous transaction managers in the same application?
I have two data access layers - one for both of the databases. I'm wondering, how do you go about using one transaction managers for one layer and different transaction manager for the other layer. I don't need to perform transactions across both databases - yet. But I do need perform transactions on each database individually. I've created an image to help outline my problem:
Here is my application context configuration:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/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.0.xsd">
<context:component-scan base-package="cheetah.repositories" />
<tx:annotation-driven />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="accounts" />
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
</beans>
Here is an example that uses this configuration:
#Repository
public class JpaAccountRepository implements AccountRepository {
#PersistenceContext(unitName = "cheetahAccounts")
private EntityManager accountManager;
#Override
#Transactional
public Account findById(long id) {
Account account = accountManager.find(Account.class, id);
return account;
}
}
So for the account repository, I want to use an entity manager factory with the persistence unit set to accounts. However, with my BusinessData Repository, I want to use an entity manager factory with a different persistence unit. Since I can only define one transaction manager bean, how can I go about using different transaction managers for the different repositories?
Thanks for any help.
Where you use a #Transactional annotation, you can specify the transaction manager to use by adding an attribute set to a bean name or qualifier. For example, if your application context defines multiple transaction managers with qualifiers:
<bean id="transactionManager1"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory1" />
<qualifier value="account"/>
</bean>
<bean id="transactionManager2"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory2" />
<qualifier value="businessData"/>
</bean>
You can use the qualifier to specify the transaction manager to use:
public class TransactionalService {
#Transactional("account")
public void setSomethingInAccount() { ... }
#Transactional("businessData")
public void doSomethingInBusinessData() { ... }
}
This Spring Jira entry discusses the issue a bit:
https://jira.spring.io/browse/SPR-3955
I think it could be one transaction manager per connection if you're not using two-phase commit. You just need to create two transaction managers and inject them with the appropriate connection.
But I must ask the question: why do you think you need two transaction managers? You can have more than one database connection. The DAOs that use the connections can and should be instantiated by different services, each of which can be annotated with their own transactional settings. One manager can accommodate both. Why do you think you need two?
Related
I opened a question some hrs ago, which got marked as a duplicate, however it was not a duplicate of the marked question, whatever.
Since then, I managed to get some things done, and work stuff out, so here is my question:
I was trying to #Autowire a spring bean into another one, however my problem was that the #Autowired field was always null, depsite of the fact that they were both managed beans and worked correctly by themselves.
I found out, that you can reach the ApplicationContext in a bean by implementing the ApplicationContextAware interface, which I did. It was called and the right context was given to it.
This way, I can call getBean() on the context, which returns the bean I wanted to #Autowire in the first place, which is a yaay, but this seems like a workaround for a bigger problem.
Can you help me what might be wrong? I tried #Autowiring both as field, method and constructor parameter, none worked. These beans are both singleton beans and are used as basis for HesianServiceExporter, in order to reach them from another servlet.
I guess is I'm missing some crucial config information here, but I can't see why a field injection would not work, while at the same time an interface implementation does.
Is it a case, where the bean which I want to #Autowire is not ready yet, so it can't be injected?
As some of you requested, here is my code. Don't know how it helps, but:
#Service(Persistence.NAME)
public class PersistenceBean implements Persistence, ApplicationContextAware {
ApplicationContext context;
#Override
public User getUser() {
User user = new User();
user.setEmail(context.getBean(HelloWorld.class).getText());
return user;
}
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
}
And my context.xml:
<?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: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.xsd
http://www.springframework.org/schema/context https://www.springframework.org/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<context:annotation-config />
<context:component-scan base-package="hu.bme.sch.qpa" annotation-config="true"/>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource"
ref="dataSource"/>
<property name="packagesToScan"
value="hu.bme.sch.qpa.global.entities"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">
update
</prop>
<prop key="hibernate.dialect">
org.hibernate.dialect.PostgreSQL95Dialect
</prop>
</props>
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="url" value="jdbc:postgresql://localhost:5432/test"/>
<property name="username" value="qpapp_server_user"/>
<property name="password" value="root"/>
</bean>
<bean id="txManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:annotation-driven/>
<bean id="persistenceExceptionTranslationPostProcessor" class=
"org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
</beans>
And lastly, my ApplicationInitializer is annotated like this:
#ImportResource("/WEB-INF/app-core-servlet.xml")
#SpringBootApplication(scanBasePackages = "hu.bme.sch.qpa")
#EnableWebMvc
#Configuration
#EnableAutoConfiguration
public class CoreStarter extends SpringBootServletInitializer {
public static void main(String[] args) throws Exception {
SpringApplication.run(CoreStarter.class, args);
}
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
}
}
And here is HelloWorld bean, which is (what the name would suggest) a really simple bean. It's in the same package as PersistenceBean:
#Service(HelloWorld.NAME)
public class HelloWorldBean implements HelloWorld {
#Override
public String getText() {
return "Hello World!!!! I'm remoted";
}
}
Thanks in advance.
Okay, I got it... Boy did it took some time.
So, as it turns out, the context I described didn't include the one that caused the problem, but I didn't want to spam the thread with my whole module.
The missing part is that I'm remoting these beans, just and only the ones that have trouble with Autowiring (I didn't know that at the time).
The way I remoted them was I wrote an implementation to the BeanDefinitionRegistryPostProcessor.
The problem with this was that I instantiated the remote beans as soon as the function of the interface got invoked, which means: before Spring normally would instantiate the beans I want to remote => too early.
Me calling the getBean() too early meant that at the of instantiating the bean, the AutowiredCapableBeanPostProcessor (or sg. like this) was not registered in the list of factories and I didn't have control of it either.
===================================TL;DR=================================
The solution was that in the Remote Exporter bean, when the postProcessBeanDefinitionRegistry() function got invoked, I just simply saved the Registry, and implemented the InstantiationAwareBeanPostProcessor and did the actual remoting when postProcessAfterInstantiation() got invoked => When the bean has been instantiated the "normal" way => the Autowiring will be done, as well as the remote bean will be created.
Sorry for stealing your time, I really appreciate it.
When using spring and spring data jpa in a normal java application how will jpa know when to commit the data to the database?
I ask this because repository.save() doesn't commit.
Should i manually commit or can spring handle this for me?
My application context xml:
<context:component-scan base-package="...">
</context:component-scan>
<jpa:repositories base-package="..." entity-manager-factory-ref="emf" />
<bean id="emf" class="...spring.MyEMF"></bean>
<!-- Add Transaction support -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf" />
</bean>
<!-- Use #Transaction annotations for managing transactions -->
<tx:annotation-driven transaction-manager="transactionManager" />
I manually init my context with:
new ClassPathXmlApplicationContext("classpath:/data.xml")
No spring can handle transaction for you just before your method repository.save() add #Transactional
#Transactional
public void save(){
//do something
}
and in your configuration class make sure that spring transaction handling is enabled
#EnableTransactionManagement
class myConfig{
}
I'm currently getting started on a project that uses spring-data in combination with JPA/Hibernate.
Right now, I'm injecting JpaRepositories using #Autowired annotations on the properties in question, e.g.:
#Component
public class EmployeeGenerator implements IDataGenerator {
...
#Autowired
private IEmployeeDao dao;
...
}
.. where IEmployeeDao is an interface extending JpaRepository that is annotated as #Repository:
#Repository
public interface IEmployeeDao extends JpaRepository<Employee, Integer> {
/**
* Finds employees by username.
*
* #param username the username
* #return the list of employees
*/
List<Employee> findByUsername(String username);
Everything works fine using this approach - However, I'm rather used to doing most of my spring configuration work in XML because I personally like the idea of all relevant confguration being in the same place and visible at the first glance.
Now, as far as I understand JPA and spring-data, the repository instances are somehow created by the JPA entity manager, so I should be able to specify them as beans in the spring config xml using.. some kind of factory method?
I guess I'm looking for something along the lines of:
<import resource="classpath:spring/db-context.xml"/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="..."/>
<property name="dataSource" ref="..."/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.connection.charSet">UTF-8</prop>
</props>
</property>
</bean>
...
<bean id="employeeDaoImpl" class="IEmployeeDao">
<factory-method="?????"> <!-- Is something like this possible??? -->
</bean>
After some reading I guess that autowiring the repositories is the "recommended" approach, and I do see some benefits doing it like that,
but still, out of interest, I'd like to get it working with pure-xml configuration (or at least without #Autowired, that is)
You can declare the repositories using <jpa:repositories />. Then you can use the repository references in your XML configuration.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<repositories base-package="com.acme.repositories" />
</beans:beans>
In this case we instruct Spring to scan com.acme.repositories and all its sub packages for interfaces extending Repository or one of its sub-interfaces. For each interface found it will register the persistence technology specific FactoryBean to create the according proxies that handle invocations of the query methods. Each of these beans will be registered under a bean name that is derived from the interface name, so an interface of UserRepository would be registered under userRepository. The base-package attribute allows the use of wildcards, so that you can have a pattern of scanned packages.
You can read more about it in the docs: http://docs.spring.io/spring-data/jpa/docs/1.3.0.RELEASE/reference/html/repositories.html#repositories.create-instances
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
I looked around for similar problems but couldn't find a solution for this:
I have a Spring Data JPA application that whenever I try to do a trasaction I get javax.persistence.TransactionRequiredException: no transaction is in progress.
I believe it has something to do with the Transaction Manager or Entity Manager Factory, but can't put my finger on it.
The context files are here (latest checked in are here), but here is the part that matters:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSourceMySQL" />
<property name="persistenceUnitName" value="spring-jpa" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="true" />
<property name="showSql" value="true" />
<property name="database" value="MYSQL" />
</bean>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSourceMySQL"/>
</bean>
<bean id="dataSourceMySQL" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/dbname"/>
<property name="username" value="user"/>
<property name="password" value="pass"/>
</bean>
<jpa:repositories base-package="com.simplecash.dal.repository" />
A sample Repository is here and then created a Repository Factory here, which I'm not sure if I need...
Then use it here (line 34).
public void populateWithTestData() {
Bank bank = new Bank();
bank.setName("ContentName");
bank.setCode("ContentCode");
RepositoryFactory.getEntityManager().getTransaction().begin();
BankRepository bankRepository = RepositoryFactory.getRepository(BankRepository.class);
bankRepository.save(bank);
bankRepository.flush();
RepositoryFactory.getEntityManager().getTransaction().commit();
}
A couple of things are wrong above, but I I've tried fixing it and can't:
Begin and Commit transactions are explicit.
bankRepository should be #Autowired, but when I do that I get null. However, in this testcase it is Autowired and works.
Has anyone faced a similar problem and knows what's going on?
Thanks a ton for taking the time to read this. Hope the answer to this question will help other folks.
Both answer provided here offer good points (using injection to get the proxied beans and using transaction-annotations), however, I'm pretty sure that for the annotation-driven transactions to work (#Transactional), you need to add the following to your xml-configuration:
<tx:annotation-driven transaction-manager="transactionManager"/>
Also make sure to add the tx-namespace in your beans-tag:
<beans
<!-- SNIP, other namespaces -->
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
<!-- SNIP, other locations -->
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
I think that in your setup the Transactions are managed by JTA, so you can't explicitly start/stop them (i.e. em.getTransaction().begin() will not work). Try telling Spring that you want a certain method to be part of a (JTA managed) transaction via annotation , like:
#Transactional
public void populateWithTestData() {
//...
}
Begin and Commit transactions are explicit.
What Spring does with your repository beans ( e.g. BankRepository ), it creates a proxy around it, and then it is ready to be injected into other collaborators, which in your case is DatabaseManagerDAO. However if you create the object yourself like you do:
BankRepository bankRepository = RepositoryFactory.getRepository(BankRepository.class);
Instead of expected Spring's proxy ( that already does transaction management for you ), you are getting a simple object that is not aware of anything beyond it is immediate declaration.
What you need to do instead is to trust Spring to do the plumbing for you and just inject a bankRepository bean into a DatabaseManagerDAO (although I don't really think you need both DAO and Repository, since those terms really mean the same thing :)
Repository Factory here, which I'm not sure if I need...
No need for another abstraction. Just inject it as a bean to whatever component needs it.
bankRepository should be #Autowired, but when I do that I get null. However, in this testcase it is Autowired and works.
In a case where it works you run your test with AbstractTransactionalJUnit4SpringContextTests, which knows about 'bankRepository' bean, hence autowires it. In your DatabaseManagerDAO, I see neither autowiring nor a setter for the bankRepository, in fact you create it manually from the factory.
EDIT to answer comments
What jpa:repositories in your XML config really does => it scans the package and creates Spring beans for each component that is either annotated as #Repository or implements a Repository interface.
With that in mind, what you should do in order to use a BankRepository repository in your DatabaseManagerDAO is to inject it. You can do it via "autowiring":
#Service
public class DatabaseManagerDAO {
#Autowired
BankRepository bankRepository;
...
}
instead of manually creating it trough your factory.
Again, DatabaseManagerDAO in your case is probably a service ( #Service ), and not a DAO, but I'll leave it up to you to decide on that.
Notice that a DatabaseManagerDAO should also be loaded by Spring in order for the autowiring to work, so make sure it has one of the Spring annotations ( #Service / #Component ) when you package scan it ( e.g. <context:component-scan base-package="org.example"/> ).
I had a similar issue when combining spring-batch and spring-jpa. In my batch XML, I had this line:
<bean id="transactionManager" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager"/>
which caused an error since JPA needs a PlatformTransactionManager.