FileDocCategorySizeDatePackage
MessagingContainer.javaAPI DocJBoss 4.2.120382Fri Jul 13 20:53:56 BST 2007org.jboss.ejb3.mdb

MessagingContainer

public abstract class MessagingContainer extends EJBContainer implements org.jboss.ejb3.timerservice.TimedObjectInvoker
version
$Revision: 61280 $
author
William DeCoste

Fields Summary
private static final Logger
log
protected TimerService
timerService
protected ActivationSpec
activationSpec
protected org.jboss.ejb3.mdb.inflow.JBossMessageEndpointFactory
messageEndpointFactory
protected static final String
DEFAULT_DESTINATION_TYPE
Default destination type. Used when no message-driven-destination is given in ejb-jar, and a lookup of destinationJNDI from jboss.xml is not successfull. Default value: javax.jms.Topic.
protected static final String
JMS_ADAPTOR
protected static final String
DESTINATION
protected static final String
DESTINATION_TYPE
protected static final String
PROVIDER_ADAPTER_JNDI
protected static final String
MAX_SESSION
Constructors Summary
public MessagingContainer(String ejbName, org.jboss.aop.AspectManager manager, ClassLoader cl, String beanClassName, Hashtable ctxProperties, org.jboss.ejb3.interceptor.InterceptorInfoRepository interceptorRepository, Ejb3Deployment deployment)


             
                 
   
      super(Ejb3Module.BASE_EJB3_JMX_NAME + ",name=" + ejbName, manager, cl, beanClassName, ejbName, ctxProperties, interceptorRepository, deployment);
      
      beanContextClass = MDBContext.class;
      
      messageEndpointFactory = new JBossMessageEndpointFactory();
      messageEndpointFactory.setContainer(this);
   
Methods Summary
protected voidaddActivationSpecProperty(java.util.Map result, ActivationConfigProperty property)

      if (!property.propertyName().equals("messagingType"))
      {
         ActivationConfigPropertyMetaData metaData = new ActivationConfigPropertyMetaData();
         try
         {
            Field nameField = ActivationConfigPropertyMetaData.class.getDeclaredField("name");
            nameField.setAccessible(true);
            nameField.set(metaData, property.propertyName());
            Field valueField = ActivationConfigPropertyMetaData.class.getDeclaredField("value");
            valueField.setAccessible(true);
            valueField.set(metaData, property.propertyValue());
         }
         catch (Exception e)
         {
            throw new RuntimeException(e);
         }
   
         /*
          * Older versions don't have this
          * TODO revert to this after we ditch 4.0.3SP1 as supported EJB3 platform
         metaData.setName(property.propertyName());
         metaData.setValue(property.propertyValue());
         */
         result.put(property.propertyName(), metaData);
      }
   
public voidcallTimeout(javax.ejb.Timer timer)

      Method timeout = callbackHandler.getTimeoutCallback();
      if (timeout == null) throw new EJBException("No method has been annotated with @Timeout");
      Object[] args = {timer};
      try
      {
         localInvoke(timeout, args);
      }
      catch (Throwable throwable)
      {
         if (throwable instanceof Exception) throw (Exception) throwable;
         throw new RuntimeException(throwable);
      }
   
private DestinationcreateDestination(java.lang.Class type, javax.naming.Context ctx, java.lang.String jndiName, java.lang.String jndiSuffix)
Create and or lookup a JMS destination.

param
type Either javax.jms.Queue or javax.jms.Topic.
param
ctx The naming context to lookup destinations from.
param
jndiName The name to use when looking up destinations.
param
jndiSuffix The name to use when creating destinations.
return
The destination.
throws
IllegalArgumentException Type is not Queue or Topic.
throws
Exception Description of Exception

      try
      {
         // first try to look it up
         return (Destination) ctx.lookup(jndiName);
      }
      catch (NamingException e)
      {
         // is JMS?
         if (getDestination() == null)
         {
            return null;
         }
         else
         {
            // if the lookup failes, the try to create it
            log.warn("destination not found: " + jndiName + " reason: " + e);
            log.warn("creating a new temporary destination: " + jndiName);
            
            createTemporaryDestination(type, jndiSuffix);
       
            // try to look it up again
            return (Destination) ctx.lookup(jndiName);
         }
      }
   
