I am on Weblogic 12c + JPA/Hibernate + EJB 3.
I wish to simplify my class model as follow:
public abstract class AbstractEJBBean {
#PersistenceContext(unitName = "myPU")
private EntityManager entityManager;
}
#Local
public interface FirstEJB {
void someMethod1();
}
#Stateless
public class FirstEJBImpl extends AbstractEJBBean implements FirstEJB {
#Override
public void someMethod1() {
// Here entityManager has been injected.
}
}
#Local
public interface SecondEJB {
void someMethod2();
}
#Stateless
public class SecondEJBImpl extends AbstractEJBBean implements SecondEJB {
#Override
public void someMethod2() {
// Here entityManager has NOT been injected!!!
}
}
In such situation, Weblogic starts (no errors logged), the application starts, but: only then entity manager into FirstEJBImpl instance have been injected. The one inside SecondEJBImpl is null!!!
I never seen any like this.
Could somebody tell my why and how to avoid it?
Thank you so much!!!
I found the solution on my own.
I suppose it is a Weblogic bug, but I am not so sure, but my solution works as expected.
I had to remove the abstract base class and inject the entity manager directly inside each EJB.
#Local
public interface FirstEJB {
void someMethod1();
}
#Stateless
public class FirstEJBImpl implements FirstEJB {
#PersistenceContext(unitName = "myPU")
private EntityManager entityManager;
#Override
public void someMethod1() {
// Here entityManager has been injected.
}
}
#Local
public interface SecondEJB {
void someMethod2();
}
#Stateless
public class SecondEJBImpl implements SecondEJB {
#PersistenceContext(unitName = "myPU")
private EntityManager entityManager;
#Override
public void someMethod2() {
// Here entityManager has been injected too! :)
}
}
Related
I have a Spring-boot project, in my project I defined two EntityManager - for two different DB.
All of my entities (tables) are common for the two different DB.
The only thing that is different is the Dao layer - but because some of my db queries are shared I decided to create - a common Dao abstract layer. and i added a getEntityManager() function to the class that extend the abstract class.
Example:
#Repository
#Transactional(value = "secondaryTransactionManager")
#javax.transaction.Transactional
public class TasksSecondaryDao extends TasksDaoAbstract {
#PersistenceContext(unitName = "secondary")
private EntityManager entityManager;
#Override
public EntityManager getEntityManager() {
return entityManager;
}
public void updateTask(Task task) {
entityManager.merge(task);
}
}
#Repository
#Transactional
public class TasksFirstDao extends TasksDaoAbstract {
#PersistenceContext
private EntityManager entityManager;
#Override
public EntityManager getEntityManager() {
return entityManager;
}
public void updateTask(Task task) { entityManager.merge(task); }
}
public abstract class TasksDaoAbstract {
#Transactional(Transactional.TxType.NEVER)
public List<Task> getAll() {
return getEntityManager().createQuery("FROM Task",
Task.class).getResultList();
}
public abstract EntityManager getEntityManager();
}
In general this code is working. But if I am trying to put updateTask method in the abstract class (with #Transactional) it look like the code is working (no error) but the DB is not updating.
I can not understand why the query is not working from the abstract class, the query that only getting data from the db is working from the abstract class.
I'm trying to follow code reusing best practices.
I have generic DAO interface with some common methods:
public interface DaoInterface<T> {
T findById(int id);
//...more methods...
}
and its implementation class:
public class GenericDao<T> implements DaoInterface<T> {
#SuppressWarnings("unchecked")
private final Class<T> persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
#Autowired
protected SessionFactory sessionFactory;
#Override
#SuppressWarnings("unchecked")
public T findById(int id) {
Session session = sessionFactory.getCurrentSession();
return (T) session.get(persistentClass, id);
}
//...more methods...
}
Then my every concrete implementation class extends GenericDao and implements its interface.
I also have Service layer in my application. Some Services' methods completely delegate their work to DAO classes. So in the each concrete Service implementation I autowire appropriate DAO class and call its methods.
So now it looks:
public interface CustomerService {
Customer findById(int id);
}
and implementation:
#Service
#Transactional(readOnly = true, rollbackFor = Exception.class)
public class CustomerServiceImpl implements CustomerService {
#Autowired
private CustomerDao customerDao;
#Override
public Customer findById(int id) {
return customerDao.findById(id);
}
}
My question is - how to generify Service classes in the same way as DAO? So that my concrete class will look:
public class CustomerServiceImpl extends GenericService<Customer> implements CustomerService {
.....
}
The problem is that I cannot autowire DAO class in Generic Service:
#Autowired
private GenericDao<T> dao;
so that I could call dao's methods.
Should I do it in the constructor?
And one more question - where is the right place to annotate methods with #Transactional - in generic class or in every implementation class?
You have to create an instance of a generic Dao and put in the service layer some decision:
#Repository
public class GenericDao implements DaoInterface<T> {
//The type must be aquired at runtime,otherwise it may not be thread safe
#Autowired
protected SessionFactory sessionFactory;
#Override
#SuppressWarnings("unchecked")
public T findById(int id,Class<?> persistenceClass) {
Session session = sessionFactory.getCurrentSession();
return (T) session.get(persistenceClass, id);
}
//...more methods...
}
Also if you need a good generic repository layer take a look for Spring Data Jpa
This will make one and only one instance of the GenericDao.
Next you have 2 choice:
Create a singleton services for all your needs
Create a class service for every entity
abstract class GenericService<T> {
#Autowired
protected GenericDao dao;
#SuppressWarnings("unchecked")
protected final Class<T> persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
#Override
public T findById(int id) {
return dao.findById(id,persistenceClass);
}
}
Now every one of your service must extends the GenericService with a supplied persistence type and the job is done.
I created a spring application where i decided to add a BaseDAO to eliminate redundant create,
update,delete,findByid,and findAll methods for every dao. So i created a baseDao and every dao should extend this BaseDAO.
BaseDaoImpl
public class BaseDAOImpl implements BaseDAO{
SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sf){
this.sessionFactory = sf;
}
#Override
public void create(ModelBase modelBase) {
Session session = this.sessionFactory.getCurrentSession();
session.persist(modelBase);
}
#Override
public void update(ModelBase modelBase) {
Session session = this.sessionFactory.getCurrentSession();
session.update(modelBase);
}
#Override
public Collection findAll(Class aClass) {
Session session = this.sessionFactory.getCurrentSession();
Collection modelCols = session.createQuery("from "+aClass.getSimpleName()).list();
return modelCols;
}
#Override
public ModelBase findById(Class aClass, Integer id) {
Session session = this.sessionFactory.getCurrentSession();
ModelBase modelBase = (ModelBase) session.load(aClass, new Integer(id));
return modelBase;
}
}
Then i extends this Dao to each DAO
EmployeeDAOImp
public class EmployeeDAOImpl extends BaseDAOImpl implements EmployeeDAO{
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sf){
this.sessionFactory = sf;
}
}
I created a BaseService like this. But when i try to access BaseDAO methods from EmployeeDAO it returns null pointer exception.
Why this happen. I dont want to use genericDAO from google. Because we should create DAOs
for each model. I want to eliminate this. So I follow this method.
Have you though about Spring Data project & Spring Data JPA in particular?
This would save you lots of time, since you would no longer need to write your DAO / Repositories from scratch, all you need to do is enable Spring Data JPA, and add needed interfaces. It should save you tons of time.
http://projects.spring.io/spring-data-jpa/
http://spring.io/guides/gs/accessing-data-jpa/ - Sample project
Your are overriding setSessionFactory from base class for no reason, its already available with extending class EmployeeDAOImpl , either remove it or try below:
public class EmployeeDAOImpl extends BaseDAOImpl implements EmployeeDAO{
//this reference should be from base class,
// the extending class ref is hiding base ref.
// private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sf){
super.setSessionFactory(sf);
}
}
Something like the following should work (note the use of constructor rather than setter injection). In the BaseDAO:
public class BaseDAOImpl implements BaseDAO {
private final SessionFactory sessionFactory;
public BaseDAOImpl(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}
Then in the Employee DAO:
public class EmployeeDAOImpl extends BaseDAOImpl implements EmployeeDAO {
#Inject
public EmployeeDAOImpl (SessionFactory sessionFactory) {
super(sessionFactory);
}
}
You can create generic dao.
#Repository("genericDao")
public class GenericDaoImpl<T,PK extends Serializable> implements GenericDao<T, PK> {
protected Class<T> entityClass;
public T create(T t) {
this.entityManager.persist(t);
return t;
}
public T read(PK id,Class<T> c) {
return (T)this.entityManager.find(c, id);
}
public T update(T t) {
return this.entityManager.merge(t);
}
public void delete(T t) {
t = this.entityManager.merge(t);
this.entityManager.remove(t);
}
public List<T> getAll(Class<T> c){
return this.entityManager.createQuery("SELECT o FROM "+ c.getName() +" o").getResultList();
}
}
UPDATED
You can use as following, TimeRange is a pojo class in the following example. If you do not want a service layer. You can use timeRangeDao in controller.
#Service("timeRangeService")
public class TimeRangeServiceImpl implements TimeRangeService{
#Autowired
GenericDao<TimeRange,Long> timeRangeDao;
public List<TimeRange> getAllTimeRanges(){
return timeRangeDao.getAll(TimeRange.class);
}
#Transactional
public void createTimeRange(TimeRange c) {
timeRangeDao.create(c);
}
#Transactional
public void update(TimeRange p) {
timeRangeDao.update(p);
}
#Transactional
public TimeRange getTimeRange(long id) {
return timeRangeDao.read(id, TimeRange.class);
}
#Transactional
public void delete(long id) {
TimeRange timeRange = new TimeRange();
timeRange.setId(id);
timeRangeDao.delete(timeRange);
}
}
I am writing a CDI-JPA DAO pattern that not using EJB because I am using Tomcat.
Here is my code:
#ApplicationScoped
public class UserDao {
#PersistenceContext(unitName = "unitName1")
EntityManager entityManager;
public void saveUser(User user) {
this.entityManager.persist(user);
}
public void removeUser(User user) {
this.entityManager.remove(user);
}
public void getUser(int id) {
this.entityManager.find(User.class, id);
}
}
Since all my DAO classes are annotated with #ApplicationScoped so I was wondering whether IT IS SAFE to inject entityManager using #PersistenceContext as I did? Can someone tell me is that ok? If NOT, please give me your ideas.
I have a generic DAO class that looks like this:
public class GenericDaoJpa <T extends DomainObject> implements GenericDao<T> {
private final Class<T> type;
#PersistenceContext(type=PersistenceContextType.TRANSACTION, unitName="myPersistenceUnit")
protected EntityManager entityManager;
public GenericDaoJpa(Class<T> type) {
super();
this.type = type;
}
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
public T get(Object id) {
return (T) entityManager.find(type, id);
}
}
The implementation DAO class looks like this:
#Repository("appDao")
public class ProductDaoJpa extends GenericDaoJpa<Product> implements ProductDao{
public ProductDaoJpa() {
super(Product.class);
}
public List<Product> getAllProducts() {
return getAll();
}
}
I have configured another persistentUnit called mySecondPersistenceUnit for a different database. I would like to create a new DAO class that will also extend the GenericDaoJpa class but use a different persistent unit. How can i extend the GenericDaoJpa class but use a different persisitent unit for each DAO?
I tried moving this declaration to each of the DAO classes but this causes the parent class not to compile because it has no reference to the entityManager.
#PersistenceContext(type=PersistenceContextType.TRANSACTION, unitName="myPersistenceUnit")
protected EntityManager entityManager;
Try to use method injection instead:
public class GenericDaoJpa <T extends DomainObject> implements GenericDao<T> {
#PersistenceContext(type=PersistenceContextType.TRANSACTION, unitName="myPersistenceUnit")
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
}
While child class that need use different PU:
#Repository("appDao")
public class ProductDaoJpa extends GenericDaoJpa<Product> implements ProductDao{
#Override
#PersistenceContext(type=PersistenceContextType.TRANSACTION, unitName="mySecondPersistenceUnit")
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
}