Hi there,
I am basically a newbie whose starting work on a new webapp. The webapp is mostly your basic CRUD operations. For this, I have decided to use JPA with Hibernate as the Persistence provider and will be developing on Apache Derby for development and testing purposes. I am using GlassFish v2 as the App Server to deploy my EJB3 beans. For the front end I am using JSF (Visual JSF with woodstock theme that comes bundled with NeatBeans v6.5)
So this is how I have been proceeding so far. I have been using the NetBeans 6.5 wizards for the most part to generate my entity classes and ejb session beans. What I do is, I create a new table in Apache Derby, say XXX. Then I use the "Entity Classes from Database" to generate the XXX Entity class which contains all the necessary annotations and getter and setter methods.
Next, I run the "JPA Controller Classes from Entity Classes" wizard to generate the controller class code, XXXJpaController which contains basically the following:
@Resource private UserTransaction utx = null;
@PersistenceUnit(unitName = "TestEnterpriseApplication-ejbPU") private EntityManagerFactory emf = null;
1. EntityManager getEntityManager() { return emf.createEntityManager() }
2. void create(XXX xxx) throws PreexistingEntityException, RollbackFailureException, Exception{}
3. void edit(XXX xxx) throws NonexistentEntityException, RollbackFailureException, Exception{}
4. void destroy(Long id) throws NonexistentEntityException, RollbackFailureException, Exception {}
5. List<XXX> findXXXEntities(){}
6. List<XXX> findXXXEntities(int maxResults, int firstResult) {}
7. List<XXX> findXXXEntities(boolean all, int maxResults, int firstResult){}
8. XXX findXXX(Long id){}
9. int getXXXCount(){}
Then, I run the "Session Beans for Entity Classes" wizard to generate EntityFacade local/remote session beans that can be called by the front end when needed as follows:
@PersistenceContext private EntityManager em;
1. void create(XXX xxx) { em.persist(xxx); }
2. void edit(XXX xxx) { em.merge(xxx); }
3. void remove(XXX xxx) { em.remove(em.merge(xxx)); }
4. List<XXX> findAll() { return em.createQuery("select object(o) from XXX as o").getResultList(); }
Since I already have the generatd Controller classes which implements these methods with better support for try and catch and transactions, I decided to call that in XXXFacade.java instead as shown below:
XXXJpaController XXXController = new XXXJpaController();
1. public void create(XXX xxx) throws PreexistingEntityException, RollbackFailureException, Exception {
XXXController.create(xxx); }
2. public void edit(XXX xxx) throws NonexistentEntityException, RollbackFailureException, Exception{
XXXController.edit(xxx); }
3. public void remove(XXX xxx) throws NonexistentEntityException, RollbackFailureException, Exception{
XXXController.destroy(xxx.getId()); }
4. public XXX find(Object id) {
return XXXController.findXXX((Long)id); }
5. public List<XXX> findAll() {
return XXXController.findXXXEntities(); }
So here is my first question. Is this a right way of doing things in the world of JEE or is there a better way of doing it? Am I introducing some sort of redundancy here? This is the pattern that I have been pretty much following for all the Entity classes: Create entity class -> create controller class -> create entityfacade class -> change entityfacade class to call controller class methods
ps: I am using JTA
This has in turn led me to another issue. All the generated controller classes have their own getEntityManager() methods. So in order to get rid of this redundancy, I decided to go with a helper class along the lines of the HibernateUtil.java that is commonly seen in Hibernate tutorials (which acts as a singleton for the sessionfactory). So I have created a PersistenceUtil.java which has getEntityManager() and getUserTransaction() methods that are supposed to return instances of EntityManager and UserTransaction to be used by the Controller classes.
Thats where the problem lies. I use @PersistenceContext ((name="jpa/EntityManager") and @Resource (name="jta/UserTransaction") on the XXXFacade classes. So I can get access to the JNDI entries for em and utx from both the XXXFacade class (if I have to, though in my case I dont) and in the XXXJpaController helper class (through the jndi lookup). After reading up online, thats what I found out. Helper classes need to use the JNDI lookup on the bean's component environment (java:comp/env) as the injection gets done only for container managed beans and not for unmanaged helper classes. This works fine for the Controller class which gets instantiated in the XXXFacade class as shown in the code above. However, I cannot use the PersistenceUtil class to lookup either the EntityManager or the UserTransaction since I am guessing its a helper's helper class. What can I do to get around this and access the container managed entitymanager and usertransaction in PersistenceUtil helper class? One option that comes to my mind is to instantiate the Persistence class in each XXXFacade class also (I dont like the sound of that).
Only other option that I can think of is to get rid of the Controller class and move all that code into the XXXFacade class. That way I wouldn't even need the PersistenceUtil helper class anymore since I could directly get it injected into the session bean, right?
Like I mentioned at the beginning, I am a newbie. I am looking to hear from all you seasoned and highly experienced java/jee veterans for guidance on this issue. Is there any particular pattern that I can employ here?
I am sorry if any of this doesn't make sense to you. Please feel free to go ahead and ask me for any clarifications and I will be more than happy to do so.