private voidcreateTemporaryDestination(java.lang.Class type, java.lang.String jndiSuffix)

      //
      // jason: we should do away with this...
      //
      // attempt to create the destination (note, this is very
      // very, very unportable).
      //

      // MBeanServer server = org.jboss.mx.util.MBeanServerLocator.locateJBoss();
      
//      String methodName;
//      String destinationContext;
//      if (type == Topic.class)
//      {
//         destinationContext = "topic";
//         methodName = "createTopic";
//      }
//      else if (type == Queue.class)
//      {
//         destinationContext = "queue";
//         methodName = "createQueue";
//      }
//      else
//      {
//         // type was not a Topic or Queue, bad user
//         throw new IllegalArgumentException
//                 ("Expected javax.jms.Queue or javax.jms.Topic: " + type);
//      }
      
      /* No longer supported (AS 4.x)
      ObjectName destinationManagerName = new ObjectName("jboss.mq:service=DestinationManager");
      
      KernelAbstraction kernel = KernelAbstractionFactory.getInstance();
      // invoke the server to create the destination
      Object result = kernel.invoke(destinationManagerName,
              methodName,
              new Object[]{jndiSuffix},
              new String[]{"java.lang.String"});
      
      InitialContext jndiContext = InitialContextFactory.getInitialContext();
      String binding = destinationContext + "/" + jndiSuffix;
      try
      {
         jndiContext.lookup(binding);
      }
      catch (NamingException e)
      {
         jndiContext.rebind(binding, result);
      }
      */
      
      //throw new UnsupportedOperationException("Can't create destination " + destinationContext + "/" + jndiSuffix);
      JMSDestinationFactory.getInstance().createDestination(type, jndiSuffix);
   
public abstract java.util.MapgetActivationConfigProperties()

protected java.lang.StringgetDestination()

      ActivationConfigPropertyMetaData property = (ActivationConfigPropertyMetaData)getActivationConfigProperties().get(DESTINATION);
      if (property != null)
         return property.getValue();
      return null;
   
protected java.lang.StringgetDestinationType()

      ActivationConfigPropertyMetaData property = (ActivationConfigPropertyMetaData)getActivationConfigProperties().get(DESTINATION_TYPE);
      if (property != null)
         return property.getValue();
      return null;
   
protected java.lang.StringgetDestinationType(javax.naming.Context ctx, java.lang.String destinationJNDI)
Try to get a destination type by looking up the destination JNDI, or provide a default if there is not destinationJNDI or if it is not possible to lookup.

param
ctx The naming context to lookup destinations from.
param
destinationJNDI The name to use when looking up destinations.
return
The destination type, either derived from destinationJDNI or DEFAULT_DESTINATION_TYPE

      String destType = null;

      if (destinationJNDI != null)
      {
         try
         {
            Destination dest = (Destination) ctx.lookup(destinationJNDI);
            if (dest instanceof javax.jms.Topic)
            {
               destType = "javax.jms.Topic";
            }
            else if (dest instanceof javax.jms.Queue)
            {
               destType = "javax.jms.Queue";
            }
         }
         catch (NamingException ex)
         {
            log.debug("Could not do heristic lookup of destination ", ex);
         }

      }
      if (destType == null)
      {
         log.warn("Could not determine destination type, defaults to: " +
                 DEFAULT_DESTINATION_TYPE);

         destType = DEFAULT_DESTINATION_TYPE;
      }

      return destType;
   
protected org.jboss.jms.jndi.JMSProviderAdaptergetJMSProviderAdapter()
Return the JMSProviderAdapter that should be used.

return
The JMSProviderAdapter to use.

      Context context = getInitialContext();
      //todo make this pluggable
      String providerAdapterJNDI = getProviderAdapterJNDI();
      try
      {
         log.debug("Looking up provider adapter: " + providerAdapterJNDI);
     
         return (JMSProviderAdapter) context.lookup(providerAdapterJNDI);
      }
      finally
      {
         context.close();
      }
   
