You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@archiva.apache.org by oc...@apache.org on 2010/05/20 15:11:52 UTC

svn commit: r946618 - /archiva/branches/archiva-1.3.x/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/ArchivaStartup.java

Author: oching
Date: Thu May 20 13:11:51 2010
New Revision: 946618

URL: http://svn.apache.org/viewvc?rev=946618&view=rev
Log:
[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

Modified:
    archiva/branches/archiva-1.3.x/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/ArchivaStartup.java

Modified: archiva/branches/archiva-1.3.x/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/ArchivaStartup.java
URL: http://svn.apache.org/viewvc/archiva/branches/archiva-1.3.x/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/ArchivaStartup.java?rev=946618&r1=946617&r2=946618&view=diff
==============================================================================
--- archiva/branches/archiva-1.3.x/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/ArchivaStartup.java (original)
+++ archiva/branches/archiva-1.3.x/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/ArchivaStartup.java Thu May 20 13:11:51 2010
@@ -19,18 +19,27 @@ package org.apache.maven.archiva.web.sta
  * 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.s
 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;
     }
 }



Re: svn commit: r946618 - /archiva/branches/archiva-1.3.x/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/ArchivaStartup.java

Posted by Brett Porter <br...@apache.org>.
On 09/06/2010, at 11:59 AM, Deng Ching wrote:

> On Wed, Jun 9, 2010 at 6:07 AM, Brett Porter <br...@apache.org> wrote:
> 
>> A couple of questions:
>> - do we need to explicitly call all the stop() methods given that the
>> close() is now there? I thought that would stop all stoppables
>> 
> 
> That's what I thought too, but unfortunately, it doesn't. The running tasks
> were still executing as well as the schedulers even when Tomcat was
> shutdown. Before the stop() methods were added, when I ran "ps aux" after
> shutting down Tomcat, the process would keep on running until you force kill
> it.
> 
> 
>> - can the e.printStackTrace be changed to something else?
>> 
> 
> I'm not sure what else we can change it to? Log the exception instead?

true, while we could use a logger it's probably irrelevant at that point.

> 
> 
>> 
>> Also, the code can be a bit cleaner if the fields are assigned the required
>> values from the start :) Maybe they could just be pushed into a list of
>> Stoppables that need to be stopped.
>> 
> 
> Ok, I'll fix this up :)
> 
> Thanks,
> Deng

--
Brett Porter
brett@apache.org
http://brettporter.wordpress.com/





Re: svn commit: r946618 - /archiva/branches/archiva-1.3.x/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/ArchivaStartup.java

Posted by Deng Ching <od...@gmail.com>.
On Wed, Jun 9, 2010 at 6:07 AM, Brett Porter <br...@apache.org> wrote:

> A couple of questions:
> - do we need to explicitly call all the stop() methods given that the
> close() is now there? I thought that would stop all stoppables
>

That's what I thought too, but unfortunately, it doesn't. The running tasks
were still executing as well as the schedulers even when Tomcat was
shutdown. Before the stop() methods were added, when I ran "ps aux" after
shutting down Tomcat, the process would keep on running until you force kill
it.


> - can the e.printStackTrace be changed to something else?
>

I'm not sure what else we can change it to? Log the exception instead?


>
> Also, the code can be a bit cleaner if the fields are assigned the required
> values from the start :) Maybe they could just be pushed into a list of
> Stoppables that need to be stopped.
>

Ok, I'll fix this up :)

Thanks,
Deng

Re: svn commit: r946618 - /archiva/branches/archiva-1.3.x/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/ArchivaStartup.java

Posted by Brett Porter <br...@apache.org>.
A couple of questions:
- do we need to explicitly call all the stop() methods given that the close() is now there? I thought that would stop all stoppables
- can the e.printStackTrace be changed to something else?

Also, the code can be a bit cleaner if the fields are assigned the required values from the start :) Maybe they could just be pushed into a list of Stoppables that need to be stopped.

- Brett

On 20/05/2010, at 11:11 PM, oching@apache.org wrote:

> Author: oching
> Date: Thu May 20 13:11:51 2010
> New Revision: 946618
> 
> URL: http://svn.apache.org/viewvc?rev=946618&view=rev
> Log:
> [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
> 
> Modified:
>    archiva/branches/archiva-1.3.x/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/ArchivaStartup.java
> 
> Modified: archiva/branches/archiva-1.3.x/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/ArchivaStartup.java
> URL: http://svn.apache.org/viewvc/archiva/branches/archiva-1.3.x/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/ArchivaStartup.java?rev=946618&r1=946617&r2=946618&view=diff
> ==============================================================================
> --- archiva/branches/archiva-1.3.x/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/ArchivaStartup.java (original)
> +++ archiva/branches/archiva-1.3.x/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/ArchivaStartup.java Thu May 20 13:11:51 2010
> @@ -19,18 +19,27 @@ package org.apache.maven.archiva.web.sta
>  * 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.s
> 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;
>     }
> }
> 
> 

--
Brett Porter
brett@apache.org
http://brettporter.wordpress.com/