From 9d998d14c98f8d5c619ac53abea1ab7759534944 Mon Sep 17 00:00:00 2001 From: "Maria Odea B. Ching" Date: Thu, 20 May 2010 13:11:51 +0000 Subject: [PATCH] [MRM-1066] Shutdown of Tomcat causes Exception when running Archiva Project submitted by Marcus Dimand o kill the executors and the archiva scheduler when context is destroyed additional changes in the patch: o removed system.out logs o moved out stopping of the task queue executors to its own method git-svn-id: https://svn.apache.org/repos/asf/archiva/branches/archiva-1.3.x@946618 13f79535-47bb-0310-9956-ffa450edef68 --- .../archiva/web/startup/ArchivaStartup.java | 117 +++++++++++++++++- 1 file changed, 111 insertions(+), 6 deletions(-) diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/ArchivaStartup.java b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/ArchivaStartup.java index df07e24bb..bca5a5fd0 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/ArchivaStartup.java +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/ArchivaStartup.java @@ -19,18 +19,27 @@ package org.apache.maven.archiva.web.startup; * under the License. */ +import java.lang.reflect.Field; + import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import org.apache.maven.archiva.common.ArchivaException; import org.apache.maven.archiva.scheduled.ArchivaTaskScheduler; +import org.apache.maven.archiva.scheduled.DefaultArchivaTaskScheduler; +import org.codehaus.plexus.personality.plexus.lifecycle.phase.StoppingException; +import org.codehaus.plexus.scheduler.DefaultScheduler; import org.codehaus.plexus.spring.PlexusToSpringUtils; +import org.codehaus.plexus.spring.PlexusWebApplicationContext; +import org.codehaus.plexus.taskqueue.Task; import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor; -import org.springframework.context.ApplicationContext; +import org.codehaus.plexus.taskqueue.execution.ThreadedTaskQueueExecutor; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; +import edu.emory.mathcs.backport.java.util.concurrent.ExecutorService; + /** * ArchivaStartup - the startup of all archiva features in a deterministic order. * @@ -39,6 +48,14 @@ import org.springframework.web.context.support.WebApplicationContextUtils; public class ArchivaStartup implements ServletContextListener { + private ThreadedTaskQueueExecutor tqeDbScanning; + + private ThreadedTaskQueueExecutor tqeRepoScanning; + + private ThreadedTaskQueueExecutor tqeIndexing; + + private ArchivaTaskScheduler taskScheduler; + public void contextInitialized( ServletContextEvent contextEvent ) { WebApplicationContext wac = @@ -48,11 +65,19 @@ public class ArchivaStartup (SecuritySynchronization) wac.getBean( PlexusToSpringUtils.buildSpringId( SecuritySynchronization.class ) ); ResolverFactoryInit resolverFactory = (ResolverFactoryInit) wac.getBean( PlexusToSpringUtils.buildSpringId( ResolverFactoryInit.class ) ); - ArchivaTaskScheduler taskScheduler = + + taskScheduler = (ArchivaTaskScheduler) wac.getBean( PlexusToSpringUtils.buildSpringId( ArchivaTaskScheduler.class ) ); - wac.getBean( PlexusToSpringUtils.buildSpringId( TaskQueueExecutor.class, "database-update" ) ); - wac.getBean( PlexusToSpringUtils.buildSpringId( TaskQueueExecutor.class, "repository-scanning" ) ); - wac.getBean( PlexusToSpringUtils.buildSpringId( TaskQueueExecutor.class, "indexing" ) ); + + tqeDbScanning = + (ThreadedTaskQueueExecutor) wac.getBean( PlexusToSpringUtils.buildSpringId( TaskQueueExecutor.class, + "database-update" ) ); + tqeRepoScanning = + (ThreadedTaskQueueExecutor) wac.getBean( PlexusToSpringUtils.buildSpringId( TaskQueueExecutor.class, + "repository-scanning" ) ); + tqeIndexing = + (ThreadedTaskQueueExecutor) wac.getBean( PlexusToSpringUtils.buildSpringId( TaskQueueExecutor.class, + "indexing" ) ); try { @@ -69,11 +94,91 @@ public class ArchivaStartup public void contextDestroyed( ServletContextEvent contextEvent ) { - ApplicationContext applicationContext = + WebApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext( contextEvent.getServletContext() ); if ( applicationContext != null && applicationContext instanceof ClassPathXmlApplicationContext ) { ( (ClassPathXmlApplicationContext) applicationContext ).close(); } + + if ( applicationContext != null && applicationContext instanceof PlexusWebApplicationContext ) + { + // stop task queue executors + stopTaskQueueExecutor( tqeDbScanning ); + stopTaskQueueExecutor( tqeRepoScanning ); + stopTaskQueueExecutor( tqeIndexing ); + + // stop the DefaultArchivaTaskScheduler and its scheduler + if ( taskScheduler != null && taskScheduler instanceof DefaultArchivaTaskScheduler ) + { + try + { + ( (DefaultArchivaTaskScheduler) taskScheduler ).stop(); + } + catch ( StoppingException e ) + { + e.printStackTrace(); + } + } + + try + { + // shutdown the scheduler, otherwise Quartz scheduler and Threads still exists + Field schedulerField = taskScheduler.getClass().getDeclaredField( "scheduler" ); + schedulerField.setAccessible( true ); + + DefaultScheduler scheduler = (DefaultScheduler) schedulerField.get( taskScheduler ); + scheduler.stop(); + } + catch ( Exception e ) + { + e.printStackTrace(); + } + + // close the application context + ( (PlexusWebApplicationContext) applicationContext ).close(); + } + } + + private void stopTaskQueueExecutor( ThreadedTaskQueueExecutor taskQueueExecutor ) + { + if ( taskQueueExecutor != null ) + { + Task currentTask = taskQueueExecutor.getCurrentTask(); + if ( currentTask != null ) + { + taskQueueExecutor.cancelTask( currentTask ); + } + + try + { + taskQueueExecutor.stop(); + ExecutorService service = getExecutorServiceForTTQE( taskQueueExecutor ); + if ( service != null ) + { + service.shutdown(); + } + } + catch ( Exception e ) + { + e.printStackTrace(); + } + } + } + + private ExecutorService getExecutorServiceForTTQE( ThreadedTaskQueueExecutor ttqe ) + { + ExecutorService service = null; + try + { + Field executorServiceField = ttqe.getClass().getDeclaredField( "executorService" ); + executorServiceField.setAccessible( true ); + service = (ExecutorService) executorServiceField.get( ttqe ); + } + catch ( Exception e ) + { + e.printStackTrace(); + } + return service; } } -- 2.39.5