| Method from org.jboss.ejb.EntityContainer Detail: |
public void addInterceptor(Interceptor in) {
if (interceptor == null)
{
interceptor = in;
}
else
{
Interceptor current = interceptor;
while (current.getNext() != null)
{
current = current.getNext();
}
current.setNext(in);
}
}
|
protected void checkCoherency() throws Exception {
// Check clustering cohrency wrt metadata
//
if (metaData.isClustered())
{
boolean clusteredProxyFactoryFound = false;
for (Iterator it = proxyFactories.keySet().iterator(); it.hasNext(); )
{
String invokerBinding = (String)it.next();
EJBProxyFactory ci = (EJBProxyFactory)proxyFactories.get(invokerBinding);
if (ci instanceof org.jboss.proxy.ejb.ClusterProxyFactory)
clusteredProxyFactoryFound = true;
}
if (!clusteredProxyFactoryFound)
{
log.warn("*** EJB '" + this.metaData.getEjbName() + "' deployed as CLUSTERED but not a single clustered-invoker is bound to container ***");
}
}
}
|
public Object createBeanClassInstance() throws Exception {
return persistenceManager.createBeanClassInstance();
}
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. |
Interceptor createContainerInterceptor() {
return new ContainerInterceptor();
}
|
public EJBObject createHome(Invocation mi) throws Exception {
// The persistence manager takes care of the wiring and creating the EJBObject
getPersistenceManager().createEntity(mi.getMethod(),mi.getArguments(),
(EntityEnterpriseContext) mi.getEnterpriseContext());
// The context implicitely carries the EJBObject
createCount++;
return ((EntityEnterpriseContext)mi.getEnterpriseContext()).getEJBObject();
}
This method takes care of the wiring of the "EJBObject" trio
(target, context, proxy). It delegates to the persistence manager. |
public EJBLocalObject createLocalHome(Invocation mi) throws Exception {
// The persistence manager takes care of the wiring and creating the EJBLocalObject
final EntityEnterpriseContext ctx = (EntityEnterpriseContext)mi.getEnterpriseContext();
getPersistenceManager().createEntity(mi.getMethod(), mi.getArguments(), ctx);
// The context implicitely carries the EJBObject
createCount++;
return localProxyFactory.getEntityEJBLocalObject(ctx.getId(), true);
}
Local home interface implementation |
protected void createService() throws Exception {
// Associate thread with classloader
ClassLoader oldCl = SecurityActions.getContextClassLoader();
SecurityActions.setContextClassLoader(getClassLoader());
pushENC();
try
{
// Acquire classes from CL
if (metaData.getHome() != null)
homeInterface = classLoader.loadClass(metaData.getHome());
if (metaData.getRemote() != null)
remoteInterface = classLoader.loadClass(metaData.getRemote());
// Call default init
super.createService();
// Make some additional validity checks with regards to the container configuration
checkCoherency ();
// Map the bean methods
setupBeanMapping();
// Map the home methods
setupHomeMapping();
// Map the interfaces to Long
setupMarshalledInvocationMapping();
// 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);
}
// Initialize pool
instancePool.create();
for (Iterator it = proxyFactories.keySet().iterator(); it.hasNext(); )
{
String invokerBinding = (String)it.next();
EJBProxyFactory ci = (EJBProxyFactory)proxyFactories.get(invokerBinding);
ci.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);
}
// Init instance cache
instanceCache.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
{
popENC();
// Reset classloader
SecurityActions.setContextClassLoader(oldCl);
}
}
|
protected void destroyService() throws Exception {
// Associate thread with classloader
ClassLoader oldCl = SecurityActions.getContextClassLoader();
SecurityActions.setContextClassLoader(getClassLoader());
pushENC();
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
{
popENC();
// Reset classloader
SecurityActions.setContextClassLoader(oldCl);
}
}
|
public Object find(Invocation mi) throws Exception {
EJBProxyFactory ci = getProxyFactory();
if (ci == null)
{
String msg = "No ProxyFactory, check for ProxyFactoryFinderInterceptor";
throw new IllegalStateException(msg);
}
Method method = mi.getMethod();
Object[] args = mi.getArguments();
EntityEnterpriseContext instance = (EntityEnterpriseContext)mi.getEnterpriseContext();
boolean syncOnCommitOnly = metaData.getContainerConfiguration().getSyncOnCommitOnly();
Transaction tx = mi.getTransaction();
Class returnType = method.getReturnType();
if (Collection.class.isAssignableFrom(returnType) || returnType == Enumeration.class)
{
// as per the spec 9.6.4, entities must be synchronized with the datastore when an ejbFind< METHOD > is called.
if (!syncOnCommitOnly)
{
synchronizeEntitiesWithinTransaction(tx);
}
// Iterator finder
Collection c = getPersistenceManager().findEntities(method, args, instance, ci);
// BMP entity finder methods are allowed to return java.util.Enumeration.
// We need a serializable Enumeration, so we can't use Collections.enumeration()
if (returnType == Enumeration.class)
{
return new SerializableEnumeration(c);
}
else
{
return c;
}
}
else
{
return findSingleObject(tx, method, args, instance, ci);
}
}
This methods finds the target instances by delegating to the persistence
manager It then manufactures EJBObject for all the involved instances
found. |
public Object findLocal(Invocation mi) throws Exception {
Method method = mi.getMethod();
Object[] args = mi.getArguments();
EntityEnterpriseContext instance = (EntityEnterpriseContext)mi.getEnterpriseContext();
boolean syncOnCommitOnly = metaData.getContainerConfiguration().getSyncOnCommitOnly();
Transaction tx = mi.getTransaction();
Class returnType = method.getReturnType();
if (Collection.class.isAssignableFrom(returnType) || returnType == Enumeration.class)
{
// as per the spec 9.6.4, entities must be synchronized with the datastore when an ejbFind< METHOD > is called.
if (!syncOnCommitOnly)
{
synchronizeEntitiesWithinTransaction(tx);
}
// Iterator finder
Collection c = getPersistenceManager().findEntities(method, args, instance, localProxyFactory);
// BMP entity finder methods are allowed to return java.util.Enumeration.
if (returnType == Enumeration.class)
{
return java.util.Collections.enumeration(c);
}
else
{
return c;
}
}
else
{
return findSingleObject(tx, method, args, instance, localProxyFactory);
}
}
|
public void flushCache() {
instanceCache.flush();
}
|
public long getCacheSize() {
return instanceCache.getCacheSize();
}
|
public EJBHome getEJBHome(Invocation mi) throws RemoteException {
EJBProxyFactory ci = getProxyFactory();
if (ci == null)
{
String msg = "No ProxyFactory, check for ProxyFactoryFinderInterceptor";
throw new IllegalStateException(msg);
}
return (EJBHome) ci.getEJBHome();
}
|
public EJBLocalHome getEJBLocalHome(Invocation mi) {
return localProxyFactory.getEJBLocalHome();
}
MF FIXME these are implemented on the client |
public EJBMetaData getEJBMetaDataHome(Invocation mi) throws RemoteException {
EJBProxyFactory ci = getProxyFactory();
if (ci == null)
{
String msg = "No ProxyFactory, check for ProxyFactoryFinderInterceptor";
throw new IllegalStateException(msg);
}
return ci.getEJBMetaData();
}
|
public EJBObject getEJBObject(Invocation mi) throws RemoteException {
EJBProxyFactory ci = getProxyFactory();
if (ci == null)
{
String msg = "No ProxyFactory, check for ProxyFactoryFinderInterceptor";
throw new IllegalStateException(msg);
}
// All we need is an EJBObject for this Id;
return (EJBObject)ci.getEntityEJBObject(((EntityCache) instanceCache).createCacheKey(mi.getId()));
}
A method for the getEJBObject from the handle |
public static GlobalTxEntityMap getGlobalTxEntityMap() {
return globalTxEntityMap;
}
|
public Handle getHandle(Invocation mi) throws RemoteException {
// TODO
throw new Error("Not yet implemented");
}
|
public Class getHomeClass() {
return homeInterface;
}
|
public HomeHandle getHomeHandleHome(Invocation mi) throws RemoteException {
// TODO
throw new Error("Not yet implemented");
}
|
public InstanceCache getInstanceCache() {
return instanceCache;
}
|
public InstancePool getInstancePool() {
return instancePool;
}
|
public Interceptor getInterceptor() {
return interceptor;
}
|
public LocalProxyFactory getLocalProxyFactory() {
return localProxyFactory;
}
|
public EntityPersistenceManager getPersistenceManager() {
return persistenceManager;
}
|
public Object getPrimaryKey(Invocation mi) throws RemoteException {
return mi.getId();
}
|
public Class getRemoteClass() {
return remoteInterface;
}
|
public Object internalInvoke(Invocation mi) throws Exception {
// Invoke through interceptors
return getInterceptor().invoke(mi);
}
|
public Object internalInvokeHome(Invocation mi) throws Exception {
Method method = mi.getMethod();
if (method != null && method.getName().equals("remove"))
{
// Map to EJBHome.remove(Object) to EJBObject.remove()
InvocationType type = mi.getType();
if (type == InvocationType.HOME)
mi.setType(InvocationType.REMOTE);
else if (type == InvocationType.LOCALHOME)
mi.setType(InvocationType.LOCAL);
mi.setMethod(EJBOBJECT_REMOVE);
// Handle or primary key?
Object arg = mi.getArguments()[0];
if (arg instanceof Handle)
{
if (arg == null)
throw new RemoteException("Null handle");
Handle handle = (Handle) arg;
EJBObject ejbObject = handle.getEJBObject();
mi.setId(ejbObject.getPrimaryKey());
}
else
mi.setId(arg);
mi.setArguments(new Object[0]);
return getInterceptor().invoke(mi);
}
// Invoke through interceptors
return getInterceptor().invokeHome(mi);
}
|
public void invokeEjbStore(EntityEnterpriseContext ctx) throws Exception {
if (ctx.getId() != null)
{
final EntityPersistenceManager pm = getPersistenceManager();
pm.invokeEjbStore(ctx);
}
}
Invokes ejbStore method on the instance |
public boolean isIdentical(Invocation mi) throws RemoteException {
EJBProxyFactory ci = getProxyFactory();
if (ci == null)
{
String msg = "No ProxyFactory, check for ProxyFactoryFinderInterceptor";
throw new IllegalStateException(msg);
}
return ci.isIdentical(this, mi);
}
|
public boolean isReadOnly() {
return readOnly;
}
|
public void postCreateHome(Invocation mi) throws Exception {
// The persistence manager takes care of the post create step
getPersistenceManager().postCreateEntity(mi.getMethod(),mi.getArguments(),
(EntityEnterpriseContext) mi.getEnterpriseContext());
}
Delegates to the persistence manager postCreateEntityMethod. |
public void postCreateLocalHome(Invocation mi) throws Exception {
// The persistence manager takes care of the post create step
getPersistenceManager().postCreateEntity(mi.getMethod(),mi.getArguments(),
(EntityEnterpriseContext) mi.getEnterpriseContext());
}
Delegates to the persistence manager postCreateEntityMethod. |
public void remove(Invocation mi) throws RemoveException, RemoteException {
// synchronize entities with the datastore before the bean is removed
// this will write queued updates so datastore will be consistent before removal
Transaction tx = mi.getTransaction();
if (!getBeanMetaData().getContainerConfiguration().getSyncOnCommitOnly())
synchronizeEntitiesWithinTransaction(tx);
// Get the persistence manager to do the dirty work
EntityEnterpriseContext ctx = (EntityEnterpriseContext)mi.getEnterpriseContext();
getPersistenceManager().removeEntity(ctx);
Object pk = ctx.getId();
removeTimerService(pk);
// We signify "removed" with a null id
// There is no need to synchronize on the context since all the threads reaching here have
// gone through the InstanceInterceptor so the instance is locked and we only have one thread
// the case of reentrant threads is unclear (would you want to delete an instance in reentrancy)
ctx.setId(null);
removeCount++;
}
|
public void removeHome(Invocation mi) throws RemoveException, RemoteException {
throw new Error("Not yet implemented");
}
|
public void removeLocalHome(Invocation mi) throws RemoveException, RemoteException {
throw new Error("Not Yet Implemented");
}
|
public void resetStatistic() {
}
|
public Map retrieveStatistic() {
// Loop through all Interceptors and add statistics
Map lStatistics = new HashMap();
StatisticsProvider lProvider = (StatisticsProvider) getPersistenceManager();
lStatistics.putAll( lProvider.retrieveStatistic() );
lProvider = (StatisticsProvider) getInstancePool();
lStatistics.putAll( lProvider.retrieveStatistic() );
return lStatistics;
}
|
public void setInstanceCache(InstanceCache ic) {
if (ic == null)
throw new IllegalArgumentException("Null cache");
this.instanceCache = ic;
ic.setContainer(this);
}
|
public void setInstancePool(InstancePool ip) {
if (ip == null)
throw new IllegalArgumentException("Null pool");
this.instancePool = ip;
ip.setContainer(this);
}
|
public void setPersistenceManager(EntityPersistenceManager pm) {
if (pm == null)
throw new IllegalArgumentException("Null persistence manager");
persistenceManager = pm;
pm.setContainer(this);
}
|
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" );
}
if( TimedObject.class.isAssignableFrom( beanClass ) ) {
// Map ejbTimeout
beanMapping.put(
TimedObject.class.getMethod( "ejbTimeout", new Class[] { Timer.class } ),
beanClass.getMethod( "ejbTimeout", new Class[] { Timer.class } )
);
}
}
catch (Exception e)
{
// ditch the half built mappings
homeMapping.clear();
beanMapping.clear();
throw e;
}
}
|
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< handleMethods.length ;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;
}
}
|
protected void setupMarshalledInvocationMapping() throws Exception {
// Create method mappings for container invoker
if (homeInterface != null)
{
Method [] m = homeInterface.getMethods();
for (int i = 0 ; i< m.length ; i++)
{
marshalledInvocationMapping.put( new Long(MarshalledInvocation.calculateHash(m[i])), m[i]);
}
}
if (remoteInterface != null)
{
Method [] m = remoteInterface.getMethods();
for (int j = 0 ; j< m.length ; j++)
{
marshalledInvocationMapping.put( new Long(MarshalledInvocation.calculateHash(m[j])), m[j]);
}
}
// Get the getEJBObjectMethod
Method getEJBObjectMethod = Class.forName("javax.ejb.Handle").getMethod("getEJBObject", new Class[0]);
// Hash it
marshalledInvocationMapping.put(new Long(MarshalledInvocation.calculateHash(getEJBObjectMethod)),getEJBObjectMethod);
}
|
protected void startService() throws Exception {
// Associate thread with classloader
ClassLoader oldCl = SecurityActions.getContextClassLoader();
SecurityActions.setContextClassLoader(getClassLoader());
pushENC();
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 the instance pool
instancePool.start();
Interceptor i = interceptor;
while(i != null)
{
i.start();
i = i.getNext();
}
// Restore persisted ejb timers
restoreTimers();
}
finally
{
popENC();
// Reset classloader
SecurityActions.setContextClassLoader(oldCl);
}
}
|
protected void stopService() throws Exception {
// Associate thread with classloader
ClassLoader oldCl = SecurityActions.getContextClassLoader();
SecurityActions.setContextClassLoader(getClassLoader());
pushENC();
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
{
popENC();
// Reset classloader
SecurityActions.setContextClassLoader(oldCl);
}
}
|
public void storeEntity(EntityEnterpriseContext ctx) throws Exception {
if (ctx.getId() != null)
{
final EntityPersistenceManager pm = getPersistenceManager();
if(pm.isStoreRequired(ctx))
{
pm.storeEntity(ctx);
}
}
}
For CMP actually stores the instance |
public static void synchronizeEntitiesWithinTransaction(Transaction tx) {
// If there is no transaction, there is nothing to synchronize.
if(tx != null)
{
getGlobalTxEntityMap().synchronizeEntities(tx);
}
}
Stores all of the entities associated with the specified transaction.
As per the spec 9.6.4, entities must be synchronized with the datastore
when an ejbFind is called.
Also, all entities within entire transaction should be synchronized before
a remove, otherwise there may be problems with 'cascade delete'. |