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#...
Reply to the post :
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&a...