JBoss是一个非常优秀的J2EE的Application Server,研究 它的源代码有助于我们更好的理解J2EE的各种技术。 本系列拟从四个方面分析Jboss源码: 1.EJB Container实现 2.Transaction实现 3.Persistence Mapping 4.Client到Server端的Invocation
------------------------------------------------------------------- 先说第1点:EJB Container实现。 1.1 EJB Pool 我们知道,EJB Container 会维护一个EJB池, 在多个client间共享,避免频繁创建销毁对象的开销。 让我们来看看Jboss实现的Pool: EJB分EntityBean,MDB,Stateless/Stateful Session Bean, 而Jboss中也对应的有EntityInstancePool,MessageDrivenInstancePool, StatefulSessionInstancePool,StatelessSessionInstancePool. 让我们先从这4个类的共同基类AbstractInstancePool看起: class AbstractInstancePool实现了接口InstancePool,该接口有以下几个方法: EnterpriseContext get() throws Exception; void free(EnterpriseContext ctx); void discard(EnterpriseContext ctx); int getCurrentSize(); public int getMaxSize(); -------------------------------------------------------------------- 先对EnterpriseContext作番说明。EnterpriseContext的作用 就是把具体的EJB instance和它的metadata联系起来。 该类签名为: public abstract class EnterpriseContext, 有4个子类,EntityEnterpriseContext,MessageDrivenEnterpriseContext, StatefulSessionEnterpriseContext,StatelessSessionEnterpriseContext。 分别对应4种类型的EJB。 EnterpriseContext中有几个重要的成员变量。 /** The EJB instance */ Object instance; /** The container using this context */ Container con; //Container这个类是JBoss用来代表对EJB提供Transaction,Security,Pool等服务的类,我们回头还会再说。 /** Only StatelessSession beans have no Id, stateful and entity do */ Object id;
/** The transaction associated with the instance */ Transaction transaction; //Transaction,我们下节再说.
// Constructors --------------------------------------------------
public EnterpriseContext(Object instance, Container con) { this.instance = instance; this.con = con; }
public Object getInstance() { return instance; } public Container getContainer() { return con; }
public void setId(Object id) { this.id = id; }
public Object getId() { return id; }
public void setTransaction(Transaction transaction) { this.transaction = transaction; }
public Transaction getTransaction() { return transaction; }
/** * Get the EJBContext object */ public abstract EJBContext getEJBContext(); //由子类实现
//返回javax.ejb.EJBContext,注意这个EJBContext是 EJB规范要求提供给EJB的Context,与JBoss自己实现类EnterpriseContext没有关系。
/** The instance is being used. This locks it\'s state */ int locked = 0; public void lock() { locked ++; }
public void unlock() { locked --; }
public boolean isLocked() { return locked != 0; } //lock这个成员变量表示当前这个EJB instance有没人在用。 //这个变量用来给Reentrance,以及canPassviate用. /** * before reusing this context we clear it of previous state called * by pool.free() * 从pool里取出来的时候没有关联任何EJB instance和Transaction信息 * 在返还pool的时候把这些信息清掉。 */ public void clear() { this.id = null; this.locked = 0; this.transaction = null; } //------------------------------------------------------------------------------------- protected boolean isContainerManagedTx() { BeanMetaData md = (BeanMetaData)con.getBeanMetaData(); return md.isContainerManagedTx(); } //从关联的container拿出对应的metadata,判断是否CMT. //注意这里con是Container成员变量,可不是什么连接,连接一般缩写为conn, //我一开始就搞混了:) //BeanMetaData这些MetaData的子类都是从xml配置里头读出来的Metadata构造的, //没什么神秘的. 这个类里头还有两个inner class,EJBContextImpl implements EJBContext, UserTransactionImpl implements UserTransaction。EJBContextImpl等 讲解过Container再说,UserTransaction等下节再说。
现在让我们来看看EnterpriseContext的几个子类: 首先类比一下几个子类的成员变量: EntityEnterpriseContext: private EJBObject ejbObject; private EJBLocalObject ejbLocalObject; private EntityContext ctx;
StatefulSessionEnterpriseContext private EJBObject ejbObject; private EJBLocalObject ejbLocalObject; private SessionContext ctx;
StatelessSessionEnterpriseContext EJBObject ejbObject; EJBLocalObject ejbLocalObject; SessionContext ctx;
MessageDrivenEnterpriseContext: private MessageDrivenContext ctx; 看来除了MDB没有对应的EJBObject/EJBLocalObject,其他统统都有:) 学过EJB的人都知道,在语法上EJB instance 是implements EntityBean/SessionBean/MessageDrivenBean (这3个interface有一个共同的 interface: public interface EnterpriseBean extends Serializable, EnterpriseBean 是个Marker接口,里头什么都没有,好像Serializable接口一样,只说明 实现它的是个EJB.而EntityBean/SessionBean/MessageDrivenBean 有对应的 void ejbActivate() throws EJBException, RemoteException; void ejbLoad() throws EJBException, RemoteException; 一些方法需要实现。(虽然常常是空实现:),由容器作了很多事) 至于EJBObject/EJBLocalObject 在语法上都是非直接实现的,代表EJB instance暴露出的Remote/Local 接口。既然这些EJB instance非直接实现这些接口,那么这些接口如何与具体的EJB instance相关联,我们讲到Container类时就知道了。 ----------------------------------------------------------------------------------
EnterpriseContext的子类EntityEnterpriseContext的构造函数 public EntityEnterpriseContext(Object instance, Container con) throws RemoteException { super(instance, con); ctx = new EntityContextImpl(); //这是EJBContextImpl的子类,不急着说:) ((EntityBean)instance).setEntityContext(ctx);//看看,原来set...Context是在这里调用的//其它instance实现的什么ejbCreate(),EJBLoad,EJBActive()到底是什么时候 调用的呢?接下来我们慢慢找,这可散布在各地呢:) } //其他几个子类的构造函数前3行也都如此,是类似的。 对于StatelessSessionEnterpriseContext和MessageDrivenEnterpriseContext,紧接的是
Method ejbCreate = instance.getClass().getMethod(\"ejbCreate\", new Class[0]); ejbCreate.invoke(instance, new Object[0]); //看看,来了一个ejbCreate:),对于StatelessSessionBean,一上来就ejbCreate()了~ 接下来看点简单的:对于EnterpriseContext, 有public abstract void discard() throws RemoteException; 对于MessageDriven...的 public void discard() throws RemoteException { ((MessageDrivenBean)instance).ejbRemove(); } 对于StatelessSession的 public void discard() throws RemoteException { ((SessionBean)instance).ejbRemove(); } 对于StatefulSession...的 public void discard() throws RemoteException { // Do nothing } 对于Entity.... public void discard() throws RemoteException { ((EntityBean)instance).unsetEntityContext(); } //discard 是在AbstractInstancePool中的 void discard(EnterpriseContext ctx);调用的
/** * Discard an anonymous instance after invocation. * This is called if the instance should not be reused, perhaps due to some * exception being thrown from it. * * @param ctx The context to discard. */ public void discard(EnterpriseContext ctx) { ctx.discard(); } AbstractInstancePool还有个free方法: public void free(EnterpriseContext ctx) { ctx.clear();//记得ctx只是清掉id,transaction等,返回pool,准备复用么? //discard是在发生错误的时候,不希望扩大影响,于是discard掉, //而对应get()的free方法只是把EnterpriseContext返还给pool. } ----------------------------------------------------------------------------------
专门对于Stateful....Context有设置EJB instance的函数 /** * During activation of stateful session beans we replace the instance * by the one read from the file. */ public void setInstance(Object instance) { this.instance = instance; ((SessionBean)instance).setSessionContext(ctx); } 注意在4种...Context中,只有Stateful...Context签名 public class StatefulSessionEnterpriseContext extends EnterpriseContext implements Serializable 多了个implements Serializable,(其他都没有), 这是为了支持Activation/Passviation,Passviation的时候 把EJB Instance写到文件中。 在StatefulSessionEnterpriseContext中有这样两个方法 private void writeObject(ObjectOutputStream out) throws IOException, ClassNotFoundException { // do nothing }
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { // do nothing } //说明序列化的时候StatefulSessionEnterpriseContext本身不需要 写出什么状态,只有对应的EJB instance才需要写出状态。
现在来看AbstractInstancePool的源码,由于内容太多 就不详细解释了。 先看Abstract...Pool的create(Object instance)函数热热身~ Abstract...Pool // Protected ----------------------------------------------------- protected abstract EnterpriseContext create(Object instance) throws Exception; 对Entity...Pool protected EnterpriseContext create(Object instance) throws Exception { return new EntityEnterpriseContext(instance, getContainer()); } 其他3种Pool类似。 再回头看Abstract..Pool /** The pool data structure */ protected EnterpriseContext[] pool; protected int currentIndex = -1; /** The maximum number of instances allowed in the pool */ protected int maxSize = 30; /** The minimum size of the pool */ protected int minSize = 0; /** determine if we reuse EnterpriseContext objects i.e. if we actually do pooling */ protected boolean reclaim = false;//对于MDB和StatelessSessionBean,这个变量被设为true,// for MDB, we *do* pool // for SLSB, we *do* pool ok,现在来看pool的重头戏,get()/free(EnterpriseContext ctx)函数 (discard(EnterpriseContext ctx)前面讲过,不再重复) 这几个函数也是Interface InstancePool里头要实现的接口:) 闲话少说,来看代码~~ protected boolean minSizeInitialized = false; /** * Get an instance without identity. * Can be used by finders,create-methods, and activation * * @return Context /w instance * @exception RemoteException */ public EnterpriseContext get() { //pool里头有东东就拿出来 synchronized (pool) { if (currentIndex > -1) { EnterpriseContext ctx = pool[currentIndex]; pool[currentIndex--] = null; return ctx; } } //initialize a small fixed size of instance at startup. if (!minSizeInitialized) { minSizeInitialized = true; synchronized (pool) { for (int i = 0; i < minSize; i++) { pool[++currentIndex] = create(container.createBeanClassInstance()); } } } // Pool is empty, create an instance return create(container.createBeanClassInstance()); } /** * Return an instance after invocation. * * Called in 2 cases: * a) Done with finder method * b) Just removed * * @param ctx */ public void free(EnterpriseContext ctx) { ctx.clear(); synchronized (pool) { if (currentIndex + 1 < maxSize) { pool[++currentIndex] = ctx; } } } 对于Entity...Pool,他overwrite了free /** * Return an instance to the free pool. Reset state * *
Called in 3 cases: *
*
- Done with finder method
*
- Removed
*
- Passivated
*
* * @param ctx */ public void free(EnterpriseContext ctx) { // If transaction still present don\\\\\\\\\\\\\\\'t do anything (let the instance be GC) if (ctx.getTransaction() != null) { return ; } super.free(ctx); } ----------------------------------------------------- 而Stateful....Pool的free方法overwrite了Abstract...Pool的, public synchronized void free(EnterpriseContext ctx) { discard(ctx);//干脆就discard掉不用了~ } 剩下的下回再讲,先预告2个类体系: 1.AbstractInstanceCache ,有EntityInstanceCache和StatefulSessionInstanceCache 子类。对于Entity,用它的 PrimaryKey作Cache的Key,对于Stateful,Jboss也会付给 每个instance一个唯一标定的值用来做CacheKey. Abstract...Cache与Abstract...Pool结合使用,得到好的Performance。 2.public abstract class Container, 有EntityContainer,MessageDrivenContainer,Stateful/StatelessSessionContainer 4个子类,用来提供对EJB instance的transaction/security/pool等服务。 //看看它的成员变量,就能猜个大概 /** This is the TransactionManager */ protected TransactionManager tm; /** This is the SecurityManager */ protected AuthenticationManager sm; /** This is the instancepool that is to be used */ protected InstancePool instancePool;
开始讲Container,以前说过Container有4种子类,分别对应4种类型的EJB. 一个Container是所有Container plugins(注1)和metadata(注2)的集散地,the container plugins可以从container拿到metadata和其他container plugins.EJB部署的时候会创建相应的Container.Container基本不做太多事,主要delegate给plugins作事情。 ok,让我们来看看Container的成员变量: /** * This is the new metadata. it includes information from both ejb-jar and * jboss.xml the metadata for the application can be accessed trough * metaData.getApplicationMetaData() */ protected BeanMetaData metaData;
/** This is the EnterpriseBean class */ protected Class beanClass;
/** This is the Home interface class */ protected Class homeInterface;
/** This is the Remote interface class */ protected Class remoteInterface;
/** The local home interface class */ protected Class localHomeInterface;
/** The local inteface class */ protected Class localInterface;
/** This is the TransactionManager */ protected TransactionManager tm;
/** This is the SecurityManager */ protected AuthenticationManager sm;
/** This is the realm mapping */ protected RealmMapping rm;
/** This is the bean lock manager that is to be used */ protected BeanLockManager lockManager;
/** This is the application that this container is a part of */ protected EjbModule ejbModule; //ejbModule作为一个单元部署的Module,比如一个ejb-jar就是一个Module, /*这个 ejb-jar里头可能有多个entitybean,sessionbean,那么对于 每个entitybean,sessionbean 都会有一个对应的container,而这些东东共享一个ejbModule.*/ /** * Returns a new instance of the bean class or a subclass of the bean class. * This factory style method is speciffically used by a container to supply * an implementation of the abstract accessors in EJB2.0, but could be * usefull in other situations. This method should ALWAYS be used instead * of getBeanClass().newInstance(); * * @return the new instance * * @see java.lang.Class#newInstance */ public Object createBeanClassInstance() throws Exception { return getBeanClass().newInstance(); } public Class getBeanClass() { return beanClass; }
注意EntityContainer overwrite了这个方法: /** * Returns a new instance of the bean class or a subclass of the bean class. * If this is 1.x cmp, simply return a new instance of the bean class. * If this is 2.x cmp, return a subclass that provides an implementation * of the abstract accessors. * * @see java.lang.Class#newInstance * * @return The new instance. */ public Object createBeanClassInstance() throws Exception { return persistenceManager.createBeanClassInstance(); } 其中 persistenceManager声明为: /** This is the persistence manager for this container */ protected EntityPersistenceManager persistenceManager; //persitenceManager和PersistenceStore我们将在第3部分讲解。 现在先给个大略印象: BMPPersistenceManager实现 public Object createBeanClassInstance() throws Exception { return con.getBeanClass().newInstance(); }
CMPPersistenceManager实现 EntityPersistenceStore store; public Object createBeanClassInstance() throws Exception { return store.createBeanClassInstance(); } ------------------------------------------------------------------- ok,接下来看看Container如何处理Client过来的Invocation。 一切精彩尽在下面这个函数 public Object invoke(Invocation mi); //Invocation代表了Client端过来的调用 //Invocation里头有些成员变量,指明了要调用的Method, //args,Transaction信息,principle/credential等信息。
/** Maps for MarshalledInvocation mapping */ protected Map marshalledInvocationMapping = new HashMap();
public Object invoke(Invocation mi) throws Exception { Thread currentThread = Thread.currentThread(); ClassLoader callerClassLoader = currentThread.getContextClassLoader(); //保存原来的classloader,在finally里恢复
Method m = null; Object type = null;
try { currentThread.setContextClassLoader(this.classLoader);(注3) // Check against home, remote, localHome, local, getHome, // getRemote, getLocalHome, getLocal type = mi.getType();
if(type == InvocationType.REMOTE || type == InvocationType.LOCAL) { if (mi instanceof MarshalledInvocation) { ((MarshalledInvocation) mi).setMethodMap( marshalledInvocationMapping); } return internalInvoke(mi); } else if(type == InvocationType.HOME || type == InvocationType.LOCALHOME) { if (mi instanceof MarshalledInvocation) { ((MarshalledInvocation) mi).setMethodMap( marshalledInvocationMapping); return internalInvokeHome(mi); } else { throw new MBeanException(new IllegalArgumentException( \\\\\\\"Unknown invocation type: \\\\\\\" + type)); } } finally { currentThread.setContextClassLoader(callerClassLoader); } }
---------------------------------------------------------------- MarshalledInvocation是Invocation的字类,代表可以从 Client传到Server的Invocation public class Invocation...
public class MarshalledInvocation extends Invocation implements java.io.Externalizable 而Invocation是在server端的调用链(Interceptor链,注4) 间传递. ------------------------------------------------------- ok,稍喘口气,接下来看看两个Internal的invoke, 都是abstract,在字类实现 public abstract Object internalInvokeHome(Invocation mi) throws Exception; public abstract Object internalInvoke(Invocation mi) throws Exception; 至于具体实现么,TO BE CONITUE拉:) ---------------------------------------------------- 注1:ContainerPlugin可以放在容器里头的东东。 接口为interface ContainerPlugin : void setContainer(Container con); 有InstancePool,InstanceCache,EJBProxyFactory/LocalProxyFactory, EntityPersistenceManager/EntityPersistenceStore等Plugin 注2:metadata描述部署的信息,比如ejb-jar.xml,描述什么东东是 entitybean,什么东东是sessionbean,session的是BMP/CMP等等。 注3: Container的成员变量protected ClassLoader classLoader; 用来load 这个Container里头的类和资源,之所以要专门设一个Container 的classLoader是因为能使EJB re-deployable.(JBoss定期扫描deploy目录, 如果ejb更改就进行redeploy,如果ejb删除就undeploy) 注4: Jboss会建立一个Interceptor 链,Invocation经过链传递。 比如有EntityInterceptor,SecurityInterceptor,TransactionInterceptor, InvokerInterceptor,一个套一个,每个Interceptor对当前Invocation进行一些处理 ,比如检查权限,事物等等,然后传给下一个Interceptor处理(这是Filter and Pipe模式了,也算是AOP拉~,别人说 JBoss 这个Interceptor实现属于AOP方言特别重:)。 所有的Interceptor都是现 Object invokeHome(Invocation mi) throws Exception; 和Object invoke(Invocation mi) throws Exception; 在自己invoke的最后, 经过所有的Interceptor之后,调用下一个。 看看AbstractInterceptor的缺省实现: public abstract class AbstractInterceptor implements Interceptor
public Object invokeHome(final Invocation mi) throws Exception { //do sth. return getNext().invokeHome(mi); } public Object invoke(final Invocation mi) throws Exception { //do sth. return getNext().invoke(mi); } 在经过重重Interceptor之后 最后到达EJB Instance 调用你要的那个方法。
其实实现很简单: public Object internalInvokeHome(Invocation mi) throws Exception { return getInterceptor().invokeHome(mi); }
public Object internalInvoke(Invocation mi) throws Exception { // Invoke through interceptors return getInterceptor().invoke(mi); }
public Interceptor getInterceptor() { return interceptor; } protected Interceptor interceptor; //这是Container建立的Interceptor链的头一个,从这里调起~ 再来看看 void addInterceptor(Interceptor in);这个函数 在Interceptor链最后再挂一个Interceptor public void addInterceptor(Interceptor in) { if (interceptor == null) { interceptor = in; } else { Interceptor current = interceptor; while (current.getNext() != null) { current = current.getNext(); }
current.setNext(in); } } ------------------------------------------------------------------------ 附带再提一下pool和cache /** This is the instance cache for this container */ protected InstanceCache instanceCache;
/** This is the instancepool that is to be used */ protected InstancePool instancePool; /** This is the instancepool that is to be used */ protected InstancePool instancePool; ------------------------------------------------------------- public void setInstanceCache(InstanceCache ic) { if (ic == null) throw new IllegalArgumentException(\\\"Null cache\\\");
this.instanceCache = ic; ic.setContainer(this); }
public InstanceCache getInstanceCache() { return instanceCache; } public void setInstancePool(InstancePool ip) { if (ip == null) throw new IllegalArgumentException(\\\"Null pool\\\");
this.instancePool = ip; ip.setContainer(this); } ----------------------------------------------------------------------- ok,现在让我们来看看Container都对EJB Instance暴露出来的 方法都作了些什么,还有如何调用EJB Instance的方法. 这里有重要的2个Map /** * These are the mappings between the home interface methods and the * container methods. * 所有Home 方法映射都存这里 */ protected Map homeMapping = new HashMap();
/** * These are the mappings between the remote/local interface methods and the * bean methods. * 所有EJBObject方法映射都存这里 */ protected Map beanMapping = new HashMap(); -------------------------------------------------------------------------- class ContainerInterceptor extends AbstractContainerInterceptor //AbstractContainerInterceptor基本上什么都不做,不用看 //ContainerInterceptor代表Container setup的Interceptor调用 //链的最后一个,到这里你就会看到他调用了你的EJB Instance的方法 { public Object invokeHome(Invocation mi) throws Exception { // Invoke and handle exceptions Method miMethod = mi.getMethod(); Method m = (Method) homeMapping.get(miMethod); if (m.getDeclaringClass().equals(EntityContainer.class)) { try { return m.invoke(EntityContainer.this, new Object[] { mi }); } catch (Exception e) { rethrow(e); } } else // Home method { try { return m.invoke(((EnterpriseContext) mi.getEnterpriseContext()).getInstance(), mi.getArguments()); } catch (Exception e) { rethrow(e); } }
// We will never get this far, but the compiler does not know that throw new org.jboss.util.UnreachableStatementException(); }
public Object invoke(Invocation mi) throws Exception { // Get method Method miMethod = mi.getMethod(); Method m = (Method) beanMapping.get(miMethod); if( m == null ) { String msg = \\\"Invalid invocation, check your deployment packaging\\\" +\\\", method=\\\"+miMethod; throw new EJBException(msg); }
// Select instance to invoke (container or bean) if (m.getDeclaringClass().equals(EntityContainer.class)) { // Invoke and handle exceptions try { return m.invoke(EntityContainer.this, new Object[]{ mi }); } catch (Exception e) { rethrow(e); } } else { // Invoke and handle exceptions try { return m.invoke(((EnterpriseContext) mi.getEnterpriseContext()).getInstance(), mi.getArguments()); } catch (Exception e) { rethrow(e); } }
// We will never get this far, but the compiler does not know that throw new org.jboss.util.UnreachableStatementException(); } }
//可以看到,两个Map作了个映射,Map的Key为 在你想要调用的EJB instance方法,value为实际 实现的方法,可能就是EJB instance本身实现的方法, 或者是容器帮忙实现的(比如CMP 中abstract get/set方法, 只能容器帮忙实现). 从这里也可以看出来,JBoss主要是保存了方法映射来处理 EJBObject/EJBLocalObject 的调用请求, 而其他一些J2EE AS是通过动态生成EJBObject/EJBLocalObject 和你的EJB Instance的字类来实现的(而JBoss就算在CMP2.0 里动态生成了一个东东,那也不是EJB Instance的子类)。
ok,基本弄明白了Container的原理之后,我们来看看 到底Container的一些初始化操作 Container算是一项服务, JBoss在deploy/undeploy/redeploy时会调用 与Service相关的几个函数: protected void createService() throws Exception {} protected void startService() throws Exception {} protected void stopService() throws Exception {} protected void destroyService() throws Exception {} 让我们从EntityContainer看起:
protected void createService() throws Exception { // Associate thread with classloader ClassLoader oldCl = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(getClassLoader());
try { // Acquire classes from CL //从metadata拿到Home/Remote的Class if (metaData.getHome() != null) homeInterface = classLoader.loadClass(metaData.getHome()); if (metaData.getRemote() != null) remoteInterface = classLoader.loadClass(metaData.getRemote());
// Call default init // 调用Container里头的CreateService,我们回头再看 super.createService();
//建立刚才所说的两个Method映射Map setupBeanMapping(); setupHomeMapping();
// Map the interfaces to Long setupMarshalledInvocationMapping();
// Initialize pool instancePool.create(); // Try to register the instance pool as an MBean try { ObjectName containerName = super.getJmxName(); Hashtable props = containerName.getKeyPropertyList(); props.put(\\\"plugin\\\", \\\"pool\\\"); ObjectName poolName = new ObjectName(containerName.getDomain(), props); server.registerMBean(instancePool, poolName); } catch(Throwable t) { log.debug(\\\"Failed to register cache as mbean\\\", t); }
// Init instance cache instanceCache.create(); // Try to register the instance cache as an MBean try { ObjectName containerName = super.getJmxName(); Hashtable props = containerName.getKeyPropertyList(); props.put(\\\"plugin\\\", \\\"cache\\\"); ObjectName cacheName = new ObjectName(containerName.getDomain(), props); server.registerMBean(instanceCache, cacheName); } catch(Throwable t) { log.debug(\\\"Failed to register cache as mbean\\\", t); }
for (Iterator it = proxyFactories.keySet().iterator(); it.hasNext(); ) { String invokerBinding = (String)it.next(); EJBProxyFactory ci = (EJBProxyFactory)proxyFactories.get(invokerBinding); ci.create(); }
// Init persistence persistenceManager.create();
// Initialize the interceptor by calling the chain Interceptor in = interceptor; while (in != null) { in.setContainer(this); in.create(); in = in.getNext(); } readOnly = ((EntityMetaData)metaData).isReadOnly(); } finally { // Reset classloader Thread.currentThread().setContextClassLoader(oldCl); } }
protected void startService() throws Exception { // Associate thread with classloader ClassLoader oldCl = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(getClassLoader());
try { // Call default start super.startService();
// Start container invokers for (Iterator it = proxyFactories.keySet().iterator(); it.hasNext(); ) { String invokerBinding = (String)it.next(); EJBProxyFactory ci = (EJBProxyFactory)proxyFactories.get(invokerBinding); ci.start(); }
// Start instance cache instanceCache.start();
// Start persistence persistenceManager.start();
// Start the instance pool instancePool.start();
// Start all interceptors in the chain Interceptor in = interceptor; while (in != null) { in.start(); in = in.getNext(); } } finally { // Reset classloader Thread.currentThread().setContextClassLoader(oldCl); } }
protected void stopService() throws Exception { // Associate thread with classloader ClassLoader oldCl = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(getClassLoader());
try { //Stop items in reverse order from start //This assures that CachedConnectionInterceptor will get removed //from in between this and the pm before the pm is stopped. // Stop all interceptors in the chain Interceptor in = interceptor; while (in != null) { in.stop(); in = in.getNext(); }
// Stop the instance pool instancePool.stop();
// Stop persistence persistenceManager.stop();
// Stop instance cache instanceCache.stop();
// Stop container invoker for (Iterator it = proxyFactories.keySet().iterator(); it.hasNext(); ) { String invokerBinding = (String)it.next(); EJBProxyFactory ci = (EJBProxyFactory)proxyFactories.get(invokerBinding); ci.stop(); }
// Call default stop super.stopService(); } finally { // Reset classloader Thread.currentThread().setContextClassLoader(oldCl); } }
protected void destroyService() throws Exception { // Associate thread with classloader ClassLoader oldCl = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(getClassLoader());
try { // Destroy container invoker for (Iterator it = proxyFactories.keySet().iterator(); it.hasNext(); ) { String invokerBinding = (String)it.next(); EJBProxyFactory ci = (EJBProxyFactory)proxyFactories.get(invokerBinding); ci.destroy(); }
// Destroy instance cache instanceCache.destroy(); instanceCache.setContainer(null); try { ObjectName containerName = super.getJmxName(); Hashtable props = containerName.getKeyPropertyList(); props.put(\\\"plugin\\\", \\\"cache\\\"); ObjectName cacheName = new ObjectName(containerName.getDomain(), props); server.unregisterMBean(cacheName); } catch(Throwable ignore) { }
// Destroy persistence persistenceManager.destroy(); persistenceManager.setContainer(null);
// Destroy the pool instancePool.destroy(); instancePool.setContainer(null); try { ObjectName containerName = super.getJmxName(); Hashtable props = containerName.getKeyPropertyList(); props.put(\\\"plugin\\\", \\\"pool\\\"); ObjectName poolName = new ObjectName(containerName.getDomain(), props); server.unregisterMBean(poolName); } catch(Throwable ignore) { }
// Destroy all the interceptors in the chain Interceptor in = interceptor; while (in != null) { in.destroy(); in.setContainer(null); in = in.getNext(); }
MarshalledInvocation.removeHashes(homeInterface); MarshalledInvocation.removeHashes(remoteInterface);
// Call default destroy super.destroyService(); } finally { // Reset classloader Thread.currentThread().setContextClassLoader(oldCl); } } ------------------------------------------------------------ protected void setupBeanMapping() throws Exception { try { if (remoteInterface != null) { Method[] m = remoteInterface.getMethods(); setupBeanMappingImpl( m, \\\"javax.ejb.EJBObject\\\" ); } if (localInterface != null) { Method[] m = localInterface.getMethods(); setupBeanMappingImpl( m, \\\"javax.ejb.EJBLocalObject\\\" ); } } catch (Exception e) { // ditch the half built mappings homeMapping.clear(); beanMapping.clear();
throw e; } }
private void setupBeanMappingImpl( Method[] m, String intfName ) throws Exception { for (int i = 0; i < m.length; i++) { if (!m.getDeclaringClass().getName().equals(intfName)) { // Implemented by bean beanMapping.put(m, beanClass.getMethod(m.getName(), m.getParameterTypes())); } else { // Implemented by container beanMapping.put(m, getClass().getMethod(m.getName(), new Class[] { Invocation.class })); } } } private void setupHomeMappingImpl(Method[] m, String finderName, String append) throws Exception { // Adrian Brock: This should go away when we don\\\'t support EJB1x boolean isEJB1x = metaData.getApplicationMetaData().isEJB1x();
for (int i = 0; i < m.length; i++) { String methodName = m.getName(); try { try // Try home method { String ejbHomeMethodName = \\\"ejbHome\\\" + methodName.substring(0,1).toUpperCase() + methodName.substring(1); homeMapping.put(m, beanClass.getMethod(ejbHomeMethodName, m.getParameterTypes()));
continue; } catch (NoSuchMethodException ignore) {} // just go on with other types of methods
// Implemented by container (in both cases) if (methodName.startsWith(\\\"find\\\")) { homeMapping.put(m, this.getClass().getMethod(finderName, new Class[] { Invocation.class })); } else if (methodName.equals(\\\"create\\\") || (isEJB1x == false && methodName.startsWith(\\\"create\\\"))) { homeMapping.put(m, this.getClass().getMethod(\\\"create\\\"+append, new Class[] { Invocation.class })); beanMapping.put(m, this.getClass().getMethod(\\\"postCreate\\\"+append, new Class[] { Invocation.class })); } else { homeMapping.put(m, this.getClass().getMethod(methodName+append, new Class[] { Invocation.class })); } } catch (NoSuchMethodException e) { throw new NoSuchMethodException(\\\"Could not find matching method for \\\"+m); } } }
protected void setupHomeMapping() throws Exception { try { if (homeInterface != null) { Method[] m = homeInterface.getMethods(); setupHomeMappingImpl( m, \\\"find\\\", \\\"Home\\\" ); } if (localHomeInterface != null) { Method[] m = localHomeInterface.getMethods(); setupHomeMappingImpl( m, \\\"findLocal\\\", \\\"LocalHome\\\" ); }
// Special methods
// Get the One on Handle (getEJBObject), get the class Class handleClass = Class.forName(\\\"javax.ejb.Handle\\\");
// Get the methods (there is only one) Method[] handleMethods = handleClass.getMethods();
//Just to make sure let\\\'s iterate for (int j=0; j { //Get only the one called handle.getEJBObject if (handleMethods[j].getName().equals(\\\"getEJBObject\\\")) { //Map it in the home stuff homeMapping.put(handleMethods[j], this.getClass().getMethod(\\\"getEJBObject\\\", new Class[] {Invocation.class})); } } } catch (Exception e) { // ditch the half built mappings homeMapping.clear(); beanMapping.clear();
throw e; } } 
|