Tuesday, September 10, 2013

Spring JMS

The General Spring Bean Life Cycle in a Web Application

The java web application provides a plugin point in the web.xml for the user to supply his own context. It is the <listener> tag where a user can put his own class that implements the interface javax.servlet.ServletContextListener. The implementation in Spring is the ContextLoaderListener class. And the user can pass additional parameter values to his listener using the <context-param> tag. The following is an example:

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
            classpath:com/xyz/dao/applicationContext-dao.xml    
            classpath:com/xyz/jms/applicationContext-jms.xml    
  </param-value>
 </context-param>

 <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>

Bean Creation

The ContextLoaderListener uses org.springframework.web.context.ContexLoader by default to perform the actual initialization work for the root application context.

ContextLoaderListener implements the following API method from the interface ServletContextListener. And this method will create the Spring beans when the web application is started.

public void contextInitialized(ServletContextEvent event) {
  this.contextLoader = createContextLoader();
  this.contextLoader.initWebApplicationContext(event.getServletContext());
 }
The following is the code of the method initWebApplicationContext of the class ContextLoader:
public WebApplicationContext initWebApplicationContext(ServletContext servletContext)
   throws IllegalStateException, BeansException {

  if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
   throw new IllegalStateException(
     "Cannot initialize context because there is already a root application context present - " +
     "check whether you have multiple ContextLoader* definitions in your web.xml!");
  }
                 ......
   // Determine parent for root web application context, if any.
   ApplicationContext parent = loadParentContext(servletContext);

   // Store context in local instance variable, to guarantee that
   // it is available on ServletContext shutdown.
   this.context = createWebApplicationContext(servletContext, parent);
   servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
   currentContextPerThread.put(Thread.currentThread().getContextClassLoader(), this.context);
                ......
   return this.context;
  
 }
You can see that Spring creates its own context and stores it in the standard servletContext object. This way it can be retrieved in other code from the servletContext. The code first has a call to loadParentContext. This is useful if the web module WAR is part of an EAR application. The following is the javadoc from Spring for this method:

The main reason to load a parent context here is to allow multiple root web application contexts to all be children of a shared EAR context, or alternately to also share the same parent context that is visible to EJBs. For pure web applications, there is usually no need to worry about having a parent context to the root web application context.

The following code shows how to get the Spring bean from the bean ID using the context:

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

public static Object getBean(String beanId) {
  
  FacesContext facesContext = FacesContext.getCurrentInstance();
  ServletContext servletContext = (ServletContext) facesContext
    .getExternalContext().getContext();
  WebApplicationContext webApplicationContext = WebApplicationContextUtils
    .getWebApplicationContext(servletContext);
  return webApplicationContext.getBean(beanId);
 }
The above method is used in JSF(Java Server Faces), hence the FacesContext. If you are not in JSF, you can also do similar thing as long as you have the servletConext object. Basically it will use the same attribute WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE to get the context from the servletContext. The actual code of the method getWebApplicationContext is below:
public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
  return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
 }

The Spring beans are defined in xml files. How are these bean names because the actual java class objects? Spring uses the class loaders that can be got by calling Thread.currentThread().getContextClassLoader() or class.getClassLoader() to load the classes.

The Spring beans are usually singletons. For different HTTP requests from the web clients, different threads are used to serve the requests. But the beans used in these threads are the same. In Weblogic, you may see sometimes that the threads to serve the clients are also same. I think that is because Weblogic maintains a thread pool. So the same thread may be used for two different requests.

Bean Termination

ContextLoaderListener implements the following API method from the interface ServletContextListener. And this method will destroy the Spring beans when the web application is shutdown.

public void contextDestroyed(ServletContextEvent event) {
  if (this.contextLoader != null) {
   this.contextLoader.closeWebApplicationContext(event.getServletContext());
  }
 }
