Guice injected EntityManager in multi threaded application - java

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.

Related

Is javax.persistence.EntityManager thread safe

I’m using EntityManager in may Dao layer without #PersistenceContext but Dao method is calling service method which is marked as #Transactional. My question is should I use EntityManagerFactory in dao layer and every time get EntityManager to keep thread safety or it’s handled already?
Dao layer:
#RequiredArgsConstructor
public class UserDaoImpl {
private final EntityManager em;
public void save(User user){
em.persist(user);
}
}
Service layer:
#RequiredArgsConstructor
public class UserService {
private final UserDao userDao;
#Transactional
public void save(User user) {
userDao.save(user);
}
}
Tnx!
just add #PersistenceContext to your Entity Manager and the container will handle it for you, but if you are not in JEE environment so create your own entity manager factory, but I think in your current case the entity manager will still null. Also you must create you persistence unit XML file, and take attention in transaction-type, it must be JTA if you use #PersistenceContext and it should be RESSOURCE_LOCAL if you will create your own Entity Manager Factory.
This stackoverflow question Is EntityManager really thread-safe? already got answer to your question.
And this one "Future-Proofing Java Data Access - DAO Pattern Done Right" shows how to design DAO layer.
But if you are using Spring and Spring Data repository then I would suggest defining repository using CrusRepository or JpaRepository interface.
That would offload your concerns regarding EntityManager handling to Spring.

Call a #Autowired Repository from a static context

