diff --git a/core-client/src/main/java/org/glassfish/jersey/client/ClientExecutorProvidersConfigurator.java b/core-client/src/main/java/org/glassfish/jersey/client/ClientExecutorProvidersConfigurator.java index 220f4f790e..df26b22587 100644 --- a/core-client/src/main/java/org/glassfish/jersey/client/ClientExecutorProvidersConfigurator.java +++ b/core-client/src/main/java/org/glassfish/jersey/client/ClientExecutorProvidersConfigurator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -65,7 +65,6 @@ class ClientExecutorProvidersConfigurator extends AbstractExecutorProvidersConfi @Override public void init(InjectionManager injectionManager, BootstrapBag bootstrapBag) { Map runtimeProperties = bootstrapBag.getConfiguration().getProperties(); - ManagedObjectsFinalizer finalizer = bootstrapBag.getManagedObjectsFinalizer(); ExecutorServiceProvider defaultAsyncExecutorProvider; ScheduledExecutorServiceProvider defaultScheduledExecutorProvider; @@ -110,7 +109,6 @@ public void init(InjectionManager injectionManager, BootstrapBag bootstrapBag) { .to(ExecutorServiceProvider.class); injectionManager.register(executorBinding); - finalizer.registerForPreDestroyCall(defaultAsyncExecutorProvider); final ScheduledExecutorService clientScheduledExecutorService = client.getScheduledExecutorService() == null // scheduled executor service set from {@link ClientConfig}. @@ -134,9 +132,9 @@ public void init(InjectionManager injectionManager, BootstrapBag bootstrapBag) { .service(defaultScheduledExecutorProvider) .to(ScheduledExecutorServiceProvider.class); injectionManager.register(schedulerBinding); - finalizer.registerForPreDestroyCall(defaultScheduledExecutorProvider); - registerExecutors(injectionManager, componentBag, defaultAsyncExecutorProvider, defaultScheduledExecutorProvider); + registerExecutors(injectionManager, componentBag, defaultAsyncExecutorProvider, + defaultScheduledExecutorProvider, bootstrapBag.getManagedObjectsFinalizer()); } private static ExecutorService lookupManagedExecutorService() { diff --git a/core-common/src/main/java/org/glassfish/jersey/process/internal/AbstractExecutorProvidersConfigurator.java b/core-common/src/main/java/org/glassfish/jersey/process/internal/AbstractExecutorProvidersConfigurator.java index 7ad252ed6e..2a9c8b4195 100644 --- a/core-common/src/main/java/org/glassfish/jersey/process/internal/AbstractExecutorProvidersConfigurator.java +++ b/core-common/src/main/java/org/glassfish/jersey/process/internal/AbstractExecutorProvidersConfigurator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -24,6 +24,7 @@ import org.glassfish.jersey.internal.BootstrapConfigurator; import org.glassfish.jersey.internal.inject.InjectionManager; import org.glassfish.jersey.model.internal.ComponentBag; +import org.glassfish.jersey.model.internal.ManagedObjectsFinalizer; import org.glassfish.jersey.spi.ExecutorServiceProvider; import org.glassfish.jersey.spi.ScheduledExecutorServiceProvider; @@ -49,12 +50,14 @@ public abstract class AbstractExecutorProvidersConfigurator implements Bootstrap * @param componentBag provides executor service providers registered by an application. * @param defaultAsyncExecutorProvider default implementation of {@link ExecutorServiceProvider}. * @param defaultScheduledExecutorProvider default implementation of {@link ScheduledExecutorServiceProvider}. + * @param finalizer register finalizers. */ protected void registerExecutors( InjectionManager injectionManager, ComponentBag componentBag, ExecutorServiceProvider defaultAsyncExecutorProvider, - ScheduledExecutorServiceProvider defaultScheduledExecutorProvider) { + ScheduledExecutorServiceProvider defaultScheduledExecutorProvider, + ManagedObjectsFinalizer finalizer) { List customExecutors = Stream.concat( @@ -64,6 +67,7 @@ protected void registerExecutors( .map(CAST_TO_EXECUTOR_PROVIDER) .collect(Collectors.toList()); customExecutors.add(defaultAsyncExecutorProvider); + customExecutors.stream().forEach(e -> finalizer.registerForPreDestroyCall(e)); List customScheduledExecutors = Stream.concat( @@ -73,6 +77,7 @@ protected void registerExecutors( .map(CAST_TO_SCHEDULED_EXECUTOR_PROVIDER) .collect(Collectors.toList()); customScheduledExecutors.add(defaultScheduledExecutorProvider); + customScheduledExecutors.stream().forEach(e -> finalizer.registerForPreDestroyCall(e)); ExecutorProviders.registerExecutorBindings(injectionManager, customExecutors, customScheduledExecutors); } diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ServerExecutorProvidersConfigurator.java b/core-server/src/main/java/org/glassfish/jersey/server/ServerExecutorProvidersConfigurator.java index 5a18a3efb4..77974f1946 100644 --- a/core-server/src/main/java/org/glassfish/jersey/server/ServerExecutorProvidersConfigurator.java +++ b/core-server/src/main/java/org/glassfish/jersey/server/ServerExecutorProvidersConfigurator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -41,7 +41,6 @@ public void init(InjectionManager injectionManager, BootstrapBag bootstrapBag) { ServerBootstrapBag serverBag = (ServerBootstrapBag) bootstrapBag; ResourceConfig runtimeConfig = serverBag.getRuntimeConfig(); ComponentBag componentBag = runtimeConfig.getComponentBag(); - ManagedObjectsFinalizer finalizer = serverBag.getManagedObjectsFinalizer(); // TODO: Do we need to register DEFAULT Executor and ScheduledExecutor to InjectionManager? ScheduledExecutorServiceProvider defaultScheduledExecutorProvider = new DefaultBackgroundSchedulerProvider(); @@ -50,16 +49,15 @@ public void init(InjectionManager injectionManager, BootstrapBag bootstrapBag) { .to(ScheduledExecutorServiceProvider.class) .qualifiedBy(BackgroundSchedulerLiteral.INSTANCE); injectionManager.register(schedulerBinding); - finalizer.registerForPreDestroyCall(defaultScheduledExecutorProvider); ExecutorServiceProvider defaultAsyncExecutorProvider = new DefaultManagedAsyncExecutorProvider(); InstanceBinding executorBinding = Bindings .service(defaultAsyncExecutorProvider) .to(ExecutorServiceProvider.class); injectionManager.register(executorBinding); - finalizer.registerForPreDestroyCall(defaultAsyncExecutorProvider); - registerExecutors(injectionManager, componentBag, defaultAsyncExecutorProvider, defaultScheduledExecutorProvider); + registerExecutors(injectionManager, componentBag, defaultAsyncExecutorProvider, + defaultScheduledExecutorProvider, serverBag.getManagedObjectsFinalizer()); } /** diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ScheduledThreadPoolExecutorProviderTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ScheduledThreadPoolExecutorProviderTest.java new file mode 100644 index 0000000000..4a1a1306b0 --- /dev/null +++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ScheduledThreadPoolExecutorProviderTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.jersey.tests.e2e.server; + +import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadFactory; + +import javax.inject.Singleton; +import javax.ws.rs.core.Application; + +import org.glassfish.jersey.server.BackgroundScheduler; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.spi.ScheduledThreadPoolExecutorProvider; +import org.glassfish.jersey.test.JerseyTest; +import org.junit.Test; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class ScheduledThreadPoolExecutorProviderTest { + + @Test + public void restartShutsdownScheduler() throws Exception { + WebContainer container = new WebContainer(); + container.setUp(); + container.tearDown(); + assertNotNull(CustomScheduledThreadPoolExecutorProvider.executor); + assertTrue(CustomScheduledThreadPoolExecutorProvider.selfRef.isClosed()); + assertTrue(CustomScheduledThreadPoolExecutorProvider.executor.isShutdown()); + } + + private static class WebContainer extends JerseyTest { + @Override + protected Application configure() { + return new ResourceConfig(CustomScheduledThreadPoolExecutorProvider.class); + } + } + + @BackgroundScheduler + @Singleton + public static class CustomScheduledThreadPoolExecutorProvider extends ScheduledThreadPoolExecutorProvider { + + private static CustomScheduledThreadPoolExecutorProvider selfRef; + private static ScheduledThreadPoolExecutor executor; + + public CustomScheduledThreadPoolExecutorProvider() { + this("CustomScheduledThreadPoolExecutorProvider"); + } + + public CustomScheduledThreadPoolExecutorProvider(String name) { + super(name); + CustomScheduledThreadPoolExecutorProvider.selfRef = this; + } + + @Override + protected ScheduledThreadPoolExecutor createExecutor(int corePoolSize, ThreadFactory threadFactory, + RejectedExecutionHandler handler) { + executor = new ScheduledThreadPoolExecutor(5, threadFactory, handler); + return executor; + } + } +}