The following is the actual stack when I redeploy a web application to the weblogic server. You can see the call stack to create beans.
   DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 222 
   DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class, Object[], boolean) line: 261 
   DefaultListableBeanFactory(AbstractBeanFactory).getBean(String, Class, Object[]) line: 185 
   DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 164 
   DefaultListableBeanFactory.preInstantiateSingletons() line: 429 
   XmlWebApplicationContext(AbstractApplicationContext).finishBeanFactoryInitialization(ConfigurableListableBeanFactory) line: 728 
   XmlWebApplicationContext(AbstractApplicationContext).refresh() line: 380 
   ContextLoader.createWebApplicationContext(ServletContext, ApplicationContext) line: 255 
   ContextLoader.initWebApplicationContext(ServletContext) line: 199 
   ContextLoaderListener.contextInitialized(ServletContextEvent) line: 45 
   EventsManager$FireContextListenerAction.run() line: 481 
   AuthenticatedSubject.doAs(AbstractSubject, PrivilegedAction) line: 321 
   SecurityManager.runAs(AuthenticatedSubject, AuthenticatedSubject, PrivilegedAction) line: 121 
   EventsManager.notifyContextCreatedEvent() line: 181 
   WebAppServletContext.preloadResources() line: 1801 
   WebAppServletContext.start() line: 3045 
   WebAppModule.startContexts() line: 1397 
   WebAppModule.start() line: 460 

JMS Sender

Send XML message using JAXB marshalling with XML schema validation

The following is the sample code to use the Spring JmsTemplate class to send the XML message. The XML message is created by marshalling a java Foo ojbect. The class Foo is a generated class from JAXB using the XSD file "your.xsd". The marshaller loads the XSD file so it will validate the XML content. If the java foo object does not create a valid message, the method "marshaller.marshal(xmlMsg, sw)" will throw exception. For example, if a field is required in the XSD file your.xsd, and the foo ojbect has null value for that field, then a SAXParseException will be thrown. The file schemas/your.xsd must be put on the classpath.

Also note that in this example, the JMS message type is BytesMessage. It also creates properties in the JMS message.

import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;

public void sendMessage(final String message, final Map properties) {
  jmsTemplate.send(new MessageCreator() {
   @Override
   public Message createMessage(Session session) throws JMSException {
    BytesMessage bytesMsg = session.createBytesMessage();
    bytesMsg.writeBytes(message.getBytes());
    if (properties != null && !properties.isEmpty()) {
     Iterator it = properties.entrySet().iterator();
     while (it.hasNext()) {
      Map.Entry entry = (Map.Entry) it.next();
      String key = (String) entry.getKey();
      String val = (String) entry.getValue();
      bytesMsg.setStringProperty(key, val);
     }
    }
    return bytesMsg;
   }
  });
 }

 public void sendMessage(Foo fooObj, final Map properties)
   throws JAXBException {
  try {
   String message = marshall(fooObj);
   this.sendMessage(message, properties);
  } catch (SAXException e) {
   throw new JAXBException(e);
  }
 }

 private String marshall(Foo fooObj) throws JAXBException,
   SAXException {
  JAXBElement xmlMsg = new com.example.schema.ObjectFactory()
    .createXYZ(fooObj);
  JAXBContext jaxbContext = JAXBContext.newInstance(Foo.class);
  Marshaller marshaller = jaxbContext.createMarshaller();
  SchemaFactory schemaFactory = SchemaFactory
    .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
  URL xsdUrl = getClass().getClassLoader().getResource(
    "schemas/your.xsd");
  Schema schema = schemaFactory.newSchema(xsdUrl);
  marshaller.setSchema(schema);
  StringWriter sw = new StringWriter();
  marshaller.marshal(xmlMsg, sw);
  return sw.toString();
 }

The Life Cycle of JMS Connection and Session