public javax.management.ObjectNamegetJmxName()

      ObjectName jmxName = null;
      String jndiName = ProxyFactoryHelper.getLocalJndiName(this);
      // The name must be escaped since the jndiName may be arbitrary
      String name = org.jboss.ejb.Container.BASE_EJB_CONTAINER_NAME + ",jndiName=" + jndiName;
      try
      {
         jmxName = org.jboss.mx.util.ObjectNameConverter.convert(name);
      }
      catch (MalformedObjectNameException e)
      {
         e.printStackTrace();
         throw new RuntimeException("Failed to create ObjectName, msg=" + e.getMessage());
      }

      return jmxName;
   
protected java.lang.StringgetMaxSession()

      ActivationConfigPropertyMetaData property = (ActivationConfigPropertyMetaData)getActivationConfigProperties().get(MAX_SESSION);
      if (property != null)
         return property.getValue();
      return null;
   
public abstract java.lang.ClassgetMessagingType()

public abstract org.jboss.aop.MethodInfogetMethodInfo(java.lang.reflect.Method method)

protected java.lang.StringgetProviderAdapterJNDI()

      ActivationConfigPropertyMetaData property = (ActivationConfigPropertyMetaData)getActivationConfigProperties().get(PROVIDER_ADAPTER_JNDI);
      if (property != null)
         return property.getValue();
      return "java:/DefaultJMSProvider";
   
public java.lang.StringgetResourceAdaptorName()

      ResourceAdapter annotation = (ResourceAdapter) resolveAnnotation(ResourceAdapter.class);
      if (annotation == null)
         return JMS_ADAPTOR;
      
      return annotation.value();
   
public TimerServicegetTimerService()

      return timerService;
   
public TimerServicegetTimerService(java.lang.Object pKey)

      assert timerService != null : "Timer Service not yet initialized";
      return timerService;
   
protected voidinitializePool()

   
       
   
     super.initializePool();
     
     String maxSession = getMaxSession();
     if (maxSession != null)
     {
        pool.setMaxSize(Integer.parseInt(maxSession));
     }
   
protected voidinnerCreateQueue(javax.naming.Context context)

      log.debug("Got destination type Queue for " + ejbName);

      // Get the JNDI suffix of the destination
      String jndiSuffix = parseJndiSuffix(getDestination(), ejbName);
      log.debug("jndiSuffix: " + jndiSuffix);

      // lookup or create the destination queue
      Queue queue = null;
      try
      {
         // First we try the specified queue
         if (getDestination() != null)
            queue = (Queue) context.lookup(getDestination());
      }
      catch (NamingException e)
      {
         log.warn("Could not find the queue destination-jndi-name=" + getDestination());
      }
      catch (ClassCastException e)
      {
         throw new DeploymentException("Expected a Queue destination-jndi-name=" + getDestination());
      }

      if (queue == null)
         queue = (Queue) createDestination(Queue.class,
                 context,
                 "queue/" + jndiSuffix,
                 jndiSuffix);
   
protected voidinnerCreateTopic(javax.naming.Context context)

      log.debug("Got destination type Topic for " + ejbName);

      // Get the JNDI suffix of the destination
      String jndiSuffix = parseJndiSuffix(getDestination(), ejbName);
      log.debug("jndiSuffix: " + jndiSuffix);

      // lookup or create the destination topic
      Topic topic = null;
      try
      {
         // First we try the specified topic
         if (getDestination() != null)
            topic = (Topic) context.lookup(getDestination());
      }
      catch (NamingException e)
      {
         log.warn("Could not find the topic destination-jndi-name=" + getDestination());
      }
      catch (ClassCastException e)
      {
         throw new DeploymentException("Expected a Topic destination-jndi-name=" + getDestination());
      }

      if (topic == null)
         topic = (Topic) createDestination(Topic.class,
                 context,
                 "topic/" + jndiSuffix,
                 jndiSuffix);
   
protected voidinnerStart()

      log.debug("Initializing");

      if (getResourceAdaptorName().equals(JMS_ADAPTOR))
         jmsCreate();
   
