private void startBeans(boolean autoStartupOnly) { Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans(); Map<Integer, LifecycleGroup> phases = new HashMap<Integer, LifecycleGroup>(); for (Map.Entry<String, ? extends Lifecycle> entry : lifecycleBeans.entrySet()) { Lifecycle bean = entry.getValue(); if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) { int phase = getPhase(bean); LifecycleGroup group = phases.get(phase); if (group == null) { group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly); phases.put(phase, group); } group.add(entry.getKey(), bean); } } if (phases.size() > 0) { List<Integer> keys = new ArrayList<Integer>(phases.keySet()); Collections.sort(keys); for (Integer key : keys) { phases.get(key).start(); } } }
/** * Start the specified bean as part of the given set of Lifecycle beans, * making sure that any beans that it depends on are started first. * @param lifecycleBeans Map with bean name as key and Lifecycle instance as value * @param beanName the name of the bean to start */ private void doStart(Map<String, ? extends Lifecycle> lifecycleBeans, String beanName, boolean autoStartupOnly) { Lifecycle bean = lifecycleBeans.remove(beanName); if (bean != null && !this.equals(bean)) { String[] dependenciesForBean = this.beanFactory.getDependenciesForBean(beanName); for (String dependency : dependenciesForBean) { doStart(lifecycleBeans, dependency, autoStartupOnly); } if (!bean.isRunning() && (!autoStartupOnly || !(bean instanceof SmartLifecycle) || ((SmartLifecycle) bean).isAutoStartup())) { if (logger.isDebugEnabled()) { logger.debug("Starting bean '" + beanName + "' of type [" + bean.getClass() + "]"); } try { bean.start(); } catch (Throwable ex) { throw new ApplicationContextException("Failed to start bean '" + beanName + "'", ex); } if (logger.isDebugEnabled()) { logger.debug("Successfully started bean '" + beanName + "'"); } } } }
/** * Retrieve all applicable Lifecycle beans: all singletons that have already been created, * as well as all SmartLifecycle beans (even if they are marked as lazy-init). * @return the Map of applicable beans, with bean names as keys and bean instances as values */ protected Map<String, Lifecycle> getLifecycleBeans() { Map<String, Lifecycle> beans = new LinkedHashMap<String, Lifecycle>(); String[] beanNames = this.beanFactory.getBeanNamesForType(Lifecycle.class, false, false); for (String beanName : beanNames) { String beanNameToRegister = BeanFactoryUtils.transformedBeanName(beanName); boolean isFactoryBean = this.beanFactory.isFactoryBean(beanNameToRegister); String beanNameToCheck = (isFactoryBean ? BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName); if ((this.beanFactory.containsSingleton(beanNameToRegister) && (!isFactoryBean || Lifecycle.class.isAssignableFrom(this.beanFactory.getType(beanNameToCheck)))) || SmartLifecycle.class.isAssignableFrom(this.beanFactory.getType(beanNameToCheck))) { Lifecycle bean = this.beanFactory.getBean(beanNameToCheck, Lifecycle.class); if (bean != this) { beans.put(beanNameToRegister, bean); } } } return beans; }
public void stop() { if (this.members.isEmpty()) { return; } if (logger.isInfoEnabled()) { logger.info("Stopping beans in phase " + this.phase); } Collections.sort(this.members, Collections.reverseOrder()); CountDownLatch latch = new CountDownLatch(this.smartMemberCount); Set<String> countDownBeanNames = Collections.synchronizedSet(new LinkedHashSet<String>()); for (LifecycleGroupMember member : this.members) { if (this.lifecycleBeans.containsKey(member.name)) { doStop(this.lifecycleBeans, member.name, latch, countDownBeanNames); } else if (member.bean instanceof SmartLifecycle) { // already removed, must have been a dependent latch.countDown(); } } try { latch.await(this.timeout, TimeUnit.MILLISECONDS); if (latch.getCount() > 0 && !countDownBeanNames.isEmpty() && logger.isWarnEnabled()) { logger.warn("Failed to shut down " + countDownBeanNames.size() + " bean" + (countDownBeanNames.size() > 1 ? "s" : "") + " with phase value " + this.phase + " within timeout of " + this.timeout + ": " + countDownBeanNames); } } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } }
/** * For tests that assume the container manager is started. */ private void startContainerManager() { //init with no processes in cache; use mock cache to start correctly EasyMock.expect(mockProcessCache.getKeys()).andReturn(Collections.EMPTY_LIST); EasyMock.replay(mockProcessCache); ((JmsContainerManagerImpl) jmsContainerManager).init(); ((SmartLifecycle) jmsContainerManager).start(); EasyMock.reset(mockProcessCache); }
/** * Stop the specified bean as part of the given set of Lifecycle beans, * making sure that any beans that depends on it are stopped first. * @param lifecycleBeans Map with bean name as key and Lifecycle instance as value * @param beanName the name of the bean to stop */ private void doStop(Map<String, ? extends Lifecycle> lifecycleBeans, final String beanName, final CountDownLatch latch, final Set<String> countDownBeanNames) { Lifecycle bean = lifecycleBeans.remove(beanName); if (bean != null) { String[] dependentBeans = this.beanFactory.getDependentBeans(beanName); for (String dependentBean : dependentBeans) { doStop(lifecycleBeans, dependentBean, latch, countDownBeanNames); } try { if (bean.isRunning()) { if (bean instanceof SmartLifecycle) { if (logger.isDebugEnabled()) { logger.debug("Asking bean '" + beanName + "' of type [" + bean.getClass() + "] to stop"); } countDownBeanNames.add(beanName); ((SmartLifecycle) bean).stop(new Runnable() { @Override public void run() { latch.countDown(); countDownBeanNames.remove(beanName); if (logger.isDebugEnabled()) { logger.debug("Bean '" + beanName + "' completed its stop procedure"); } } }); } else { if (logger.isDebugEnabled()) { logger.debug("Stopping bean '" + beanName + "' of type [" + bean.getClass() + "]"); } bean.stop(); if (logger.isDebugEnabled()) { logger.debug("Successfully stopped bean '" + beanName + "'"); } } } else if (bean instanceof SmartLifecycle) { // don't wait for beans that aren't running latch.countDown(); } } catch (Throwable ex) { if (logger.isWarnEnabled()) { logger.warn("Failed to stop bean '" + beanName + "'", ex); } } } }
public void add(String name, Lifecycle bean) { if (bean instanceof SmartLifecycle) { this.smartMemberCount++; } this.members.add(new LifecycleGroupMember(name, bean)); }
private static int getPhase(Lifecycle lifecycle) { return (lifecycle instanceof SmartLifecycle) ? ((SmartLifecycle) lifecycle).getPhase() : 0; }
/** * Tests that all containers are subscribed at start-up to the * correct JMS queues (by sending message to expected subscribed). * @throws InterruptedException * @throws JMSException */ @Test @Ignore("This test is broken") public void testInitAtStartUp() throws InterruptedException, JMSException { ArrayList<Long> keys = new ArrayList<Long>(); keys.add(0, 1L); keys.add(1, 2L); Process mockProcess1 = EasyMock.createMock(Process.class); Process mockProcess2 = EasyMock.createMock(Process.class); EasyMock.expect(mockProcessCache.getKeys()).andReturn(keys); EasyMock.expect(mockProcessCache.get(1L)).andReturn(mockProcess1); EasyMock.expect(mockProcessCache.get(2L)).andReturn(mockProcess2); long millis = System.currentTimeMillis(); EasyMock.expect(mockProcess1.getName()).andReturn("Process-1-" + millis).times(2); EasyMock.expect(mockProcess2.getName()).andReturn("Process-2-" + millis).times(2); EasyMock.expect(mockProcess1.getId()).andReturn(1L); EasyMock.expect(mockProcess2.getId()).andReturn(2L); final CountDownLatch latch = new CountDownLatch(2); //expect one message from each mockListener.onMessage(EasyMock.isA(TextMessage.class), EasyMock.isA(Session.class)); EasyMock.expectLastCall().andAnswer(() -> { latch.countDown(); return null; }); mockListener.onMessage(EasyMock.isA(TextMessage.class), EasyMock.isA(Session.class)); EasyMock.expectLastCall().andAnswer(() -> { latch.countDown(); return null; }); //run test EasyMock.replay(mockProcessCache); EasyMock.replay(mockProcess1); EasyMock.replay(mockProcess2); EasyMock.replay(mockListener); //init subscriptions ((JmsContainerManagerImpl) jmsContainerManager).init(); ((SmartLifecycle) jmsContainerManager).start(); //check messages are picked up jmsSender.sendToQueue("test message from process 1", testTrunkName + ".Process-1-" + millis); jmsSender.sendToQueue("test message from process 2", testTrunkName + ".Process-2-" + millis); // wait for the listeners to fire latch.await(); EasyMock.verify(mockProcessCache); EasyMock.verify(mockProcess1); EasyMock.verify(mockProcess2); EasyMock.verify(mockListener); }
/** * Stop the specified bean as part of the given set of Lifecycle beans, * making sure that any beans that depends on it are stopped first. * @param lifecycleBeans Map with bean name as key and Lifecycle instance as value * @param beanName the name of the bean to stop */ private void doStop(Map<String, ? extends Lifecycle> lifecycleBeans, final String beanName, final CountDownLatch latch, final Set<String> countDownBeanNames) { Lifecycle bean = lifecycleBeans.remove(beanName); if (bean != null) { String[] dependentBeans = this.beanFactory.getDependentBeans(beanName); for (String dependentBean : dependentBeans) { doStop(lifecycleBeans, dependentBean, latch, countDownBeanNames); } try { if (bean.isRunning()) { if (bean instanceof SmartLifecycle) { if (logger.isDebugEnabled()) { logger.debug("Asking bean '" + beanName + "' of type [" + bean.getClass() + "] to stop"); } countDownBeanNames.add(beanName); ((SmartLifecycle) bean).stop(new Runnable() { public void run() { latch.countDown(); countDownBeanNames.remove(beanName); if (logger.isDebugEnabled()) { logger.debug("Bean '" + beanName + "' completed its stop procedure"); } } }); } else { if (logger.isDebugEnabled()) { logger.debug("Stopping bean '" + beanName + "' of type [" + bean.getClass() + "]"); } bean.stop(); if (logger.isDebugEnabled()) { logger.debug("Successfully stopped bean '" + beanName + "'"); } } } else if (bean instanceof SmartLifecycle) { // don't wait for beans that aren't running latch.countDown(); } } catch (Throwable ex) { if (logger.isWarnEnabled()) { logger.warn("Failed to stop bean '" + beanName + "'", ex); } } } }