The following is a case study. The version Spring 2.5.6 is used. In the actual application code,the operations are put into a JTA transaction. The analysis below is to show how the JMS connection and session are created and closed.
  1. Spring uses JmsTemplate to send messages
  2. JmsTemplate uses the following method to actually send the message:
        public Object execute(SessionCallback action, boolean startConnection) throws JmsException {
         ...
          
         Session sessionToUse = ConnectionFactoryUtils.doGetTransactionalSession(
             getConnectionFactory(), this.transactionalResourceFactory, startConnection);
         ...
         return action.doInJms(sessionToUse);
            ...  
    
         finally {
           JmsUtils.closeSession(sessionToClose);
           ConnectionFactoryUtils.releaseConnection(conToClose, getConnectionFactory(), startConnection);
         }
       }
     
    Notes:
    (1) The "finally" block closes sessionToClose and conToClose. These are not the same as sessionToUse and its connection. When sessionToUse is not null, sessionToClose and conToClose are not created, and the "finally" block will do nothing when they are null.
    (2) I did not find a call to connection.start(). I did a separate test and it showed that the message can still be sent if start() is not invoked. But for a JMS consumer, this has to be called. Otherwise, no message will be received.
  3. The call ConnectionFactoryUtils.doGetTransactionalSession(...) creates the connection and the session. And the connection is saved into a new JmsResourceHolder() which is bound to TransactionSynchronizationManager in the following code in that method:
       TransactionSynchronizationManager.bindResource(connectionFactory, resourceHolderToUse);
     
  4. At the end of the operations, TransactionSynchronizationManager calls the following method:
          public static Object unbindResource(Object key) 
          
    Eventually the following code of class JmsResourceHolder is called:
        public void closeAll() {
          for (Iterator it = this.sessions.iterator(); it.hasNext();) {
           try {
            ((Session) it.next()).close();
           }
           catch (Throwable ex) {
            logger.debug("Could not close synchronized JMS Session after transaction", ex);
           }
          }
          for (Iterator it = this.connections.iterator(); it.hasNext();) {
           Connection con = (Connection) it.next();
           ConnectionFactoryUtils.releaseConnection(con, this.connectionFactory, true);
          }
          this.connections.clear();
          this.sessions.clear();
          this.sessionsPerConnection.clear();
     }
        
Question: What if the connection returned from the ConnectionFactory is a pooled connection? Obviously it should not be closed at the end. How does Spring know it is pooled and not close it?

One implementation I saw that solve the question above is the following. The code ConnectionFactoryUtils.releaseConnection(con, this.connectionFactory, true); will call con.close();. But the trick is in the method close(). The connection is a customer-implemented class. Its "close" method actually does not close it in all circumstances. The connection class itself has a reference to the connection factory. It will first check if connection pooling is enabled. If yes, it will just tell the factory to update the status for this connection, and that is it. Only if the pooling is not enabled, will the connection actually close itself.

Spring also has its own JMS connection pool implementation. One of them is the SingleConnectionFactory. It uses the similar way as the one mentioned above to avoid the connection being closed. It will return a connection proxy that will essentially do nothing in the "close()" method. The following is the actual code:

/**
  * Wrap the given Connection with a proxy that delegates every method call to it
  * but suppresses close calls. This is useful for allowing application code to
  * handle a special framework Connection just like an ordinary Connection from a
  * JMS ConnectionFactory.
  * @param target the original Connection to wrap
  * @return the wrapped Connection
  */
 protected Connection getSharedConnectionProxy(Connection target) {
  List classes = new ArrayList(3);
  classes.add(Connection.class);
  if (target instanceof QueueConnection) {
   classes.add(QueueConnection.class);
  }
  if (target instanceof TopicConnection) {
   classes.add(TopicConnection.class);
  }
  return (Connection) Proxy.newProxyInstance(
    Connection.class.getClassLoader(),
    (Class[]) classes.toArray(new Class[classes.size()]),
    new SharedConnectionInvocationHandler(target));
 }
The following javadoc of the class org.springframework.jms.connection.SingleConnectionFactory is also quite helfpful.
A JMS ConnectionFactory adapter that returns the same Connection from all 
createConnection() calls, and ignores calls to Connection.close(). According to the
 JMS Connection model, this is perfectly thread-safe (in contrast to e.g. JDBC). The 
shared Connection can be automatically recovered in case of an Exception. 

You can either pass in a specific JMS Connection directly or let this factory lazily 
create a Connection via a given target ConnectionFactory. This factory generally works
 with JMS 1.1 as well as the JMS 1.0.2 API. 

...

Useful for testing and standalone environments in order to keep using the same 
Connection for multiple JmsTemplate calls, without having a pooling ConnectionFactory
 underneath. This may span any number of transactions, even concurrently executing 
transactions. 

Note that Spring's message listener containers support the use of a shared Connection
 within each listener container instance. Using SingleConnectionFactory in combination
 only really makes sense for sharing a single JMS Connection across multiple listener
 containers. 

