I have something that seems to work, although I don't know if it the best
solution - feel free to comment/improve (or trash, if appropriate) this
approach.
The problem space dictates that the application operate on a schema that is
determined by user input, So the schema must be derived at runtime. The
application id deployed in several environments as it evolves from current
branch development to production - this is still a challenge as I am required
to change code, the list of persistence units; I am looking at ant hacks to
accommodate this.
The basic approach is to define a Stateless Session Bean base class that
defines the PersistenceUnits that the application has available to it. My
entities are all wrapped by generated session facades. Each method in the
session facade must call super.getEntitymanager(persistenceUnitName) to ensure
that an EntityManager is available. The PersistenceUnitName is determined by
the client of the session facade.
One cool aspect of this design is that the table centric set of entities and
session facades contain absolutely no business logic. Business logic goes in
subclasses of the session facades to accomplish application/webService specific
tasks. The result is a set of beans that expose the database and a common
definition of property names. The brings naming consistence to all web
services that are based on these tables. Not terribly slick, but it removes
naming challenges/convention/religion from other development organizations that
use them.
The Session Bean base class looks like:
| package com.czncorp.base.session;
|
| import javax.ejb.Stateless;
| import javax.naming.*;
| import javax.persistence.*;
|
| @Stateless
| @PersistenceUnits({
| @PersistenceUnit(name="persistence/CM5AZ", unitName="CM5AZ"),
| @PersistenceUnit(name="persistence/CM5CA", unitName="CM5CA"),
| @PersistenceUnit(name="persistence/CM5EA", unitName="CM5EA"),
| @PersistenceUnit(name="persistence/CM5US", unitName="CM5US")
| })
| public class BaseStatelessSession implements BaseStatelessSessionLocal {
|
| protected EntityManager entityManager;
|
| public void getEntityManager(String persistenceUnit) {
|
| try {
| if (entityManager == null) {
| InitialContext jndiContext = new InitialContext();
| EntityManagerFactory emf =
(EntityManagerFactory)jndiContext.lookup("java:comp/env/persistence/" +
persistenceUnit);
| entityManager = emf.createEntityManager();
| }
| }
| catch (NamingException ne) {
| ;; // Handle this based on your needs
| }
| }
| }
|
Session facades (TableBeans) wrap entities with CRUD capabilities, nothing
more. These look like:
| package com.czncorp.as400.tables.blsbl;
|
| import com.czncorp.base.session.BaseStatelessSession;
| import com.czncorp.as400.tables.svord.LogUtil;
|
| import java.util.List;
| import java.util.logging.Level;
| import javax.ejb.Stateless;
|
|
| /**
| * Facade for entity Blsbl.
| *
| * @see com.czncorp.as400.tables.blsbl.Blsbl
| * @author MyEclipse Persistence Tools
| */
| @ Stateless
|
| public class BlsblFacade extends BaseStatelessSession implements
BlsblFacadeLocal, BlsblFacadeRemote {
|
| public void save(String persistenceUnit, Blsbl transientInstance) {
| LogUtil.log("saving Blsbl instance", Level.INFO, null);
| try {
| super.getEntityManager(persistenceUnit); // <<---- make sure
there is an Entity Manager
| entityManager.persist(transientInstance);
| LogUtil.log("save successful", Level.INFO, null);
| }
| catch (RuntimeException re) {
| LogUtil.log("save failed", Level.SEVERE, re);
| throw re;
| }
| }
|
| public void delete(String persistenceUnit, Blsbl persistentInstance) {
| LogUtil.log("deleting Blsbl instance", Level.INFO, null);
| try {
| super.getEntityManager(persistenceUnit);
| entityManager.remove(persistentInstance);
| LogUtil.log("delete successful", Level.INFO, null);
| }
| catch (RuntimeException re) {
| LogUtil.log("delete failed", Level.SEVERE, re);
| throw re;
| }
| }
|
| public Blsbl update(String persistenceUnit, Blsbl detachedInstance) {
| LogUtil.log("updating Blsbl instance", Level.INFO, null);
| try {
| super.getEntityManager(persistenceUnit);
| Blsbl result = entityManager.merge(detachedInstance);
| LogUtil.log("update successful", Level.INFO, null);
| return result;
| }
| catch (RuntimeException re) {
| LogUtil.log("update failed", Level.SEVERE, re);
| throw re;
| }
| }
| ...
| ...
| ...
|
Current challenge, and I think it is just a deployment issue I need to work
through, is to deploy the TableBeans (stuff above) in it's own EAR. Other
deployable units that implement business logic will subclass the session
facades of TableBeans. Currently I am deploying two separate jars, problem is
that the TableBean super class of my application specific session bean, a
subclass of BlsblFacade in this case, can't find the Blsbl entity when the
subclass calls methods in BlsblFacade. Of course, everything works fine if the
subclasses are deployed in the same jar as TableBeans, so I know I am close.
If that makes any sense, I am not beyond taking your suggestions.
Hope this helps others trying to determine the schema to use at runtime. Be
aware that because you are using an EntityManagerFactory, the
PersistenceContext will be "EXTENDED". I thought I could make it "TRANSACTION"
since the container was doing everything, but that did not work for me.
View the original post :
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4095311#4095311
Reply to the post :
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4095311
_______________________________________________
jboss-user mailing list
[email protected]
https://lists.jboss.org/mailman/listinfo/jboss-user