I have a createEntity method that is static, because i need to call it from other entities, inside this method, i need to call a repository, but logically i can't do it because it's non static.
public static Client createEntity(EntityManager em) {
default_operation = operationRepository.save(OperationResource.createEntity(em));
}
I wouldn't ask if i hadn't my head blown away by this, i tried to use #Autowired constructors as other solution suggested but this won't work for a repository.
If anyone has an idea, or a workaround, i would appreciate it!
Using static methods causes problems (not only in Spring). One of the reasons is that the autowired properties of a class are not available in a static context. They are only injected during certain stages of Spring's lifecycle.
You should declare the class that contains the createEntity method as a Spring bean (for example with #Component). Then you can inject this bean (with #Autowired) in all other classes that need to call createEntity.
I DO NOT recommend this, but because of any reason if you can't change the original class (to a singleton), you can consider the below approach which calls the createEntity(entityManager) inside #PostConstruct method:
public class MyRepository {
private EntityManager entityManager;
private static Client client;
#Autowired
public MyRepository(EntityManager entityManager) {
this.entityManager = entityManager;
}
#PostConstruct
public void init() {
//Now call your createEntity(entityManager) method
client = EntityUtils.createEntity(entityManager);
}
}

How to pass entity manager injected in statelesbean to dao without setter method

I am working on a project where I have separated EJB such that they only carry out the business logic but not performing the queries. Then I also have the DAOs that performs the queries. For me to use the DAOs, I inject the DAOs in the EJB and with a method annotated #PostConstruct, I set the EntityManager in the DAO with the EntityManager injected in the bean like bellow:
public class ClazzDao implements ClazzDaoI{
private EntityManager em;
public void setEm(EntityManager em){
this.em = em;
}
public List<Entity> list(){
return em.createQuery("FROM Entity e").getResultList();
}
}
And the EJB
#Stateless
public class ClazzBean implements ClazzBeanI{
#PersistenceContext
private EntityManager em;
#Inject
private ClazzDaoI clazzDao;
#PostConstruct
private void init(){
clazzDao.setEm(em);
}
public BigDecimal sendEmailToMembers(){
List<Entity> members = clazzDao.list();
//do some stuff with data like say send emails...
}
}
Is there a way that I can make the DAOs use the entity manager injected in the EJB without setting it at the #PostConstruct of the EJB?
You can use inject capability only in container managed beans. You dao class is outside of container management no way to inject the EntityManager into this object. Put you class into container management (EJB/CDI) if you need injection capability. By the way avoid to use unnecessary interfaces use non interface view instead.
Make Sure Are you using JAVA EE 6 OR HIGHER, Make the ClazzDao as Managed Bean, means either #ApplicationScoped/#SessionScoped
#ApplicationScoped
public class ClazzDao implements ClazzDaoI
CDI can inject ClazzDao ManagedBean.

Write Less DAOs with Spring Hibernate using Annotations

My Spring+Hibernate configuration files are small and super tight. I use auto scanning to find my model entities/daos.
I don't want to have to write a DAO + DAOImpl for EVERY Entity in my hierarchy.
Some may qualify to have their own, like if they have complex relationships with other entities and require more than basic CRUD functionality. But for the rest...
Is there any way to circumvent the defacto standard?
Say, something like a generic DAO, ex:
http://www.ibm.com/developerworks/java/library/j-genericdao/index.html
Then I can do something like
GenericDao dao = appContext.getBean("genericDao");
dao.save(car);
dao.save(lease);
Is this possible with annotations? I don't want to have to configure anything in xml. If I cannot do above, is it still possible to have one GenericDaoImpl.java with something like:
#Repository("carDao")
#Repository("leaseDao")
class GenericDaoImpl extends CustomHibernateDaoSupport implements GenericDao {
...
}
and then
GenericDao dao = appContext.getBean("carDao");
dao.save(car);
dao = appContext.getBean("leaseDao"); //carDao is garbage coll.
dao.save(lease);
Is this practical at all?
Using generics, you might try something like this:
#Repository
#Transactional
public class GenericDAOImpl<T> implements GenericDAO<T> {
#Autowired
private SessionFactory factory;
public void persist(T entity) {
Session session = factory.getCurrentSession();
session.persist(entity);
}
#SuppressWarnings("unchecked")
public T merge(T entity) {
Session session = factory.getCurrentSession();
return (T) session.merge(entity);
}
public void saveOrUpdate(T entity) {
Session session = factory.getCurrentSession();
session.saveOrUpdate(entity);
}
public void delete(T entity) {
Session session = factory.getCurrentSession();
session.delete(entity);
}
}
The content may be different, but the general idea is applicable.
You should be able to then autowire the DAO in your controller and service classes by using
#Autowired
private GenericDAO<Car> carDao;
You can combine Spring/Hibernate with JPA, which provides the EntityManager for a large amount of basic persistence tasks:
#Service
public class CarService {
#PersistenceContext
private EntityManager em;
public void saveCarAndLease(Car car, Lease lease) {
em.persist(car);
em.persist(lease);
}
}
It will also handle transactions and simple queries without needing to write a DAO. For the more complex operations, you can still write a DAO and fall back to Hibernate's SessionFactory (although JPA is an option here too).
Some tutorials suggest you should still write the DAO for abstraction of the JPA plumbing. However, I have personally found this unnecessary (JPA has a very small integration footprint), and in fact this is also the way Spring Roo deals with the data layer behind the scenes.
Have you tried to use Spring Data. I mean to say Spring JPA where you can use repositories.
You can eliminate writing all stuffs for each entity.

#Transactional method called from another method doesn't obtain a transaction

In Spring, a method that is annotated with #Transactional will obtain a new transaction if there isn't one already, but I noticed that a transactional method does not obtain any transaction if it is called from a non-transactional one. Here's the code.
#Component
public class FooDao {
private EntityManager entityManager;
#PersistenceContext
protected void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
#Transactional
public Object save(Object bean) {
return this.entityManager.merge(bean);
}
public Object saveWrap(Object bean) {
return save(bean);
}
}
#Component
public class FooService {
private FooDao fooDao;
public void save(Object bean) {
this.fooDao.saveWrap(bean); // doesn't work.
this.fooDao.save(bean); // works
}
}
saveWrap() is a regular method that calls save() which is transactional, but saveWrap() won't persist any changes.
I'm using Spring 3 and Hibernate 3. What am I doing wrong here? Thanks.
It is one of the limitations of Springs AOP. Because the dao bean is in fact a proxy when it is created by spring, it means that calling a method from within the same class will not call the advice (which is the transaction). The same goes for any other pointcut
Yes, this is expected behaviour. #Transactional tells spring to create a proxy around the object. The proxy intercepts calls to the object from other objects. The proxy does not intercept calls within the object.
If you want to make this work, add #Transactional on the method that is invoked from "outside".
This is a bit late I know, but would just like to add a way to overcome this limitation is that within the method obtain the spring bean from the application context and invoke the method. When the spring bean is obtained from the application context it will be the proxy bean not the original bean . Since the proxy bean is now invoking the method instead of the original bean the transaction advice will be implemented on it.
A possible workaround is to call the method like if it was invoked from "outside"
You can do it by getting the current proxy of the component and then call the method :
((MyService) AopContext.currentProxy()).innerMethod();
Source: https://www.programmersought.com/article/58773839126/

Categories

Resources