So the answer to the original question may be the following. Spring actually does not detect if a connection returned from a connection factory is pooled or not. It just calls its "close" method. It lets the connection class itself to decide whether or not to close the actual connection.

JMS Consumer

The Life Cycle of JMS Connection and Session

Spring uses DefaultMessageListenerContainer to receiver messages. An example is as follows:
<bean id="jmsContainer"
  class="org.springframework.jms.listener.DefaultMessageListenerContainer">
  <property name="connectionFactory" ref="jmsDestConnectionFactory" />
  <property name="destination" ref="myDestination" />
  <property name="sessionAcknowledgeModeName" value="AUTO_ACKNOWLEDGE" />
  <property name="messageListener" ref="messageListener" />
  <property name="sessionTransacted" value="true" />
  <property name="concurrentConsumers" value="1"></property>
 </bean>
The main steps are the following.
  1. When the bean is created, the JMS connection and session are created. The connection is also started.
  2. The conneciton will be reused by the application. When the application is shutdown, the connection will be stopped and then closed.
The following are the main steps that the JMS connection is closed.
  1. org.springframework.web.context.ContextLoader calls
        public void closeWebApplicationContext(ServletContext servletContext) {...}
    
  2. The method above will call
     protected void doClose() {
          ...
           Map lifecycleBeans = getLifecycleBeans();
           for (Iterator it = new LinkedHashSet(lifecycleBeans.keySet()).iterator(); it.hasNext();) {
            String beanName = (String) it.next();
            doStop(lifecycleBeans, beanName);
           }
           // Destroy all cached singletons in the context's BeanFactory.
           destroyBeans();
           // Close the state of this context itself.
           closeBeanFactory();
           onClose();
           synchronized (this.activeMonitor) {
            this.active = false;
           }
          }
     }
    
    In the above code, the "doStop()" method will stop the connection, and the "destoryBeans()" will close the connection

What Happens Internally in JMS Connection and Session?

So how are the messages actually sent over the network? We have to use open source code to get some idea. I looked at ActiveMQ, which is a popular open source JMS implementation. The basic steps to send a message are as follows:

  1. MessageProducer invokes the "send(...)" method.
  2. The MessageProducer implementation actually has a reference to the session. So its "send" method will call "session.send(...)"
  3. The session implementation actually has a reference to the connection. So it calls "connection.synSendPacket(...)" or "connection.aSyncSendPacket(...)".
  4. The connection object will delegate the task to some transport layer object to actually send the message. And eventually I saw in a place that it uses ObjectOutputStream to send out the message.
Other observations on ActiveMQ.
  1. A connection holds references to all the sessions that it has created.
  2. A session holds references to all the consumers that it has created.
  3. When a connection is started, it calls the "start()" method of all its sessions.
  4. When a session is started, it calls the "start()" method of all its consumers. Also it calls "executor.start()". The executor is of class ActiveMQSessionExecutor. Its "start()" method has the following main code line:
       messageQueue.start();
    
    The messageQueue here is of class MessageDispatchChannel.
  5. The "start()" method of the consumer has the following main code lines:
          unconsumedMessages.start();
          session.executor.wakeup();
    
    The unconsumerdMessages is an instance of MessageDispatchChannel.
  6. The MessageDispatchChannel interface has the "enqueue" and "dequeue" methods. One implementation of this interface has a list of MessageDispatch, which has an instance variable of Message. So this list can be used to store and send messages. But there must be other ways such as using files or a database to store the messages. I am not clear here.

Transaction for Spring JMS consumer

The general JMS API specifies that when you create a session, you specify whether it is transacted. The first argument to the createSession method is a boolean value. A value of true means that the session is transacted; a value of false means that it is not transacted. The second argument to this method is the acknowledge mode, which is relevant only to nontransacted sessions. If the session is transacted, the second argument is ignored.

The commit and the rollback methods for local transactions are associated with the session.

In an Enterprise JavaBeans component, you cannot use the Session.commit and Session.rollback methods. Instead, you use distributed transactions.

