User: pra
Date: 00/12/06 05:00:56
Modified: src/main/org/jboss/ejb ContainerFactory.java
Added: src/main/org/jboss/ejb MessageDrivenContainer.java
MessageDrivenEnterpriseContext.java
Log:
Added MessageDriven bean classes in ejb hierarchy. ContainerInvoker is changed to
support MessageDriven Beans
Revision Changes Path
1.58 +111 -3 jboss/src/main/org/jboss/ejb/ContainerFactory.java
Index: ContainerFactory.java
===================================================================
RCS file: /products/cvs/ejboss/jboss/src/main/org/jboss/ejb/ContainerFactory.java,v
retrieving revision 1.57
retrieving revision 1.58
diff -u -r1.57 -r1.58
--- ContainerFactory.java 2000/11/14 21:41:06 1.57
+++ ContainerFactory.java 2000/12/06 13:00:55 1.58
@@ -58,6 +58,7 @@
import org.jboss.metadata.BeanMetaData;
import org.jboss.metadata.SessionMetaData;
import org.jboss.metadata.EntityMetaData;
+import org.jboss.metadata.MessageDrivenMetaData;
import org.jboss.metadata.ConfigurationMetaData;
import org.jboss.metadata.XmlLoadable;
import org.jboss.metadata.XmlFileLoader;
@@ -70,13 +71,15 @@
* an EJB-jar or EJB-JAR XML file, which will be used to instantiate containers and
make
* them available for invocation.
*
+* Now also works with message driven beans
* @see Container
* @author Rickard �berg ([EMAIL PROTECTED])
* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Juha Lindfors</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Sebastien Alborini</a>
+* @author Peter Antman ([EMAIL PROTECTED])
*
-* @version $Revision: 1.57 $
+* @version $Revision: 1.58 $
*/
public class ContainerFactory
extends org.jboss.util.ServiceMBeanSupport
@@ -87,7 +90,7 @@
public static String DEFAULT_STATEFUL_CONFIGURATION = "Default Stateful
SessionBean";
public static String DEFAULT_ENTITY_BMP_CONFIGURATION = "Default BMP EntityBean";
public static String DEFAULT_ENTITY_CMP_CONFIGURATION = "Default CMP EntityBean";
-
+ public static String DEFAULT_MESSAGEDRIVEN_CONFIGURATION = "Default MesageDriven
Bean";
// Attributes ----------------------------------------------------
// Temp directory where deployed jars are stored
File tmpDir;
@@ -394,8 +397,113 @@
BeanMetaData bean = (BeanMetaData)beans.next();
log.log("Deploying "+bean.getEjbName());
+ // Added message driven deployment
+ if (bean.isMessageDriven()) {
+ // Stolen from Stateless deploy
+ // Create container
+ MessageDrivenContainer container = new MessageDrivenContainer();
+
+ // Create classloader for this container
+ // Only used to identify bean. Not really used for class loading!
+ container.setClassLoader(new URLClassLoader(new URL[0], cl));
+
+ // Set metadata
+ container.setBeanMetaData(bean);
+
+ // get the container configuration for this bean
+ // a default configuration is now always provided
+ ConfigurationMetaData conf = bean.getContainerConfiguration();
+
+ // Set transaction manager
+ container.setTransactionManager((TransactionManager)new
InitialContext().lookup("java:/TransactionManager"));
+
+ // Set security manager & role mapping manager
+ String securityManagerJNDIName = conf.getAuthenticationModule();
+ String roleMappingManagerJNDIName = conf.getRoleMappingManager();
+
+ if ((securityManagerJNDIName != null) &&
(roleMappingManagerJNDIName != null))
+ {
+ try
+ {
+ EJBSecurityManager ejbS = (EJBSecurityManager)new
InitialContext().lookup(securityManagerJNDIName);
+ container.setSecurityManager( ejbS );
+ }
+ catch (NamingException ne)
+ {
+ throw new DeploymentException( "Could not find the Security
Manager specified for this container", ne );
+ }
+
+ try
+ {
+ RealmMapping rM = (RealmMapping)new
InitialContext().lookup(roleMappingManagerJNDIName);
+ container.setRealmMapping( rM );
+ }
+ catch (NamingException ne)
+ {
+ throw new DeploymentException( "Could not find the Role
Mapping Manager specified for this container", ne );
+ }
+ }
+
+ // Set container invoker
+ ContainerInvoker ci = null;
+ try {
+
+ ci =
(ContainerInvoker)cl.loadClass(conf.getContainerInvoker()).newInstance();
+ } catch(Exception e) {
+ throw new DeploymentException("Missing or invalid Container
Invoker (in jboss.xml or standardjboss.xml): " + conf.getContainerInvoker() +" - " +
e);
+ }
+ if (ci instanceof XmlLoadable) {
+ // the container invoker can load its configuration from the
jboss.xml element
+ ((XmlLoadable)ci).importXml(conf.getContainerInvokerConf());
+ }
+ container.setContainerInvoker(ci);
+
+ // Set instance pool
+ InstancePool ip = null;
+ try {
+ ip =
(InstancePool)cl.loadClass(conf.getInstancePool()).newInstance();
+ } catch(Exception e) {
+ throw new DeploymentException("Missing or invalid Instance Pool
(in jboss.xml or standardjboss.xml)");
+ }
+ if (ip instanceof XmlLoadable) {
+ ((XmlLoadable)ip).importXml(conf.getContainerPoolConf());
+ }
+ container.setInstancePool(ip);
+
+ // Create interceptors
+
+ container.addInterceptor(new LogInterceptor());
+ container.addInterceptor(new SecurityInterceptor());
+
+ if (((MessageDrivenMetaData)bean).isContainerManagedTx())
+ {
+ // CMT
+ container.addInterceptor(new TxInterceptorCMT());
+
+ if (metricsEnabled)
+ container.addInterceptor(new MetricsInterceptor());
+
+ container.addInterceptor(new
MessageDrivenInstanceInterceptor());
+ }
+ else
+ {
+ // BMT
+ container.addInterceptor(new
MessageDrivenInstanceInterceptor());
+ // FIXME. should we have a special BMT tx interceptor
+ // to place ACK there???
+ container.addInterceptor(new MessageDrivenTxInterceptorBMT());
+
+ if (metricsEnabled)
+ container.addInterceptor(new MetricsInterceptor());
+ }
+
+ // Finally we add the last interceptor from the container
+ container.addInterceptor(container.createContainerInterceptor());
- if (bean.isSession()) // Is session?
+ // Add container to application
+ app.addContainer(container);
+ }
+ else if (bean.isSession()) // Is session?
{
if (((SessionMetaData)bean).isStateless()) // Is stateless?
{
1.1 jboss/src/main/org/jboss/ejb/MessageDrivenContainer.java
Index: MessageDrivenContainer.java
===================================================================
/*
* jBoss, the OpenSource EJB server
*
* Distributable under GPL license.
* See terms of license at gnu.org.
*/
package org.jboss.ejb;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.Principal;
import java.util.Map;
import java.util.HashMap;
import javax.ejb.Handle;
import javax.ejb.HomeHandle;
import javax.ejb.EJBObject;
import javax.ejb.EJBHome;
import javax.ejb.EJBMetaData;
import javax.ejb.CreateException;
import javax.ejb.RemoveException;
import javax.ejb.EJBException;
import org.jboss.logging.Logger;
/**
* MessageDrivenContainer, based on the StatelessSessionContainer
*
* @see <related>
* @author Peter Antman ([EMAIL PROTECTED])
* @author Rickard �berg ([EMAIL PROTECTED])
* @author <a href="[EMAIL PROTECTED]">Marc Fleury</a>
* @version $Revision: 1.1 $
* extends StatelessSessionContainer
*/
public class MessageDrivenContainer
extends Container
implements ContainerInvokerContainer, InstancePoolContainer
{
// These are the mappings between the remote interface methods and the bean
methods
protected Map beanMapping;
// This is the container invoker for this container
protected ContainerInvoker containerInvoker;
// This is the instancepool that is to be used
protected InstancePool instancePool;
// This is the first interceptor in the chain. The last interceptor must be
provided by the container itself
protected Interceptor interceptor;
// Static --------------------------------------------------------
// Constructors --------------------------------------------------
// Public --------------------------------------------------------
public void setContainerInvoker(ContainerInvoker ci)
{
if (ci == null)
throw new IllegalArgumentException("Null invoker");
this.containerInvoker = ci;
ci.setContainer(this);
}
public ContainerInvoker getContainerInvoker()
{
return containerInvoker;
}
public void setInstancePool(InstancePool ip)
{
if (ip == null)
throw new IllegalArgumentException("Null pool");
this.instancePool = ip;
ip.setContainer(this);
}
public InstancePool getInstancePool()
{
return instancePool;
}
public void addInterceptor(Interceptor in)
{
if (interceptor == null)
{
interceptor = in;
} else
{
Interceptor current = interceptor;
while ( current.getNext() != null)
{
current = current.getNext();
}
current.setNext(in);
}
}
public Interceptor getInterceptor()
{
return interceptor;
}
/* ContainerInvokerContainer - not needed, should we skip inherit this
* or just throw Error??
*/
public Class getHomeClass()
{
throw new Error("Not valid for MessageDriven beans");
}
public Class getRemoteClass()
{
throw new Error("Not valid for MessageDriven beans");
}
// Container implementation - overridden here ----------------------
public void init()
throws Exception
{
try {
// Associate thread with classloader
ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(getClassLoader());
// Call default init
super.init();
// Map the bean methods
setupBeanMapping();
// Map the home methods
// Are these vallid, probalye not!!
//setupHomeMapping();
// Initialize pool
instancePool.init();
// Init container invoker
containerInvoker.init();
// Initialize the interceptor by calling the chain
Interceptor in = interceptor;
while (in != null)
{
in.setContainer(this);
in.init();
in = in.getNext();
}
// Reset classloader
Thread.currentThread().setContextClassLoader(oldCl);
}catch(Throwable ex) {
Logger.error("Serius error in init: " + ex);
//DEBUG ex.printStackTrace();
throw new Exception(ex.toString());
}
}
public void start()
throws Exception
{
// Associate thread with classloader
ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(getClassLoader());
// Call default start
super.start();
// Start container invoker
containerInvoker.start();
// Start the instance pool
instancePool.start();
// Start all interceptors in the chain
Interceptor in = interceptor;
while (in != null)
{
in.start();
in = in.getNext();
}
// Reset classloader
Thread.currentThread().setContextClassLoader(oldCl);
}
public void stop()
{
// Associate thread with classloader
ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(getClassLoader());
// Call default stop
super.stop();
// Stop container invoker
containerInvoker.stop();
// Stop the instance pool
instancePool.stop();
// Stop all interceptors in the chain
Interceptor in = interceptor;
while (in != null)
{
in.stop();
in = in.getNext();
}
// Reset classloader
Thread.currentThread().setContextClassLoader(oldCl);
}
public void destroy()
{
// Associate thread with classloader
ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(getClassLoader());
// Call default destroy
super.destroy();
// Destroy container invoker
containerInvoker.destroy();
// Destroy the pool
instancePool.destroy();
// Destroy all the interceptors in the chain
Interceptor in = interceptor;
while (in != null)
{
in.destroy();
in = in.getNext();
}
// Reset classloader
Thread.currentThread().setContextClassLoader(oldCl);
}
public Object invokeHome(MethodInvocation mi)
throws Exception
{
throw new Error("Not valid for MessageDriven beans");
//return getInterceptor().invokeHome(mi);
}
/**
* This method does invocation interpositioning of tx and security,
* retrieves the instance from an object table, and invokes the method
* on the particular instance
*
* @param id
* @param m
* @param args
* @return
* @exception Exception
*/
public Object invoke(MethodInvocation mi)
throws Exception
{
// Invoke through interceptors
return getInterceptor().invoke(mi);
}
// EJBHome implementation ----------------------------------------
public EJBObject createHome()
throws java.rmi.RemoteException, CreateException
{
throw new Error("Not valid for MessageDriven beans");
//Object obj = containerInvoker.getStatelessSessionEJBObject();
//return (EJBObject)obj;
}
public void removeHome(Handle handle)
throws java.rmi.RemoteException, RemoveException
{
throw new Error("Not valid for MessageDriven beans");
// TODO
}
public void removeHome(Object primaryKey)
throws java.rmi.RemoteException, RemoveException
{
throw new Error("Not valid for MessageDriven beans");
// TODO
}
public EJBMetaData getEJBMetaDataHome()
throws java.rmi.RemoteException
{
// TODO
//return null;
throw new Error("Not valid for MessageDriven beans");
}
public HomeHandle getHomeHandleHome()
throws java.rmi.RemoteException
{
// TODO
//return null;
throw new Error("Not valid for MessageDriven beans");
}
protected void setupBeanMapping()
throws NoSuchMethodException
{
Map map = new HashMap();
/*
* Here we should have a way of looking up wich message class
* the MessageDriven bean implements, by doing this we might
* be able to use other MOM systems, aka XmlBlaser. TODO!
*/
String msgInterface = "javax.jms.MessageListener";
String msgMethod = "onMessage";
String msgArgument = "javax.jms.Message";
// Get the method
Class msgInterfaceClass = null;
Class argumentClass = null;
try {
msgInterfaceClass = Class.forName(msgInterface);
argumentClass = Class.forName(msgArgument);
} catch(ClassNotFoundException ex) {
Logger.error("Could not the classes for message interface" + msgInterface);
// Hackish
throw new NoSuchMethodException("Could not the classes for message
interface" + msgInterface + ": " + ex);
}
Method m = msgInterfaceClass.getMethod(msgMethod, new Class[] {argumentClass});
// Implemented by bean
map.put(m, beanClass.getMethod(m.getName(), m.getParameterTypes()));
//DEBUG Logger.debug("Mapped "+m.getName()+" "+m.hashCode()+"to "+map.get(m));
beanMapping = map;
}
Interceptor createContainerInterceptor()
{
return new ContainerInterceptor();
}
// This is the last step before invocation - all interceptors are done
class ContainerInterceptor
implements Interceptor
{
public void setContainer(Container con) {}
public void setNext(Interceptor interceptor) {}
public Interceptor getNext() { return null; }
public void init() {}
public void start() {}
public void stop() {}
public void destroy() {}
public Object invokeHome(MethodInvocation mi)
throws Exception
{
throw new Error("Not valid for MessageDriven beans");
}
/*
* FIXME Design problem, who will do the acknowledging for
* beans with bean managed transaction?? Probably best done in the
* listener "proxys"
*/
public Object invoke(MethodInvocation mi)
throws Exception
{
//wire the transaction on the context, this is how the instance remember
the tx
if (mi.getEnterpriseContext().getTransaction() == null)
mi.getEnterpriseContext().setTransaction(mi.getTransaction());
// Get method and instance to invoke upon
Method m = (Method)beanMapping.get(mi.getMethod());
//If we have a method that needs to be done by the container (EJBObject
methods)
// Here we may have a problem! MessageDriven beans does not
// have a remote inteface, is the methods here only the
// ones in the EJBObject remote interface, or are there
// others????
/*
if (m.getDeclaringClass().equals(StatelessSessionContainer.class))
{
try
{
return m.invoke(StatelessSessionContainer.this, new Object[] {
mi });
} catch (IllegalAccessException e)
{
*/
// Throw this as a bean exception...(?)
/*
throw new EJBException(e);
} catch (InvocationTargetException e)
{
Throwable ex = e.getTargetException();
if (ex instanceof EJBException)
throw (EJBException)ex;
else if (ex instanceof RuntimeException)
throw new EJBException((Exception)ex);
*/
// Transform runtime exception into what a bean *should* have thrown
/*
else if (ex instanceof Exception)
throw (Exception)ex;
else
throw (Error)ex;
}
} else
*/
// we have a method that needs to be done by a bean instance
{
// Invoke and handle exceptions
try
{
return m.invoke(mi.getEnterpriseContext().getInstance(),
mi.getArguments());
} catch (IllegalAccessException e)
{
// Throw this as a bean exception...(?)
throw new EJBException(e);
} catch (InvocationTargetException e)
{
Throwable ex = e.getTargetException();
if (ex instanceof EJBException)
throw (EJBException)ex;
else if (ex instanceof RuntimeException)
throw new EJBException((Exception)ex); // Transform runtime
exception into what a bean *should* have thrown
else if (ex instanceof Exception)
throw (Exception)ex;
else
throw (Error)ex;
}
}
}
}
}
1.1 jboss/src/main/org/jboss/ejb/MessageDrivenEnterpriseContext.java
Index: MessageDrivenEnterpriseContext.java
===================================================================
/*
* jBoss, the OpenSource EJB server
*
* Distributable under GPL license.
* See terms of license at gnu.org.
*/
package org.jboss.ejb;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.lang.IllegalStateException;
import java.security.Principal;
import java.rmi.RemoteException;
import java.rmi.ServerException;
import javax.transaction.UserTransaction;
import javax.ejb.EJBHome;
import javax.ejb.EJBObject;
import javax.ejb.MessageDrivenContext;
import javax.ejb.MessageDrivenBean;
import javax.ejb.SessionContext;
import javax.ejb.EJBException;
import org.jboss.logging.Logger;
import org.jboss.metadata.MessageDrivenMetaData;
/**
* Context for message driven beans, based on Stateless.
* FIXME - not yet verified agains spec!!!
* <description>
*
* @see <related>
* @author Peter Antman ([EMAIL PROTECTED])
* @author Rickard �berg ([EMAIL PROTECTED])
* @author <a href="[EMAIL PROTECTED]">Sebastien Alborini</a>
* @version $Revision: 1.1 $
*/
public class MessageDrivenEnterpriseContext
extends EnterpriseContext
{
// Constants -----------------------------------------------------
// Attributes ----------------------------------------------------
//EJBObject ejbObject;
MessageDrivenContext ctx;
// Static --------------------------------------------------------
// Constructors --------------------------------------------------
public MessageDrivenEnterpriseContext(Object instance, Container con)
throws Exception
{
super(instance, con);
ctx = new MessageDrivenContextImpl();
((MessageDrivenBean)instance).setMessageDrivenContext(ctx);
try
{
Method ejbCreate = instance.getClass().getMethod("ejbCreate", new Class[0]);
ejbCreate.invoke(instance, new Object[0]);
} catch (InvocationTargetException e)
{
Throwable ex = e.getTargetException();
if (ex instanceof EJBException)
throw (Exception)ex;
else if (ex instanceof RuntimeException)
throw new EJBException((Exception)ex); // Transform runtime exception
into what a bean *should* have thrown
else if (ex instanceof Exception)
throw (Exception)ex;
else
throw (Error)ex;
}
}
// Public --------------------------------------------------------
// FIXME
// Here we have some problems. If we are to use the Stateless stuff,
// should we inherit from StatelessSessionEnterpriseContext or what?
public void setEJBObject(EJBObject eo) {
throw new Error("Not applicatable for MessageDrivenContext");
//NOOP
//ejbObject = eo;
}
public EJBObject getEJBObject() {
throw new Error("Not applicatable for MessageDrivenContext");
//return ejbObject;
}
// This is used at least in The pool, created there even!!!
// and in interceptors, ugh
public SessionContext getSessionContext() {
throw new Error("Not applicatable for MessageDrivenContext");
//return ctx;
}
public MessageDrivenContext getMessageDrivenContext() {
return ctx;
}
// EnterpriseContext overrides -----------------------------------
public void discard()
throws RemoteException
{
((MessageDrivenBean)instance).ejbRemove();
}
// Package protected ---------------------------------------------
// Protected -----------------------------------------------------
// Private -------------------------------------------------------
// Inner classes -------------------------------------------------
protected class MessageDrivenContextImpl
extends EJBContextImpl
implements MessageDrivenContext
{
public EJBHome getEJBHome()
{
Logger.log("MessageDriven bean is not allowed to call getEJBHome");
throw new IllegalStateException("Not valid for MessageDriven beans");
}
public boolean isCallerInRole(String id)
{
Logger.log("MessageDriven bean is not allowed to call isCallerInRole");
throw new IllegalStateException("Not valid for MessageDriven beans");
}
public Principal getCallerPrincipal()
{
Logger.log("MessageDriven bean is not allowed to call
getCallerPrincipal()");
throw new IllegalStateException("Not valid for MessageDriven beans");
}
public boolean getRollbackOnly()
{
if (((MessageDrivenMetaData)con.getBeanMetaData()).getAcknowledgeMode() !=
MessageDrivenMetaData.CLIENT_ACKNOWLEDGE_MODE) {
// NO transaction
Logger.log("MessageDriven bean is not allowed to call getRollbackOnly
with this transaction settings");
throw new IllegalStateException("MessageDriven bean is not allowed to call
getRollbackOnly with this transaction settings");
} else {
return super.getRollbackOnly();
}
}
public void setRollbackOnly()
{
if (((MessageDrivenMetaData)con.getBeanMetaData()).getAcknowledgeMode() !=
MessageDrivenMetaData.CLIENT_ACKNOWLEDGE_MODE) {
// NO transaction
Logger.log("MessageDriven bean is not allowed to call setRollbackOnly
with this transaction settings");
throw new IllegalStateException("MessageDriven bean is not allowed to
call setRollbackOnly with this transaction settings");
}else {
super.setRollbackOnly();
}
}
public UserTransaction getUserTransaction()
{
if (((MessageDrivenMetaData)con.getBeanMetaData()).isContainerManagedTx() )
{
// NO transaction
Logger.log("MessageDriven bean is not allowed to get a UserTransactio:
transaction is containeremanaged");
throw new IllegalStateException("MessageDriven bean is not allowed to
get a UserTransactio: transaction is containeremanaged");
}else {
return super.getUserTransaction();
}
}
}
}