Skip to content

Commit a53ce99

Browse files
committed
#246: Keep track of whether the user manually provided an executor service and if not, shut it down together with the connection pool to prevent a JVM shutdown from being blocked.
1 parent 9d61a9e commit a53ce99

File tree

7 files changed

+68
-2
lines changed

7 files changed

+68
-2
lines changed

modules/core-module/src/main/java/org/simplejavamail/api/mailer/Mailer.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,9 @@ public interface Mailer {
112112
* Shuts down the connection pool associated with this {@link Mailer} instance and closes remaining open connections. Waits until all connections still in use become available again
113113
* to deallocate them as well.
114114
* <p>
115-
* In order to shut down the whole connection pool (in case of clustering), each individual {@link Mailer} instance should be shutdown.
115+
* <strong>Note:</strong> In order to shut down the whole connection pool (in case of clustering), each individual {@link Mailer} instance should be shutdown.
116+
* <p>
117+
* <strong>Note:</strong> This does *not* shut down the executor service if it was provided by the user.
116118
* <p>
117119
* <strong>Note:</strong> this is only works in combination with the {@value org.simplejavamail.internal.modules.BatchModule#NAME}.
118120
*/

modules/core-module/src/main/java/org/simplejavamail/api/mailer/MailerGenericBuilder.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,10 @@ public interface MailerGenericBuilder<T extends MailerGenericBuilder<?>> {
243243
* <strong>Note:</strong> What makes it NonJvm is that the default keepAliveTime is set to the lowest non-zero value (so 1), so that
244244
* any threads will die off as soon as possible, as not to block the JVM from shutting down.
245245
* <p>
246+
* <p>
247+
* <strong>Note:</strong> Simple Java Mail will <strong>not</strong> shut down the provided executor service, even if the connection pool is being shut down.
248+
* <em>This will block the JVM from shutting down</em>. The user is responsible for managing the provided executor's life cycle.
249+
* <p>
246250
* <strong>Note:</strong> this only works in combination with the {@value org.simplejavamail.internal.modules.BatchModule#NAME}.
247251
*
248252
* @param executorService A custom executor service (ThreadPoolExecutor), replacing the {@code NonJvmBlockingThreadPoolExecutor}.

modules/core-module/src/main/java/org/simplejavamail/api/mailer/config/OperationalConfig.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ public interface OperationalConfig {
109109
@NotNull
110110
ExecutorService getExecutorService();
111111

112+
/**
113+
* Indicates whether the executor service was provided by the user or internally. Used to known if Simple Java Mail should shut down the executor
114+
* when the connection pool is shut down.
115+
*/
116+
boolean executorServiceIsUserProvided();
117+
112118
/**
113119
* @see MailerGenericBuilder#withCustomMailer(CustomMailer)
114120
*/
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.simplejavamail.mailer.internal;
2+
3+
import org.simplejavamail.api.mailer.MailerGenericBuilder;
4+
5+
/**
6+
* This interface is only there to improve readability there where internal builder API is used.
7+
*/
8+
@SuppressWarnings("UnusedReturnValue")
9+
public interface InternalMailerBuilder<T extends MailerGenericBuilder<?>> extends MailerGenericBuilder<T> {
10+
boolean isExecutorServiceUserProvided();
11+
}

modules/simple-java-mail/src/main/java/org/simplejavamail/mailer/internal/MailerGenericBuilderImpl.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
* @see MailerGenericBuilder
4040
*/
4141
@SuppressWarnings({"UnusedReturnValue", "unchecked"})
42-
abstract class MailerGenericBuilderImpl<T extends MailerGenericBuilderImpl<?>> implements MailerGenericBuilder<T> {
42+
abstract class MailerGenericBuilderImpl<T extends MailerGenericBuilderImpl<?>> implements InternalMailerBuilder<T> {
4343

4444
/**
4545
* @see MailerGenericBuilder#async()
@@ -95,6 +95,11 @@ abstract class MailerGenericBuilderImpl<T extends MailerGenericBuilderImpl<?>> i
9595
@NotNull
9696
private ExecutorService executorService;
9797

98+
/**
99+
* @see InternalMailerBuilder#isExecutorServiceUserProvided()
100+
*/
101+
private boolean executorServiceIsUserProvided = false;
102+
98103
/**
99104
* @see MailerGenericBuilder#withThreadPoolSize(Integer)
100105
*/
@@ -266,6 +271,7 @@ OperationalConfig buildOperationalConfig() {
266271
isTrustAllSSLHost(),
267272
isVerifyingServerIdentity(),
268273
getExecutorService(),
274+
isExecutorServiceUserProvided(),
269275
getCustomMailer());
270276
}
271277

@@ -376,6 +382,7 @@ public T withEmailAddressCriteria(@NotNull final EnumSet<EmailAddressCriteria> e
376382
@Override
377383
public T withExecutorService(@NotNull final ExecutorService executorService) {
378384
this.executorService = executorService;
385+
this.executorServiceIsUserProvided = true;
379386
return (T) this;
380387
}
381388

@@ -569,6 +576,7 @@ public T resetEmailAddressCriteria() {
569576
@Override
570577
public T resetExecutorService() {
571578
this.executorService = determineDefaultExecutorService();
579+
this.executorServiceIsUserProvided = false;
572580
return (T) this;
573581
}
574582

@@ -773,6 +781,14 @@ public ExecutorService getExecutorService() {
773781
return executorService;
774782
}
775783

784+
/**
785+
* @see InternalMailerBuilder#isExecutorServiceUserProvided()
786+
*/
787+
@Override
788+
public boolean isExecutorServiceUserProvided() {
789+
return executorServiceIsUserProvided;
790+
}
791+
776792
/**
777793
* @see MailerGenericBuilder#getThreadPoolSize()
778794
*/

modules/simple-java-mail/src/main/java/org/simplejavamail/mailer/internal/MailerImpl.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,9 @@ public boolean validate(@NotNull final Email email)
337337
*/
338338
@Override
339339
public Future<?> shutdownConnectionPool() {
340+
if (!operationalConfig.executorServiceIsUserProvided()) {
341+
operationalConfig.getExecutorService().shutdown();
342+
}
340343
return ModuleLoader.loadBatchModule().shutdownConnectionPools(session);
341344
}
342345

modules/simple-java-mail/src/main/java/org/simplejavamail/mailer/internal/OperationalConfigImpl.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ class OperationalConfigImpl implements OperationalConfig {
107107
@NotNull
108108
private final ExecutorService executorService;
109109

110+
/**
111+
* @see InternalMailerBuilder#isExecutorServiceUserProvided()
112+
*/
113+
private final boolean executorServiceIsUserProvided;
114+
110115
/**
111116
* @see org.simplejavamail.api.mailer.MailerGenericBuilder#withCustomMailer(CustomMailer)
112117
*/
@@ -130,6 +135,7 @@ class OperationalConfigImpl implements OperationalConfig {
130135
final boolean trustAllSSLHost,
131136
final boolean verifyingServerIdentity,
132137
@NotNull final ExecutorService executorService,
138+
final boolean executorServiceIsUserProvided,
133139
@Nullable final CustomMailer customMailer) {
134140
this.async = async; // can be overridden when calling {@code mailer.send(async = true)}
135141
this.properties = properties;
@@ -148,6 +154,7 @@ class OperationalConfigImpl implements OperationalConfig {
148154
this.trustAllSSLHost = trustAllSSLHost;
149155
this.verifyingServerIdentity = verifyingServerIdentity;
150156
this.executorService = executorService;
157+
this.executorServiceIsUserProvided = executorServiceIsUserProvided;
151158
this.customMailer = customMailer;
152159
}
153160

@@ -297,18 +304,35 @@ public Properties getProperties() {
297304
return properties;
298305
}
299306

307+
/**
308+
* @see OperationalConfig#getClusterKey()
309+
*/
300310
@NotNull
301311
@Override
302312
public UUID getClusterKey() {
303313
return clusterKey;
304314
}
305315

316+
/**
317+
* @see OperationalConfig#getExecutorService()
318+
*/
306319
@NotNull
307320
@Override
308321
public ExecutorService getExecutorService() {
309322
return executorService;
310323
}
311324

325+
/**
326+
* @see OperationalConfig#executorServiceIsUserProvided()
327+
*/
328+
@Override
329+
public boolean executorServiceIsUserProvided() {
330+
return executorServiceIsUserProvided;
331+
}
332+
333+
/**
334+
* @see OperationalConfig#getCustomMailer()
335+
*/
312336
@Nullable
313337
@Override
314338
public CustomMailer getCustomMailer() {

0 commit comments

Comments
 (0)