Now for Spring class org.springframework.jms.listener.DefaultMessageListenerContainer, it has the properties transactionManager, sessionAcknowledgeModeName and sessionTransacted. The logic about how these properties are used are the following:

  1. If the property "transactionManager" is set, then that transaction manager will be used. The property "sessionTransacted" will be ignored.
  2. Else if "sessionTransacted" is set to "true", local transaction will be used. And the property "sessionAcknowledgeModeName" will be ignored. Programs need to use session.commit or session.rollback to manage the transaction.
  3. Else there is no transaction. The property "sessionAcknowledgeModeName" comes into effect.
The javadoc[1] of Spring recommends the following:
  1. The general recommendation is to set "sessionTransacted" to "true", typically in combination with local database transactions triggered by the listener implementation, through Spring's standard transaction facilities. This will work nicely in Tomcat or in a standalone environment, often combined with custom duplicate message detection (if it is unacceptable to ever process the same message twice).
  2. Alternatively, specify a JtaTransactionManager as "transactionManager" for a fully XA-aware JMS provider - typically when running on a J2EE server, but also for other environments with a JTA transaction manager present. This will give full "exactly-once" guarantees without custom duplicate message checks, at the price of additional runtime processing overhead.

    Note that it is also possible to specify a JmsTransactionManager as external "transactionManager", providing fully synchronized Spring transactions based on local JMS transactions. The effect is similar to "sessionTransacted" set to "true", the difference being that this external transaction management will also affect independent JMS access code within the service layer (e.g. based on JmsTemplate or TransactionAwareConnectionFactoryProxy), not just direct JMS Session usage in a SessionAwareMessageListener.

Note from [1] about how the exception is handled for the class AbstractMessageListenerContainer, which is an upper class of DefaultMessageListenerContainer: "NOTE: The default behavior of this message listener container is to never propagate an exception thrown by a message listener up to the JMS provider. Instead, it will log any such exception at the error level. This means that from the perspective of the attendant JMS provider no such listener will ever fail."

The Duplicate Messages Issue

Again from [1], I think the following is true for the DefaultMessageListenerContainer. Note that cases #4, #5 and #6 are only effective when no transaction manager or local transaction is used. If a transactionManager is set or the sessionTransacted is set to "true", the AcknowledgeMode will be ignored.
  1. If a JtaTransactionManager as "transactionManager" for a fully XA-aware JMS provider, it will give full "exactly-once" guarantees without custom duplicate message checks
  2. To specify a JmsTransactionManager as external "transactionManager". The javadoc does not explicitly say if there will be duplicate messages. But it says this case is similar to "sessionTransacted" set to "true", in which case the duplicate messaegs are possible.
  3. To set "sessionTransacted" to "true". In this case, the duplicate messages are possible because the javadoc there says this case is "often combined with custom duplicate message detection"
  4. "sessionAcknowledgeMode" set to "AUTO_ACKNOWLEDGE" (default): Automatic message acknowledgment before listener execution; no redelivery in case of exception thrown.
  5. "sessionAcknowledgeMode" set to "CLIENT_ACKNOWLEDGE": Automatic message acknowledgment after successful listener execution; no redelivery in case of exception thrown.
  6. "sessionAcknowledgeMode" set to "DUPS_OK_ACKNOWLEDGE": Lazy message acknowledgment during or after listener execution; potential redelivery in case of exception thrown.
Also note that the javadoc has the following regarding the above acknowledge modes: "The exact behavior might vary according to the concrete listener container and JMS provider used."

Appendix