protected voidjmsCreate()

      //    Get the JMS provider
      // todo get rid of server module dependency
      JMSProviderAdapter adapter = getJMSProviderAdapter();
      log.debug("Provider adapter: " + adapter);
  
      // Connect to the JNDI server and get a reference to root context
      Context context = adapter.getInitialContext();
      log.debug("context: " + context);

      // if we can't get the root context then exit with an exception
      if (context == null)
      {
         throw new RuntimeException("Failed to get the root context");
      }

      // Unfortunately the destination is optional, so if we do not have one
      // here we have to look it up if we have a destinationJNDI, else give it
      // a default.
      String destinationType = getDestinationType();
      if (destinationType == null)
      {
         log.warn("No message-driven-destination given; using; guessing type");
         destinationType = getDestinationType(context, getDestination());
      }

      if ("javax.jms.Topic".equals(destinationType))
      {
         innerCreateTopic(context);

      }
      else if ("javax.jms.Queue".equals(destinationType))
      {
         innerCreateQueue(context);

      }
      else
         throw new DeploymentException("Unknown destination-type " + destinationType);

      log.debug("Initialized with config " + toString());

      context.close();
   
public java.lang.ObjectlocalInvoke(java.lang.reflect.Method method, java.lang.Object[] args)

      MethodInfo info = getMethodInfo(method);
      if (info == null)
      {
         throw new RuntimeException("Could not resolve beanClass method from proxy call: " + method.toString());
      }
      return localInvoke(info, args);

   
public java.lang.ObjectlocalInvoke(org.jboss.aop.MethodInfo info, java.lang.Object[] args)

     
      ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
      pushEnc();
      try
      {
         EJBContainerInvocation nextInvocation = new EJBContainerInvocation(info);
         nextInvocation.setAdvisor(this);
         nextInvocation.setArguments(args);
         return nextInvocation.invokeNext();
      }
      finally
      {
         Thread.currentThread().setContextClassLoader(oldLoader);
         popEnc();
      }
   
protected java.lang.StringparseJndiSuffix(java.lang.String jndiname, java.lang.String defautSuffix)
Parse the JNDI suffix from the given JNDI name.

param
jndiname The JNDI name used to lookup the destination.
param
defautSuffix Description of Parameter
return
The parsed suffix or the defaultSuffix

      // jndiSuffix is merely the name that the user has given the MDB.
      // since the jndi name contains the message type I have to split
      // at the "/" if there is no slash then I use the entire jndi name...
      String jndiSuffix = "";

      if (jndiname != null)
      {
         int indexOfSlash = jndiname.indexOf("/");
         if (indexOfSlash != -1)
         {
            jndiSuffix = jndiname.substring(indexOfSlash + 1);
         }
         else
         {
            jndiSuffix = jndiname;
         }
      }
      else
      {
         // if the jndi name from jboss.xml is null then lets use the ejbName
         jndiSuffix = defautSuffix;
      }

      return jndiSuffix;
   
protected abstract voidpopulateActivationSpec()

public voidsetMessageEndpointFactory(org.jboss.ejb3.mdb.inflow.JBossMessageEndpointFactory messageEndpointFactory)

      this.messageEndpointFactory = messageEndpointFactory;
   
public voidstart()
Initialize the container invoker. Sets up a connection, a server session pool and a connection consumer for the configured destination.

Any JMSExceptions produced while initializing will be assumed to be caused due to JMS Provider failure.

throws
Exception Failed to initalize.

      super.start();

      populateActivationSpec();
         
      innerStart();

      timerService = TimerServiceFactory.getInstance().createTimerService(this.getObjectName(), this);

      startProxies();
      
      TimerServiceFactory.getInstance().restoreTimerService(timerService);
   
protected voidstartProxies()

      messageEndpointFactory.start();
   
public voidstop()

      if (timerService != null)
      {
         TimerServiceFactory.getInstance().removeTimerService(timerService);
         timerService = null;
      }

      stopProxies();
      
      super.stop();
   
protected voidstopProxies()

      messageEndpointFactory.stop();