Technology(Java EE 6 with Glassfish 3.1, Netbeans 7.0)
I have an application client that access a db via JPA. No EJB is involved. Now I need to add an web interface for this application client. So I will choose to use JSF 2.x. I have some concern about design here, and I hope the community would help me out. So thanks to BalusC, I am able to use JPA in a stand alone client application by specify transaction-type=RESOURCE_LOCAL in the persistence.xml. Below are demonstration:
EDIT the below codes has been edited base on BalusC suggestion
Here is my App Client main
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("CoreInPU");
EntityManager em = emf.createEntityManager();
EntityDAO entityDAOClient = new EntityDAOClient(em);
Main pgm = new Main();
try {
process(entityDAOClient);
} catch (Exception e) {
logger.fatal("", e);
}finally{
em.close();
emf.close();
}
}
public void process(EntityDAO entityDAO){
validatePDF(List<pdfFiles>);
processPDF(List<pdfFiles>, entityDAO);
createPrintJob(List<pdfFiles>, entityDAO);
}
public void processPDF(List<pdfFiles>, EntityDAO entityDAO){
for(File file : pdfFiles){
entityDAO.create(file);
}
}
Here is my DAO interface class in my App Client
public interface EntityDAO {
public <T> T create(T t);
public <T> T find(Class<T> type, Object id);
public List findWithNamedQuery(String queryName);
public List findWithNamedQuery(String queryName, int resultLimit);
}
Here is the App Client DAO
public class EntityDAOClient implements EntityDAO {
private EntityManager em;
private static Logger logger = Logger.getLogger(EntityDAOClient.class);
public EntityDAOClient(EntityManager em) {
this.em = em;
}
@Override
public <T> T create(T t){
em.getTransaction().begin();
em.persist(t);
em.getTransaction().commit();
return t;
}
@Override
public <T> T find(Class<T> type, Object id){
em.getTransaction().begin();
T t = em.find(type, id);
em.getTransaction().commit();
return t;
}
...
}
And here is the persistence.xml
<persistence-unit name="CoreInPU" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>com.wf.docsys.core.entity.Acknowledgement</class>
<class>com.wf.docsys.core.entity.PackageLog</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/core"/>
<property name="javax.persistence.jdbc.password" value="root"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.user" value="xxxx"/>
<property name="eclipselink.ddl-generation" value="create-tables"/>
</properties>
</persistence-unit>
Now I need to add a web module on top of this. I know I need JTA transaction type, so I create an EAR project call foo with foo_ejb and foo_war in it. So my EJB look like this.
@Stateless
@LocalBean
public class CoreEJB implements EntityDAO{
@PersistenceContext(unitName = "CoreInWeb-ejbPU")
private EntityManager em;
//@Override
public <T> T create(T t) {
em.persist(t);
return t;
}
//@Override
public <T> T find(Class<T> type, Object id) {
return em.find(type, id);
}
...
}
Note that CoreInWeb-ejbPU is the new persistence.xml unit name with JTA transaction type. I also add my app client jar file to the foo_ejb package. When I deploy I got this message Invalid ejb jar [foo-ejb.jar]: it contains zero ejb. It is because of this @Stateless public class CoreEJB implements EntityDAO. If I take the implements EntityDAO out then it is deploy, but I need the EJB to be implements EntityDAO so that in my managed bean I can do this
@ManagedBean
@RequestScoped
public class Bean {
@EJB
private CoreEJB coreEJB;
public Bean() {
}
public void runAppClientMainProcess() {
//The web interface can also kick off the same process as the app client
process(coreEJB);
}
// ...
}
How can I do this correctly? Please help
I know I might be asking too much here, but if you can base on my structure above, show me how to add a web module in, I would greatly appreciate it. Some codes would be awesome. I am still learning, so if my design is flaw, feel free to rip it, I will redesign everything if I am convince there are better way to accomplish this. Bottom line is, there are a set of business logic, and I want to access those via both application client and web interface. Like how glassfishv3 have web interface and admin console
I want to apologize for my late reply. I was behind the schedule for another project so I do not have time to write a proper response to
BalusCandkirananswers.kiranask me this:Case 2 - Web Module - You have used(want to use) jsf for presentation , CoreEJB for persistence -- i am not clear where you intend to put business logic, for now ill take is as another ejb class.Answer: Hi kiran, the bottom line is that, I want the same set of logic to be access at both app client side and web module side. Like glassfish app server. You have a command line version and web module version accessing the same resources.
BalusCsuggestion to useRESOURCE_LOCALwork great if I just use application client. However, once I adding the web module on top of it, I cant not get it to work anymore even though BalusC did try to work with me. You guys can read BalusC response and my implementation of his idea above (The code from the original post is my implementation of BalusC idea). If I add the App Client to the Java EE project (EAR) classpath, it receive no compile error when I try to access the logic from App Client, but when i run the web module, it generate Exception saying that it does not see the class/method that I try to access from App Client. So I decide to port all my logic onto EJB and make my App Client very thin. The logics will be exposed to App Client viajavax.ejb.Remoteinterface, and exposed to the Web module viajavax.ejb.Localinterface. So below is my general layout of this idea.This is my
thinApp Client (Main)So on my EJB side which package inside Java EE project (EAR) that contain EJB and web module, I have
Note that since all the logics now inside EJB, I can use
JTAtransaction type, which is container managed. I like it this way better than manage it myself.Some people suggestion to exposed the business logics via RESTful. Since I do not know very well about RESTful, I will stay with this implementation for now. Thank you for all your help
BalusCandkiran.