In the following code, a Null pointer exception is raised when I try to call beginTransaction method. I thought that JBoss would init my transaction... apparently not :\
What am I missing ?
JBoss 5.1.0.GA
JPA 1
JDK 6
import javax.annotation.Resource;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import javax.transaction.UserTransaction;
public abstract class AbstractDAO {
#PersistenceUnit(unitName = "miniDS")
protected static EntityManagerFactory emf;
#Resource
protected UserTransaction t;
public AbstractDAO() {
}
protected void beginTransaction() throws Throwable {
t.begin();
}
protected void commitTransaction() throws Throwable {
t.commit();
}
protected void rollbackTransaction() throws Throwable {
t.rollback();
}
}
Your AbstractDAO does not seem to be managed. Injection only works in container managed objects. This is not specific to injection of UserTransaction, but injection in general. As result emf is null as well. Java EE specification lists following classes to be able to use injection:
Servlet: servlets, servlet filters, event listeners
JSP: tag handlers, tag library event listeners
JSF: scoped managed beans
JAX-WS: service endpoints, handlers
EJB: beans, interceptors
Managed Beans: managed beans
CDI: CDI-style managed beans, decorators
Java EE Platform: main class (static), login callback handler
Possible workaround are to move injection of resources to managed class or use JNDI lookup.
Your concrete class ConcreteDAO which extends AbstractDAO, should be an ejb, as said by Mikko Maunu and should manage itself transaction (beans that manage transaction themselves BMT), in other words:
#Stateless
#TransactionManagement(TransactionManagementType.BEAN)
public class ConcreteDAO extends AbstractDAO {
...
}
And it be better if you inject EntityManager in your AbstractDAO, and configure JBOSS datasource to manage transaction (local-tx-datasource or xa-datasource).
you can look at JBOSS DS config at:
https://community.jboss.org/wiki/ConfigDataSources
if you want to manage transaction yourself through EntityManager, with entityManagerFactory
EntityManager entityManager = emf.createEntityManager();
entityManager.getTransaction().begin();
you can't use UserTransaction and the JBoss DS should be no-tx-datasource
If you inject your persistence unit, try to get the transaction through the EntityManager.
EntityManager entityManager = emf.createEntityManager();
entityManager.getTransaction().begin();
For more information, have a look here: https://github.com/wicketstuff/core/wiki/How-to-use-#PersistenceUnit-annotation
Related
I am developing a project with spring framework.
I have following architecture: all database code is in dao classes, all application logic is in service classes, http requests are processed using spring mvc rest controllers.
#Repository
public class UserDao {
#PersistenceContext
private EntityManager em;
public void editUser(User user) {
...
}
}
#Service
public class UserService {
#Autowired
private UserDao userDao;
#Transactional
public void editUser(User user) {
...
}
}
#RestController
#RequestMapping(value = "/UserCtrl", produces = "application/json;charset=UTF-8")
public class UserCtrl {
private static final Logger logger = LogManager.getLogger(AppConfig.LOGGER_NAME);
#Autowired
private ApplicationContext appContext;
#RequestMapping(value = "/editUser")
public ActionResult editUser(#ModelAttribute User user) {
ActionResult rslt = new ActionResult();
try {
UserService userService = appContext.getBean(UserService.class);
userService.editUser(user);
rslt.setSuccess(true);
} catch (Exception ex) {
logger.error("editUser", ex);
rslt.setSuccess(false);
}
return rslt;
}
}
This code works correctly.
One thing I cannot understand is how aop proxy of UserService bean starts transaction, when EntityManager is injected only in UserDao class. Can somebody explain me how this works and how EntityManager lifecycle is managed by spring framework ?
Any help appreciated.
The TransactionManager is responsible for managing the transaction boundaries
in Spring Framework.
When you annotate the business method with #Transactional you are instrumenting the method with an aspect.
Before executing the method, this aspect interact with TransactionManager which decides if it is necessary to create a new Transaction or use a preexisting one. In the case of create a new Transaction, a new Entity Manager is created from EntityManagerFactory and is associated to the current thread alonside with the Transaction.
The EntityManager is responsible to iterate with the database. When you inject it with #PersistenceContext, Spring injects an proxy to the EntityManager.
Whenever an operation is executed in the EntityManager proxy it looks the EntityManager associated with the thread.
Based on the snippet of code you provide you are using spring with some implementation of JPA you are using J2EE container for your web application and bases on my guess I think this is good article about how things works.
Basic concepts :
EntityManager - A class that manages the persistent state(or lifecycle) of an entity.
Persistence Unit - is a named configuration of entity classes.
Persistence Context - is a managed set of entity instances. The entities classes are part of the Persistence Unit configurations.
Managed Entities - an entity instance is managed if it is part of a persistence context and that Entity Manager can act upon it.
Based on this article you use Container Managed EntityManager by using #PersistenceContext
When a container of the application(be it a Java EE container or any other custom container like Spring) manages the lifecycle of the Entity Manager, the Entity Manager is said to be Container Managed. The most common way of acquiring a Container Managed EntityManager is to use #PersistenceContext annotation on an EntityManager attribute.
And the injection is like this :
A Transaction Scoped Entity Manager is returned whenever a reference created by #PersistenceContext is resolved.
and
Every time an operation is invoked on an Entity Manager, the container proxy(the container creates a proxy around the entity manager while instantiating it ) checks for any existing Persistence Context on the JTA Transaction. If it finds one, the Entity Manager will use this Persistence Context. If it doesnt find one, then it will create a new Persistence Context and associates it with the transaction.
So the lifecycle of of entity manager is managed by your container and
we work with an instance of EntityManager, the only role of EntityManager is to determine the lifetime of the Persistence Context. It plays no role in dictating how a Persistence Context should behave. To reiterate, Persistence Context is a managed set of Entity instances. Whenever a transaction begins, a Persistence Context instance gets associated with it. And when a Transaction ends(commits for example), the Persistence Context is flushed and get disassociated with the transaction.
In the nutshell container instantiate your EntityManager by the EntityManagerFactory you provide and manage it's lifecycle but inject the proxy of EntityManager for you. The TransactionManager is responsible for creating, commiting and ... tranactions based on annotations you provide ,whenever it begins the transaction the PersistancecContext associated with it and when the tranasction ends it commites the state of PersistenceContext. The EntityManager works with PersistenceContext and if it's not provided the EntityManager creates one. The EntityManager is threadsafe as long as it holds no state and the state (PersistenceContext) is attached to current tranasction.
Hope this helps.
Does anyone tried integrating spring-data-jpa with java-ee application?
I'm using glassfish3 as an application container.
I followed an official spring-data-jpa tutorial and created a class:
public class EntityManagerFactoryProducer {
#Produces
#ApplicationScoped
public EntityManagerFactory createEntityManagerFactory() {
return Persistence.createEntityManagerFactory("myPU");
}
public void close(#Disposes EntityManagerFactory entityManagerFactory) {
entityManagerFactory.close();
}
#Produces
#RequestScoped
public EntityManager createEntityManager(EntityManagerFactory entityManagerFactory) {
return entityManagerFactory.createEntityManager();
}
public void close(#Disposes EntityManager entityManager) {
entityManager.close();
}
}
But when I try to deploy my application, I'm getting an exception:
Error occurred during deployment: Exception while preparing the app : Could not resolve a persistence unit corresponding to the persistence-context-ref-name [org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean/entityManager] in the scope of the module called [App]. Please verify your application.. Please see server.log for more details.
Command deploy failed.
What am I missing? Should I also have another configuration file or maybe some xml file?
Since you are in a Java EE Application Container you do not want to create your own Persistence instance. The example from the Spring Data documentation you used is for CDI environmets that do not have built in JPA support. Glasfish creates EntityManagerFactory and EntityManager for you. You only need to republish it as CDI bean. So in your case it is important to use the second example shown in the documentation:
public class EntityManagerProducer {
#Produces
#RequestScoped
#PersistenceContext
private EntityManager entityManager;
}
It's a bit more tricky that what is told in official documentation. To handle properly a Spring Repository in a CDI env, you need to declare:
a dependent entity manager producer
#Produces #Dependent #PersistenceContext
EntityManager entityManager;
a eager repository
#Eager public interface TestRepository extends CrudRepository<TestEntity, Long>
Then you'll be able to #Inject the repository in a CDI managed Bean.
If you don't use the #Dependent and the #Eager annotation, Spring will cause exceptions at the initialization of the repositories, leading to uncatch expcetions on the first request made against it.
References:
Spring Data JPA repositories use in EJB timer causes TransactionRequiredException
Getting a reference to EntityManager in Java EE applications using CDI
I'm trying to move out my project from Seam 3.
Now I'm stuck on JTA transactions after switching off Seam Faces module. There was integrated transaction management. Transactions were begun and commit automatically - without manual commit.
Now when I try to execute EntityManager.persist() or EntityManager.merge(Object entity), I've got error:
JBAS011469: Transaction is required to perform this operation (either use a transaction or extended persistence context)
Is there any way to force JTA to start transaction and commit it transparently?
Ps. Funny thing - some time ago I was looking for solution how to force manual commit/rollback in Seam3.
OK, if I put bean into #Stateless state - then it behaves as I expected.
But...
Isn't it - that if I put application managed EntityManager - then I should manage transaction on my own (method testApplicationJTA() in example below), but if I use container managed EntityManager - then it should work without transaction managing (method testContainterJTA() ) ?
My example:
#Named
#SessionScoped
public class Test implements Serializable {
private static final long serialVersionUID = 1L;
#PersistenceContext
private EntityManager em;
#PersistenceUnit
private EntityManagerFactory emf;
#Resource
private UserTransaction utx;
public void testContainerJTA() {
TestEntity entity = em.find(TestEntity.class, 1L);
entity.setName("dddddd");
em.merge(entity);
}
public void testApplicationJTA() {
EntityManager mgr = emf.createEntityManager();
TestEntity entity = em.find(TestEntity.class, 1L);
entity.setName("fffff");
try {
utx.begin();
mgr.joinTransaction();
mgr.merge(dict);
utx.commit();
} catch (Exception e) {
utx.rollback();
}
mgr.close();
}
}
In my example above method testContainerJTA() doesn't work. Why?
If I'll remove #SessionScoped and put #Stateless then method testApplicationJTA() doesn't work, but testContainerJTA() works. Why?
Should't they work both always - as application managed and container managed?
OK, so it is possible to make CDI bean tansactional - with interceptors :-)
Finally I managed to solve my problem reading this article:
http://smokeandice.blogspot.com/2009/12/cdi-and-declarative-transactions.html
Edit:
From JEE7 there is new #Transactional annotation which takes all JPA actions in CDI bean or method into transaction.
I tried to obtain the TransactionManager in a #Singleton SessionBean - EJB 3.1 - to control the scope of my transaction, because i have to access a database on a #PostConstruct method. If an exception occurrs, I cannot let the Container RollBack because it throws the TransactionRolledbackException: setRollbackOnly called from within a singleton post construct method.
I am using a JTA DataSource and defined the #TransactionManagement(TransactionManagementType.BEAN) to override control of the transaction.
#Resource
private TransactionManager transactionManager;
returns to me a NullPointerException when i try to do a "transactionManager.begin();". Does anyone knows how to solve this ?
UPDATE:
the code i am using is this:
#Startup
#Singleton
#TransactionManagement(TransactionManagementType.BEAN)
public class RuntimeContextEJB
{
#EJB
private RepositoryRecursosExternosFactoryEJB repositoryRecursosExternosFactoryEJB;
#EJB
private MetodologiaIndiceLiquidezFactoryEJB metodologiaIndiceLiquidezFactoryEJB;
#EJB
private FuncaoMatematicaFactoryEJB funcaoMatematicaFactoryEJB;
private boolean bootstrapRunning = false;
private List<String> dadosMercadoMonitorados;
#PersistenceContext(unitName = "crv-persistence-unit")
private EntityManager entityManager;
#Resource
private TransactionManager transactionManager;
#PostConstruct
public void init()
{
// comentário
MotorCalculoContext.setupMotorCalculoContext(repositoryRecursosExternosFactoryEJB, metodologiaIndiceLiquidezFactoryEJB,
funcaoMatematicaFactoryEJB);
carregaDadosMercadoMonitorados();
}
public void sinalizarInicioBootstrap()
{
bootstrapRunning = true;
}
public void sinalizarTerminoBootstrap()
{
bootstrapRunning = false;
}
public boolean isBootstrapRunnnig()
{
return bootstrapRunning;
}
public void carregaDadosMercadoMonitorados()
{
try
{
transactionManager.begin();
this.dadosMercadoMonitorados = (List<String>) entityManager
.createQuery(
"SELECT DISTINCT(p.parametro.codigoDadoMercado) FROM PlanoExecucaoPasso p WHERE p.parametro.codigoDadoMercado <> '' AND p.parametro.codigoDadoMercado <> '0'")
.getResultList();
}
catch (Exception e)
{
}
}
}
I think there should be a JNDI adress to add on the #Resource annotation, one that is specific for WebSphere, but i really can't find wich is.
UPDATE:
why use JNDI on a container managed injection ? Since i am getting a nullpointer exception from a direct injection, tried to use like the ex. on page 305 from OReilly Enterprise Java Beans 3.1 6th edition.
#Resource(mappedName = "java:/TransactionManager")
//mappedName is vendor-specific, and in this case points to an address in JNDI
tried this with no success.
UPDATE
WebSphere is not getting our beans annotations - can't really know why - so the annotation:
#TransactionManagement(TransactionManagementType.BEAN)
was not working. So, edited de ejb-jar.xml and added the following code:
<transaction-type>Bean</transaction-type>
and the UserTransaction worked. Thanks for the answers.
When you have bean managed transaction, you don't use javax.transaction.TransactionManager but instead you use javax.transaction.UserTransaction.
And then you call begin, commit .... etc of UserTransaction interface.
Answer Updated:
1) First of all, as I said, don't use TransactionManager. Use UserTransaction
2) As you wanted to know the JNDI name of the UserTransaction object. It is java:comp/UserTransaction. But you need this only when your component is not managed. ie: Servlet, EJB. That process is called making a manual call to JNDI API
3) Provide commit() or rollback(). None of them is present.
I am looking at your class and it seems alright.
So, where is the problem ? (possibilities)
1) Your class is not treated as EJB (container managed) and which is why injection fails.
2) Transaction service is not started before EJB #Startup or it fails to start.
3) You have JTA Datasource configured in your persistence.xml. In which case, try:
#Resource
private EJBContext context;
userTransaction = context.getUserTransaction();
Note: Please also provide full stack trace and persistence.xml in order to pinpoint exact problem.
You don't need to use the Transaction Manager in programmatic (BMT) session beans, unless you want to suspend() or resume() the associated transaction in some cases, use the UserTransaction instead .
However, you can get a reference to the Transaction Manager in websphere by com.ibm.ws.Transaction.TransactionManagerFactory class using the static method getTransactionManager() .
public TransactionManager getTransactionManager() {
return TransactionManagerFactory.getTransactionManager();
}
Here's some sample code that runs properly using UserTransaction to have control over transactions.
#Singleton
#Startup
#TransactionManagement(TransactionManagementType.BEAN)
public class SampleUT {
Logger logger = Logger.getLogger(SampleUT.class.getName());
#Resource
private UserTransaction ut;
#PostConstruct
public void postConstruct()
{
logger.info("PostConstruct called");
try {
ut.begin();
...
The NullPointerException you're getting is probably related to you trying to use the injected resource inside the Constructor of your EJB. You should be aware that the injected reference is never available until the constructor of the EJB is finished, so if you try to use any injected reference inside the constructor, it will throw a NullPointerException.
I'm working on a desktop application using Java SE 7. The application uses multiple threads and in each thread that is created a DAO class is injected to gain access to my database. As persistence layer i'm using EclipseLink and JPA. The EntityManager is injected into my DAO class using constructor injection and since it is not thread safe, I went for the approach using a Provder like this:
public PluginInstanceJpaController implements IPluginInstanceDao {
private EntityManager em;
#Injected
public PluginInstanceJpaController(Provider<EntityManager> emp) {
this.em = emp.get();
}
#Transactional
public void create(PluginInstance foo) throws Exception {
em.persist(foo);
}
}
However, the very same EntityManager instance is injected into each DAO. For setting that up I used the JpaPersistModule as it is provided by guice and i'm sure that there are not singletons in my setup so far.
Does anyone know how to tell guice to create a new instance of the EntityManager when injecting?
In another approach I tried custom providers for the EntityManagerFactory and the EntityManager and leaving the JpaPersistModule out of my business. This resulted in a EntityManager instance per DAO, however #Transactional annotated methods were not intercepted then.
I'd appreciate any solution to this issue.
Thanks so far!
--- EDIT ---
The DAO classes are injected into a Runnable that is using them. The Runnable is also provided through a Provider. My module configuration looks something like this:
public class RepositoryModule extends AbstractModule {
#Override
protected void configure() {
// DAO bindings
bind(IObjectStoreDao.class).to(ObjectStoreJpaController.class);
bind(IPluginInstanceDao.class).to(PluginInstanceJpaController.class);
}
#Provides
public PluginMonitor newMonitor(IPluginInstanceDao plugDao, IObjectStoreDao osDao) {
PluginMonitor m = new PluginMonitor();
m.setPluginInstanceDao(plugDao);
m.setObjectStoreDao(osDao);
return m;
}
}
Here PluginMonitor is my Runnable. The Injector itself is created in my main thread... might this have been the issue?
This is very similiar issue: How Guice injects singletons and non-singletons into multiple threads
To your DAO, this should work.
public PluginInstanceJpaController implements IPluginInstanceDao {
private Provider<EntityManager> emProvider;
#Injected
public PluginInstanceJpaController(Provider<EntityManager> emp) {
this.em = emp;
}
#Transactional
public void create(PluginInstance foo) throws Exception {
em.get().persist(foo);
}
}
You should use Jpa Persistence Module or create custom EntityManager provider, which will return new EntityManager for each get() call, also it can be implemented with ThreadLocal to ensure EntityManager will be shared across thread.
I'm not familiar with JPA, but hopefully I can still help :-)
If you look at the source for EntityManagerProvider, you can see there's a ThreadLocal<EntityManager>. So by default, each thread should have its own EntityManager. That leads me to believe the problem is elsewhere. Are you sure that no module is setting the EntityManager to be a singleton? How are you determining that all the EntityManagers are the same object? Each DAO is definitely on its own thread? Can you provide details on how FooDao is configured in your module and how a new FooDao is provided to each thread?
Also, you should be fine to write your constructor as:
#Inject
public FooDao(EntityManager emp) {
this.em = emp;
}
Guice will do the magic for you of determining that EntityManagerProvider provides EntityManager instances, and will call get() on the EntityManagerProvider instance to get an EntityManager to give to your constructor.