I have a Transaction Manager injected with #PersistenceContext context annotation. Every time I'm trying to start the transaction with em.getTransaction().begin I got an exception with the error message
Transaction is not accessible when using JTA with JPA-compliant transaction access enabled
I know that I should inject UserTransaction or use #Transactional annotation but I want to know the reason for such behavior.
I think you should inject a container managed transaction.
Something like:
#Resource
private UserTransaction transaction;
public method() {
try {
transaction.begin();
...do some persistence...
transaction.commit();
} catch (Exception e) {
transaction.rollback();
}
}
OR
if you don't need such control you can use #Transaction annotation on your method.
Hope it helps.
I had the very same issue but problem lied elsewhere...
So the stack: I was using Wildfly server , postgresql, and JPA
At first, my persistence.xml was configured to use RESOURCE_LOCAL transactions e.g.
<persistence-unit name="unit" transaction-type="RESOURCE_LOCAL">
and I had a problem that even when the method was marked #Transactional it was not doing any rollbacks when error occured, yet saving worked fine.
So then I decided to use transaction-type JTA instead of RESOURCE_LOCAL so that the container manages the transactions.
When I changed my persistence.xml to this, it was still not working
<persistence-unit name="unit" transaction-type="JTA">
<jta-data-source>java:jboss/datasources/unit</jta-data-source>
and was throwing the very error that is in the title of this question.
My problem was, how I was creating the EntityManager, this is how it was defined
#Produces
#PersistenceContext
private static EntityManager em = Persistence.createEntityManagerFactory(UNIT_NAME).createEntityManager()
The solution? I had to remove the annotation #PersistenceContext
P.s. for JTA transactions do not forget to tell wildfly about the datasource for example via CLI like this
data-source add --jndi-name=java:jboss/datasources/unit --name=MyDb --connection-url=jdbc:postgresql://localhost:5432/postgres --driver-name=postgresql --user-name=username --password=password
I'm writing some junit tests for my Spring 3.2.8 + Hibernate 4.3.4 application. My test class is annotated with:
#DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD)
#Transactional
public class UserServiceImplTest {
...
...
}
However, I get the following error thrown by an aspect that is trying to use the entity manager:
org.springframework.dao.InvalidDataAccessApiUsageException: EntityManagerFactory is closed; nested exception is java.lang.IllegalStateException: EntityManagerFactory is closed
If I look at the logs, I see the following error message at the start of my second test:
2014-04-02 16:36:48,891 [main] WARN org.hibernate.jpa.internal.EntityManagerFactoryRegistry - HHH000436: Entity manager factory name (default) is already registered. If entity manager will be clustered or passivated, specify a unique value for property 'hibernate.ejb.entitymanager_factory_name'
I realize that it is just a warning, but I am wondering if this is part of the issue. I do not understand why it is complaining that the factory is already registered when the #DirtiesContext is supposed to ensure that the context is cleaned out before starting the second test.
I do see the context being cleaned up at the end of my first test:
2014-04-02 16:36:10,733 [main] INFO springframework.test.context.transaction.TransactionalTestExecutionListener - Rolled back transaction after test execution for test context [TestContext#1ff221ad testClass = UserServiceImplTest, testInstance = com.ia.service.UserServiceImplTest#5180f53d, testMethod = testUpdateRoles#UserServiceImplTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration#6964a198 testClass = UserServiceImplTest, locations = '{classpath:META-INF/spring/applicationContext*.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{test}', resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.test.context.web.WebDelegatingSmartContextLoader', parent = [null]]]
2014-04-02 16:36:10,735 [main] INFO springframework.web.context.support.GenericWebApplicationContext - Closing org.springframework.web.context.support.GenericWebApplicationContext#53c3dcdc: startup date [Wed Apr 02 16:35:00 EDT 2014]; root of context hierarchy
2014-04-02 16:36:10,736 [main] INFO springframework.beans.factory.support.DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#2ff0a910: defining beans [dataSource,entityManagerFactory,org.springframework.transaction.config.internalTransactionAspect,hibernateJpaVendorAdapter,transactionManager,org.springframework.data.repository.core.support.RepositoryInterfaceAwareBeanPostProcessor#0,org.springframework.data.jpa.repository.support.EntityManagerBeanDefinitionRegistrarPostProcessor#0,org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor#0,rateRepository,userRepositoryImpl,userRepository,patchRepository,org.springframework.security.filterChains,org.springframework.security.filterChainProxy,org.springframework.security.web.DefaultSecurityFilterChain#0,org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler#0,org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource#0,org.springframework.security.access.vote.AffirmativeBased#0,org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor#0,org.springframework.security.methodSecurityMetadataSourceAdvisor,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.security.web.PortMapperImpl#0,org.springframework.security.web.PortResolverImpl#0,org.springframework.security.config.authentication.AuthenticationManagerFactoryBean#0,org.springframework.security.authentication.ProviderManager#0,org.springframework.security.web.context.NullSecurityContextRepository#0,org.springframework.security.web.savedrequest.NullRequestCache#0,org.springframework.security.access.vote.AffirmativeBased#1,org.springframework.security.web.access.intercept.FilterSecurityInterceptor#0,org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator#0,org.springframework.security.authentication.AnonymousAuthenticationProvider#0,org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint#0,org.springframework.security.userDetailsServiceFactory,org.springframework.security.web.DefaultSecurityFilterChain#1,org.springframework.security.authentication.dao.DaoAuthenticationProvider#0,org.springframework.security.authentication.DefaultAuthenticationEventPublisher#0,org.springframework.security.authenticationManager,basicAuthenticationFilter,authenticationEntryPoint,defaultWebSecurityExpressionHandler,org.springframework.context.support.PropertySourcesPlaceholderConfigurer#0,org.springframework.context.config.internalBeanConfigurerAspect,contactDataOnDemand,userDataOnDemand,testBase.BeanRegistry,securityService,patchServiceImpl,rateServiceImpl,userServiceImpl,appConfig,viewConfig,webContextFilter,patchEngineContextListener,patchEngineImpl.PatchEngineInitializer,patchEngineImpl,initializeUsersRolesAndPermissionsPatch,tilesContainerFactory,viewMetaPreparer,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,applicationProperties,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor,org.springframework.data.auditing.AuditingHandler#0,org.springframework.data.jpa.domain.support.AuditingEntityListener,org.springframework.data.jpa.domain.support.AuditingBeanFactoryPostProcessor,org.springframework.data.auditing.AuditingHandler#1,auditorProvider,objectMapper,org.springframework.orm.jpa.SharedEntityManagerCreator#0]; root of factory hierarchy
2014-04-02 16:36:10,754 [main] INFO org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean - Closing JPA EntityManagerFactory for persistence unit 'default'
so I am not sure why it is complaining that the EntityManagerFactory is already registered. Furthermore, I am not sure why the EMF is closed when I am trying to access it.
Do I need to do something special to ensure that it is still accessible in each test? I did find this post on SO that relates to the issue, but doesn't help me nail down why this is happening.
It turns out after much debugging that the problem is in the aspect that is using the EntityManagerFactory. Given that the aspect is instantiated outside the Spring context, when the context is refreshed, the aspect's references are not updated. Consequently, the aspect is holding a reference to an EMF that is indeed closed - the original EMF from the first unit test. Now I just have to figure out how to get Spring to update/refresh the references when the context is updated.
Seems that something try to get a persistence context before the spring context was set up or after it was disposed.
Don't you have some junit #before or #after annotated method which accesses the persistence ?
Can #PersistenceUnit be used with JTA in JPA? If so, how is it possible?
Per http://tomee.apache.org/jpa-concepts.html:
With <persistence-unit transaction-type="RESOURCE_LOCAL"> [...]
You must use the EntityManagerFactory to get an EntityManager
[...]
An EntityManagerFactory can be injected via the #PersistenceUnit annotation only (not #PersistenceContext)
With <persistence-unit transaction-type="JTA"> [...]
An EntityManager can be injected via the #PersistenceContext annotation only (not #PersistenceUnit)
I have a similar code which uses JTA and #PersistenceUnit at the same time. But sometimes I am having NullPointerException when accesing transaction (defined as #Resource).
Using JTA means that you delegate the work to the container. You can override it by using a UserTransaction. Your quotation contains all the answers you want to know. Using PersistenceUnit to get an EntityManager won't work.
If you are using RESOURCE_LOCAL you are responsible for the transaction itself, by using EntityManager.getTransaction(). An entity manager is created by an EntityManagerFactory. To obtain that factory, you can use PersistenceUnit.
So the simple answer is no, if you rely on container managed entity managers.
As example see http://docs.oracle.com/javaee/6/tutorial/doc/bnbqw.html
Application Managed Entity Managers = RESOURCE_LOCAL can use UserTransaction (which are part of JTA).
What does entity manager means???
If i am a naive programmer i could simply interpret something which manages entity & Indeed it means the same.
An Entity Manager is been instantiated with the help of an Entity Manager Factory. A connection to a database is managed by the entity manager i.e. it provides functionality for performing operations on a database. Therefore we could say if an application needs multiple database connections, an EntityManagerFactory will be constructed for a specific database which provides an efficient way to construct multiple EntityManager instances(if required, even single instance of entity manager can the job depending upon the requirement you may opt for multiple instances) for that database required for every HTTP request. We shall understand this with the help of an example. Suppose we have a
Database : A , having a relational tables B and C.
So for A, an instance of entity manager factory will be instantiated. Now we if ever want to perform any update to table B & lets say delete operation for table C, either two different entity manager could be instantiated or same the entity manager instance can be utilized for both.
The instantiation of Entity Manager Factory itself is considered to be less efficient but since it's a one time activity therefore it's manageable task because Entity Manager Factory once instantiated, it will serve the entire application
The entity manager instantiated is associated with a persistence context.
#PersistenceUnit(unitName = "MyDatabase")
EntityManagerFactory emf;
EntityManager entityManager = emf.createEntityManager();
or
#PersistenceContext(unitName = "MyDatabase")
private EntityManager entityManager;
PersistenceUnit injects an EntityManagerFactory, and PersistenceContext injects an EntityManager. It's generally better to use PersistenceContext unless you really need to manage the EntityManager lifecycle manually.
EntityManagerFactory defines another method for instantiation of EntityManager that, like the factory, takes a map of properties as an argument. This form is useful when a user name and a password other than the EntityManagerFactory's default user name and password have to specified:
Map properties = new HashMap();
properties.put("javax.persistence.jdbc.user", "kashyap");
properties.put("javax.persistence.jdbc.password","kashyap");
EntityManager em = emf.createEntityManager(properties);
Within the persistence context, the entity instances and their lifecycle are managed. By Entity instance, we mean instance of an entity & each entity designates relational table in the database. Entity Manager is actually an interface which provides methods to create and remove persistent entity instances, to find entities by their primary key, and to query over entities so together these functionalities are grouped under operations we perform. Operations that modify the content of a database require active transactions. Transactions are managed by an Entity Transaction instance obtained from the EntityManager.
Precise Definition :-
An Entity Manager is defined by a persistence unit. A persistence unit defines the set of all classes that are related or grouped by the application, and which must be colocated in their mapping to a single database.
Below i'm writing a code snippet for better understanding :-
try {
em.getTransaction().begin();
// Operations that modify the database should come here.
em.getTransaction
/**
*getTransaction() EntityManager's method Return the resource-level EntityTransaction object. See JavaDoc Reference Page
*/
em.getTransaction().commit();
}
finally {
if (em.getTransaction().isActive())
em.getTransaction().rollback();
}
Lets proceed as per JPA Specification :-
1) Extended vs Transactional - Scoped :
By Default the Transactional Persistence Context is in used which means all changes are flushed and all managed entities become detahced when the current transaction commits.
The Extended scope is available only for Stateful EJBs & it even makes a perfect sense since stateful beans can save the state therefore one can say end of
one business method doesn't necessary means the end of the transaction.
With the Stateless beans, it has a different aspect - We have business method that must end when the business method finishes.
===> One Method = One Transaction;
Only Transactional-Scoped Entity Manager is allowed for Stateless Beans
You can control if the EntityManager is extended or transactional during the EntityManager Injection :-
#PersistenceContext (type = javax.persistence.PersistenceContextType.EXTENDED)
EntityManager emng;
By Default it's javax.persistence.PersistenceContextType.TRANSACTION
Extended and Transaction Scoped PersistenceContext are allowed only in case of container-managed EntityManagers.
Time to step up a bit with: Container-managed vs Application-managed
2) Container-managed vs Application-managed :
#PersistenceContext
EntityManager emng;
Above statement authorises Container to inject the entity manager for you, hence Container-Managed.
Alternatively, you can create an EntityManager by yourself using EntityManagerFactory But this time the injection will be bit different -
#PersistenceUnit
EntityManagerFactory emf;
Now to get the EntityManager you need to invoke
emf.createEntityManager();
And here it is - you're using the application managed Persistence Context. Now you're responsible for creation and removal of EntityManagers.
Focus before you read the next para because that's what the tangled context , i'm trying to resolve-
You might use createEntityManager if you want to have control over created EM - e.g. if you need to move the created EntityManager across multiple beans involved in the trasaction - the container won't do it for you and every time you invoke createEntityManager(), you're creating an EntityManager that is connected to the new PersistenceContext. You might use the CDI for EntityManager's sharing.
Stay tuned for Entity Transaction - JPA and Resource-local, will be posting a detailed discussion on it.
Hope it gives a brief idea about the context. & Feel free to post queries.
Read the second part from here
I have some Java entity classes that are working well in my production code. I am writing an automated test for this application where I am reusing the very same classes.
When the test application is creating its entity manager this way:
Properties props = new Properties();
props.setProperty("provider", "org.apache.openjpa.persistence.PersistenceProviderImpl");
props.setProperty(...);
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("foobar-upgrade-restful-test", props);
EntityManager entityManager = entityManagerFactory.createEntityManager();
The applications throws an error message telling that:
Caused by: <openjpa-2.2.0-r422266:1244990 fatal user error> org.apache.openjpa.persistence.ArgumentException: You have supplied columns for "com.foo.bar.server.commontypes.job.CompositeJob", but this mapping cannot have columns in this context.
at org.apache.openjpa.jdbc.meta.MappingInfo.assertNoSchemaComponents(MappingInfo.java:382)
at org.apache.openjpa.jdbc.meta.strats.FlatClassStrategy.map(FlatClassStrategy.java:51)
at org.apache.openjpa.jdbc.meta.ClassMapping.setStrategy(ClassMapping.java:392)
at org.apache.openjpa.jdbc.meta.RuntimeStrategyInstaller.installStrategy(RuntimeStrategyInstaller.java:56)
at org.apache.openjpa.jdbc.meta.MappingRepository.prepareMapping(MappingRepository.java:411)
at org.apache.openjpa.meta.MetaDataRepository.preMapping(MetaDataRepository.java:762)
at org.apache.openjpa.meta.MetaDataRepository.resolve(MetaDataRepository.java:651)
... 72 more
I do not really understand the error message as the same entity bean is working in the application under Glassfish and the persistence.xml is also almost identical. (In the test I use RESOURCE_LOCAL tx instead of JTA but I doubt that it has relation with this error.
Do you have any idea what's wrong?
The error indicates that there is a problem with the mapping information that you provided for com.foo.bar.server.commontypes.job.CompositeJob.
I'm guessing the reason it works for JTA, but not resource local most likely has to do with some oddity in the way that metadata is loaded / processed in the different environments. It would be helpful if you post the relevant mapping data from your Entity.
I am in the process of developing a web application and decided that using spring-data would be a good idea. To be fair it makes life extremely easy and the DAO layer very thin.
The issue I am have is to do with persisting data. When I use a JPATransactionManager the persistence works as expected. But I need to use a JTATransactionManager. When I use this it appears that the transaction looks fine but the hibernate flush does not seem to be associated with the tx commit
DEBUG [org.springframework.transaction.jta.JtaTransactionManager] (http--127.0.0.1-8080-2) Creating new transaction with name [com.clubgroups.user.registration.service.impl.UserRegistrationServiceImpl.registerUser]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
DEBUG [org.springframework.transaction.jta.JtaTransactionManager] (http--127.0.0.1-8080-2) Participating in existing transaction
DEBUG [org.springframework.transaction.jta.JtaTransactionManager] (http--127.0.0.1-8080-2) Initiating transaction commit
Above is the debug message that confirms that the transaction is being committed. But the data does not seem to be flushed to the database.
I initialize the transaction manager like this:
#Bean
public JpaTransactionManager transactionManager() {
JtaTransactionManager transactionManager = new JtaTransactionManager();
return transactionManager;
}
Any help would be great.
I am a bit puzzled about your JTA setup as it's highly unusual. First, have a look at the reference documentation on how to setup JTA transactions correctly. Simply instantiating the JtaTransactionManager doesn't work as you need to obtain a UserTransaction from JNDI by some means. You should see an error popping up if you call afterPropertiesSet() in your #Bean method as this will unveil the missing configuration.