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 { JAXBElementxmlMsg = 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.- Spring uses JmsTemplate to send messages
- 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. -
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);
-
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(); }
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.
- When the bean is created, the JMS connection and session are created. The connection is also started.
- The conneciton will be reused by the application. When the application is shutdown, the connection will be stopped and then closed.
- org.springframework.web.context.ContextLoader calls
public void closeWebApplicationContext(ServletContext servletContext) {...}
- 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:
- MessageProducer invokes the "send(...)" method.
- The MessageProducer implementation actually has a reference to the session. So its "send" method will call "session.send(...)"
- The session implementation actually has a reference to the connection. So it calls "connection.synSendPacket(...)" or "connection.aSyncSendPacket(...)".
- 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.
- A connection holds references to all the sessions that it has created.
- A session holds references to all the consumers that it has created.
- When a connection is started, it calls the "start()" method of all its sessions.
- 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. - The "start()" method of the consumer has the following main code lines:
unconsumedMessages.start(); session.executor.wakeup();
The unconsumerdMessages is an instance of MessageDispatchChannel. - 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:- If the property "transactionManager" is set, then that transaction manager will be used. The property "sessionTransacted" will be ignored.
- 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.
- Else there is no transaction. The property "sessionAcknowledgeModeName" comes into effect.
- 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).
- 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.
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.- If a JtaTransactionManager as "transactionManager" for a fully XA-aware JMS provider, it will give full "exactly-once" guarantees without custom duplicate message checks
- 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.
- 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"
- "sessionAcknowledgeMode" set to "AUTO_ACKNOWLEDGE" (default): Automatic message acknowledgment before listener execution; no redelivery in case of exception thrown.
- "sessionAcknowledgeMode" set to "CLIENT_ACKNOWLEDGE": Automatic message acknowledgment after successful listener execution; no redelivery in case of exception thrown.
- "sessionAcknowledgeMode" set to "DUPS_OK_ACKNOWLEDGE": Lazy message acknowledgment during or after listener execution; potential redelivery in case of exception thrown.
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
- http://docs.spring.io/spring/docs/2.5.6/api/org/springframework/jms/listener/AbstractMessageListenerContainer.html
No comments:
Post a Comment