To see more about the steps of how a Spring bean is created, the following complete stack trace is helpful. The stack is obtained by putting a break point in the code and redeploying the web application to the weblogic server that is started in debug mode.
Oracle WebLogic Server 11gR1 PatchSet 1 at localhost [Oracle WebLogic Launch Configuration] 
 Java HotSpot(TM) Client VM[localhost:8453] 
  Daemon Thread [DynamicListenThread[Default]] (Running) 
  Daemon Thread [DynamicListenThread[Default[2]]] (Running) 
  Daemon Thread [DynamicListenThread[Default[3]]] (Running) 
  Daemon Thread [DynamicListenThread[Default[1]]] (Running) 
  Daemon Thread [[STANDBY] ExecuteThread: '4' for queue: 'weblogic.kernel.Default (self-tuning)'] (Running) 
  Daemon Thread [weblogic.GCMonitor] (Running) 
  Daemon Thread [TIBCO EMS TCPLink Reader (Server-47729)] (Running) 
  Daemon Thread [TIBCO EMS Connections Pinger] (Running) 
  Daemon Thread [Timer-2] (Suspended (exception NoClassDefFoundError)) 
   TimerThread.run() line: 468 
  Daemon Thread [FooJMSStarvedConsumerTimer] (Running) 
  Daemon Thread [[ACTIVE] ExecuteThread: '3' for queue: 'weblogic.kernel.Default (self-tuning)'] (Running) 
  Daemon Thread [Monitor Runner] (Running) 
  Daemon Thread [Session Monitor] (Running) 
  Daemon Thread [Session Monitor] (Running) 
  Daemon Thread [[STANDBY] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'] (Suspended (breakpoint at line 37 in SampleProducer)) 
   SampleProducer.setJmsTemplate(JmsTemplate) line: 37 
   NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] 
   NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39 
   DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25 
   Method.invoke(Object, Object...) line: 597 
   BeanWrapperImpl.setPropertyValue(BeanWrapperImpl$PropertyTokenHolder, PropertyValue) line: 840 
   BeanWrapperImpl.setPropertyValue(PropertyValue) line: 651 
   BeanWrapperImpl(AbstractPropertyAccessor).setPropertyValues(PropertyValues, boolean, boolean) line: 78 
   BeanWrapperImpl(AbstractPropertyAccessor).setPropertyValues(PropertyValues) line: 59 
   DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).applyPropertyValues(String, BeanDefinition, BeanWrapper, PropertyValues) line: 1276 
   DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).populateBean(String, AbstractBeanDefinition, BeanWrapper) line: 1010 
   DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 472 
   AbstractAutowireCapableBeanFactory$1.run() line: 409 
   AccessController.doPrivileged(PrivilegedAction, AccessControlContext) line: not available [native method] 
   DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 380 
   AbstractBeanFactory$1.getObject() line: 264 
   DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 222 
   DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class, Object[], boolean) line: 261 
   DefaultListableBeanFactory(AbstractBeanFactory).getBean(String, Class, Object[]) line: 185 
   DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 164 
   DefaultListableBeanFactory.findAutowireCandidates(String, Class, DependencyDescriptor) line: 671 
   DefaultListableBeanFactory.resolveDependency(DependencyDescriptor, String, Set, TypeConverter) line: 610 
   AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(Object, String, PropertyValues) line: 499 
   InjectionMetadata.injectMethods(Object, String, PropertyValues) line: 117 
   AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(PropertyValues, PropertyDescriptor[], Object, String) line: 253 
   DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).populateBean(String, AbstractBeanDefinition, BeanWrapper) line: 998 
   DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 472 
   AbstractAutowireCapableBeanFactory$1.run() line: 409 
   AccessController.doPrivileged(PrivilegedAction, AccessControlContext) line: not available [native method] 
   DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 380 
   AbstractBeanFactory$1.getObject() line: 264 
   DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory) line: 222 
   DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class, Object[], boolean) line: 261 
   DefaultListableBeanFactory(AbstractBeanFactory).getBean(String, Class, Object[]) line: 185 
   DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 164 
   DefaultListableBeanFactory.preInstantiateSingletons() line: 429 
   XmlWebApplicationContext(AbstractApplicationContext).finishBeanFactoryInitialization(ConfigurableListableBeanFactory) line: 728 
   XmlWebApplicationContext(AbstractApplicationContext).refresh() line: 380 
   ContextLoader.createWebApplicationContext(ServletContext, ApplicationContext) line: 255 
   ContextLoader.initWebApplicationContext(ServletContext) line: 199 
   ContextLoaderListener.contextInitialized(ServletContextEvent) line: 45 
   EventsManager$FireContextListenerAction.run() line: 481 
   AuthenticatedSubject.doAs(AbstractSubject, PrivilegedAction) line: 321 
   SecurityManager.runAs(AuthenticatedSubject, AuthenticatedSubject, PrivilegedAction) line: 121 
   EventsManager.notifyContextCreatedEvent() line: 181 
   WebAppServletContext.preloadResources() line: 1801 
   WebAppServletContext.start() line: 3045 
   WebAppModule.startContexts() line: 1397 
   WebAppModule.start() line: 460 
   ModuleStateDriver$3.next(Object) line: 425 
   StateMachineDriver.nextState(StateChange, Object[]) line: 83 
   ModuleStateDriver.start(Module[]) line: 119 
   ScopedModuleDriver.start() line: 200 
   ModuleListenerInvoker.start() line: 247 
   ModuleStateDriver$3.next(Object) line: 425 
   StateMachineDriver.nextState(StateChange, Object[]) line: 83 
   ModuleStateDriver.start(Module[]) line: 119 
   StartModulesFlow.activate() line: 27 
   BaseDeployment$2.next(Object) line: 1267 
   StateMachineDriver.nextState(StateChange, Object[]) line: 83 
   WarDeployment(BaseDeployment).activate(DeploymentContext) line: 409 
   WarDeployment(SingleModuleDeployment).activate(DeploymentContext) line: 39 
   DeploymentStateChecker.activate(DeploymentContext) line: 161 
   AppContainerInvoker.activate(DeploymentContext) line: 79 
   RedeployOperation(AbstractOperation).activate(Deployment) line: 569 
   RedeployOperation(ActivateOperation).activateDeployment() line: 150 
   RedeployOperation(ActivateOperation).doCommit() line: 116 
   RedeployOperation(AbstractOperation).commit() line: 323 
   DeploymentManager.handleDeploymentCommit(Deployment, AbstractOperation) line: 844 
   DeploymentManager.activateDeploymentList(ArrayList, DeploymentManager$DeploymentRequestInfo) line: 1253 
   DeploymentManager.handleCommit(DeploymentContext) line: 440 
   DeploymentServiceDispatcher.commit(DeploymentContext) line: 163 
   DeploymentReceiverCallbackDeliverer.doCommitCallback(DeploymentContext) line: 181 
   DeploymentReceiverCallbackDeliverer.access$100(DeploymentReceiverCallbackDeliverer, DeploymentContext) line: 12 
   DeploymentReceiverCallbackDeliverer$2.run() line: 67 
   SelfTuningWorkManagerImpl$WorkAdapterImpl.run() line: 516 
   ExecuteThread.execute(Runnable) line: 201 
   ExecuteThread.run() line: 173 
  Daemon Thread [AS400 Read Daemon [system:pitt2;job:114314/QUSER/QZDASOINIT]] (Running) 
  Daemon Thread [AS400 Read Daemon [system:tst1;job:113896/QUSER/QZDASOINIT]] (Running) 
  Daemon Thread [Thread-11] (Running) 
  Daemon Thread [DoSManager] (Running) 
  Daemon Thread [VDE Transaction Processor Thread] (Running) 
  Daemon Thread [ExecuteThread: '3' for queue: 'weblogic.socket.Muxer'] (Running) 
  Daemon Thread [ExecuteThread: '2' for queue: 'weblogic.socket.Muxer'] (Running) 
  Daemon Thread [ExecuteThread: '1' for queue: 'weblogic.socket.Muxer'] (Running) 
  Daemon Thread [ExecuteThread: '0' for queue: 'weblogic.socket.Muxer'] (Running) 
  Daemon Thread [Thread-7] (Running) 
  Daemon Thread [[ACTIVE] ExecuteThread: '1' for queue: 'weblogic.kernel.Default (self-tuning)'] (Running) 
  Daemon Thread [weblogic.timers.TimerThread] (Running) 
  Daemon Thread [weblogic.time.TimeEventGenerator] (Running) 
  Daemon Thread [[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'] (Running) 
  Daemon Thread [Timer-1] (Running) 
  Daemon Thread [Timer-0] (Running) 
  Thread [main] (Running) 
  Daemon Thread [FooJMSStarvedConsumerTimer] (Running) 
 Weblogic Server 
new hap-ws LDEV [Maven Build] 
 C:\bea1032\jdk160_14_R27.6.5-32\bin\javaw.exe (Sep 10, 2013 4:59:32 PM) 

References

  1. http://docs.spring.io/spring/docs/2.5.6/api/org/springframework/jms/listener/AbstractMessageListenerContainer.html

No comments:

Post a Comment