From 46d94aba4f4b78377ac80300ccc06eeb58e3a2a9 Mon Sep 17 00:00:00 2001 From: nklmish Date: Fri, 1 Dec 2017 11:19:23 +0100 Subject: [PATCH 1/2] Allow graceful shutdown of Atomikos See gh-11237 --- .../jta/AtomikosJtaConfiguration.java | 3 ++- .../boot/jta/atomikos/AtomikosProperties.java | 20 +++++++++++++++++++ .../jta/atomikos/AtomikosPropertiesTests.java | 10 +++++++--- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/AtomikosJtaConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/AtomikosJtaConfiguration.java index a653a24dd2..23bc7bc85d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/AtomikosJtaConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/AtomikosJtaConfiguration.java @@ -53,6 +53,7 @@ import org.springframework.util.StringUtils; * @author Andy Wilkinson * @author Stephane Nicoll * @author Kazuki Shimizu + * @author Nakul Mishra * @since 1.2.0 */ @Configuration @@ -72,7 +73,7 @@ class AtomikosJtaConfiguration { .getIfAvailable(); } - @Bean(initMethod = "init", destroyMethod = "shutdownForce") + @Bean(initMethod = "init", destroyMethod = "shutdownWait") @ConditionalOnMissingBean(UserTransactionService.class) public UserTransactionServiceImp userTransactionService( AtomikosProperties atomikosProperties) { diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosProperties.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosProperties.java index 6a03d099d3..b3ddb0ece0 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosProperties.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosProperties.java @@ -29,6 +29,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; * * @author Phillip Webb * @author Stephane Nicoll + * @author Nakul Mishra * @since 1.2.0 * @see #asProperties() */ @@ -107,6 +108,11 @@ public class AtomikosProperties { private final Recovery recovery = new Recovery(); + /** + * How long should normal shutdown (no-force) wait for transactions to complete. + */ + private long defaultMaxWaitTimeOnShutdown = Long.MAX_VALUE; + /** * Specifies the transaction manager implementation that should be started. There is * no default value and this must be set. Generally, @@ -300,6 +306,19 @@ public class AtomikosProperties { return this.recovery; } + /** + * Specifies how long should a normal shutdown (no-force) wait for transactions to complete. + * Defaults to {@literal Long.MAX_VALUE}. + * @param defaultMaxWaitTimeOnShutdown the default max wait time on shutdown + */ + public void setDefaultMaxWaitTimeOnShutdown(long defaultMaxWaitTimeOnShutdown) { + this.defaultMaxWaitTimeOnShutdown = defaultMaxWaitTimeOnShutdown; + } + + public long getDefaultMaxWaitTimeOnShutdown() { + return this.defaultMaxWaitTimeOnShutdown; + } + /** * Returns the properties as a {@link Properties} object that can be used with * Atomikos. @@ -326,6 +345,7 @@ public class AtomikosProperties { set(properties, "recovery_delay", recovery.getDelay()); set(properties, "oltp_max_retries", recovery.getMaxRetries()); set(properties, "oltp_retry_interval", recovery.getRetryInterval()); + set(properties, "default_max_wait_time_on_shutdown", getDefaultMaxWaitTimeOnShutdown()); return properties; } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosPropertiesTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosPropertiesTests.java index 0565dd1662..a06d4dfc18 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosPropertiesTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosPropertiesTests.java @@ -33,6 +33,7 @@ import static org.assertj.core.api.Assertions.entry; * * @author Phillip Webb * @author Stephane Nicoll + * @author Nakul Mishra */ public class AtomikosPropertiesTests { @@ -58,7 +59,8 @@ public class AtomikosPropertiesTests { this.properties.getRecovery().setDelay(Duration.ofMillis(3000)); this.properties.getRecovery().setMaxRetries(10); this.properties.getRecovery().setRetryInterval(Duration.ofMillis(4000)); - assertThat(this.properties.asProperties().size()).isEqualTo(17); + this.properties.setDefaultMaxWaitTimeOnShutdown(20); + assertThat(this.properties.asProperties().size()).isEqualTo(18); assertProperty("com.atomikos.icatch.service", "service"); assertProperty("com.atomikos.icatch.max_timeout", "1"); assertProperty("com.atomikos.icatch.default_jta_timeout", "2"); @@ -76,6 +78,7 @@ public class AtomikosPropertiesTests { assertProperty("com.atomikos.icatch.recovery_delay", "3000"); assertProperty("com.atomikos.icatch.oltp_max_retries", "10"); assertProperty("com.atomikos.icatch.oltp_retry_interval", "4000"); + assertProperty("com.atomikos.icatch.default_max_wait_time_on_shutdown", "20"); } @Test @@ -94,10 +97,11 @@ public class AtomikosPropertiesTests { "com.atomikos.icatch.threaded_2pc", "com.atomikos.icatch.forget_orphaned_log_entries_delay", "com.atomikos.icatch.oltp_max_retries", - "com.atomikos.icatch.oltp_retry_interval")); + "com.atomikos.icatch.oltp_retry_interval", + "com.atomikos.icatch.default_max_wait_time_on_shutdown")); assertThat(properties).contains(entry("com.atomikos.icatch.recovery_delay", defaultSettings.get("com.atomikos.icatch.default_jta_timeout"))); - assertThat(properties).hasSize(14); + assertThat(properties).hasSize(15); } private MapEntry[] defaultOf(Properties defaultSettings, String... keys) { From 408368a1f931857fd99344d40d0406b43c9bc5e2 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Tue, 12 Dec 2017 08:30:24 +0100 Subject: [PATCH 2/2] Polish "Allow graceful shutdown of Atomikos" Closes gh-11237 --- .../jta/AtomikosJtaConfiguration.java | 1 - .../appendix-application-properties.adoc | 1 + .../boot/jta/atomikos/AtomikosProperties.java | 39 ++++++++++--------- .../jta/atomikos/AtomikosPropertiesTests.java | 9 ++--- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/AtomikosJtaConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/AtomikosJtaConfiguration.java index 23bc7bc85d..01bce191e0 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/AtomikosJtaConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/AtomikosJtaConfiguration.java @@ -53,7 +53,6 @@ import org.springframework.util.StringUtils; * @author Andy Wilkinson * @author Stephane Nicoll * @author Kazuki Shimizu - * @author Nakul Mishra * @since 1.2.0 */ @Configuration diff --git a/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index 1636762783..bea1dd81f8 100644 --- a/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -749,6 +749,7 @@ content into your application. Rather, pick only the properties that you need. spring.jta.atomikos.properties.allow-sub-transactions=true # Specify whether sub-transactions are allowed. spring.jta.atomikos.properties.checkpoint-interval=500 # Interval between checkpoints, in milliseconds. spring.jta.atomikos.properties.default-jta-timeout=10000 # Default timeout for JTA transactions, in milliseconds. + spring.jta.atomikos.properties.default-max-wait-time-on-shutdown=9223372036854775807 # How long should normal shutdown (no-force) wait for transactions to complete. spring.jta.atomikos.properties.enable-logging=true # Whether to enable disk logging. spring.jta.atomikos.properties.force-shutdown-on-vm-exit=false # Whether a VM shutdown should trigger forced shutdown of the transaction core. spring.jta.atomikos.properties.log-base-dir= # Directory in which the log files should be stored. diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosProperties.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosProperties.java index b3ddb0ece0..303d954e58 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosProperties.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosProperties.java @@ -29,7 +29,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; * * @author Phillip Webb * @author Stephane Nicoll - * @author Nakul Mishra * @since 1.2.0 * @see #asProperties() */ @@ -83,6 +82,11 @@ public class AtomikosProperties { */ private boolean forceShutdownOnVmExit; + /** + * How long should normal shutdown (no-force) wait for transactions to complete. + */ + private long defaultMaxWaitTimeOnShutdown = Long.MAX_VALUE; + /** * Transactions log file base name. */ @@ -108,10 +112,6 @@ public class AtomikosProperties { private final Recovery recovery = new Recovery(); - /** - * How long should normal shutdown (no-force) wait for transactions to complete. - */ - private long defaultMaxWaitTimeOnShutdown = Long.MAX_VALUE; /** * Specifies the transaction manager implementation that should be started. There is @@ -242,6 +242,19 @@ public class AtomikosProperties { return this.forceShutdownOnVmExit; } + /** + * Specifies how long should a normal shutdown (no-force) wait for transactions to complete. + * Defaults to {@literal Long.MAX_VALUE}. + * @param defaultMaxWaitTimeOnShutdown the default max wait time on shutdown + */ + public void setDefaultMaxWaitTimeOnShutdown(long defaultMaxWaitTimeOnShutdown) { + this.defaultMaxWaitTimeOnShutdown = defaultMaxWaitTimeOnShutdown; + } + + public long getDefaultMaxWaitTimeOnShutdown() { + return this.defaultMaxWaitTimeOnShutdown; + } + /** * Specifies the transactions log file base name. Defaults to {@literal tmlog}. The * transactions logs are stored in files using this name appended with a number and @@ -306,19 +319,6 @@ public class AtomikosProperties { return this.recovery; } - /** - * Specifies how long should a normal shutdown (no-force) wait for transactions to complete. - * Defaults to {@literal Long.MAX_VALUE}. - * @param defaultMaxWaitTimeOnShutdown the default max wait time on shutdown - */ - public void setDefaultMaxWaitTimeOnShutdown(long defaultMaxWaitTimeOnShutdown) { - this.defaultMaxWaitTimeOnShutdown = defaultMaxWaitTimeOnShutdown; - } - - public long getDefaultMaxWaitTimeOnShutdown() { - return this.defaultMaxWaitTimeOnShutdown; - } - /** * Returns the properties as a {@link Properties} object that can be used with * Atomikos. @@ -335,6 +335,8 @@ public class AtomikosProperties { set(properties, "serial_jta_transactions", isSerialJtaTransactions()); set(properties, "allow_subtransactions", isAllowSubTransactions()); set(properties, "force_shutdown_on_vm_exit", isForceShutdownOnVmExit()); + set(properties, "default_max_wait_time_on_shutdown", + getDefaultMaxWaitTimeOnShutdown()); set(properties, "log_base_name", getLogBaseName()); set(properties, "log_base_dir", getLogBaseDir()); set(properties, "checkpoint_interval", getCheckpointInterval()); @@ -345,7 +347,6 @@ public class AtomikosProperties { set(properties, "recovery_delay", recovery.getDelay()); set(properties, "oltp_max_retries", recovery.getMaxRetries()); set(properties, "oltp_retry_interval", recovery.getRetryInterval()); - set(properties, "default_max_wait_time_on_shutdown", getDefaultMaxWaitTimeOnShutdown()); return properties; } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosPropertiesTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosPropertiesTests.java index a06d4dfc18..79d6937f31 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosPropertiesTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosPropertiesTests.java @@ -33,7 +33,6 @@ import static org.assertj.core.api.Assertions.entry; * * @author Phillip Webb * @author Stephane Nicoll - * @author Nakul Mishra */ public class AtomikosPropertiesTests { @@ -50,6 +49,7 @@ public class AtomikosPropertiesTests { this.properties.setSerialJtaTransactions(true); this.properties.setAllowSubTransactions(false); this.properties.setForceShutdownOnVmExit(true); + this.properties.setDefaultMaxWaitTimeOnShutdown(20); this.properties.setLogBaseName("logBaseName"); this.properties.setLogBaseDir("logBaseDir"); this.properties.setCheckpointInterval(4); @@ -59,7 +59,6 @@ public class AtomikosPropertiesTests { this.properties.getRecovery().setDelay(Duration.ofMillis(3000)); this.properties.getRecovery().setMaxRetries(10); this.properties.getRecovery().setRetryInterval(Duration.ofMillis(4000)); - this.properties.setDefaultMaxWaitTimeOnShutdown(20); assertThat(this.properties.asProperties().size()).isEqualTo(18); assertProperty("com.atomikos.icatch.service", "service"); assertProperty("com.atomikos.icatch.max_timeout", "1"); @@ -70,6 +69,7 @@ public class AtomikosPropertiesTests { assertProperty("com.atomikos.icatch.serial_jta_transactions", "true"); assertProperty("com.atomikos.icatch.allow_subtransactions", "false"); assertProperty("com.atomikos.icatch.force_shutdown_on_vm_exit", "true"); + assertProperty("com.atomikos.icatch.default_max_wait_time_on_shutdown", "20"); assertProperty("com.atomikos.icatch.log_base_name", "logBaseName"); assertProperty("com.atomikos.icatch.log_base_dir", "logBaseDir"); assertProperty("com.atomikos.icatch.checkpoint_interval", "4"); @@ -78,7 +78,6 @@ public class AtomikosPropertiesTests { assertProperty("com.atomikos.icatch.recovery_delay", "3000"); assertProperty("com.atomikos.icatch.oltp_max_retries", "10"); assertProperty("com.atomikos.icatch.oltp_retry_interval", "4000"); - assertProperty("com.atomikos.icatch.default_max_wait_time_on_shutdown", "20"); } @Test @@ -92,13 +91,13 @@ public class AtomikosPropertiesTests { "com.atomikos.icatch.serial_jta_transactions", "com.atomikos.icatch.allow_subtransactions", "com.atomikos.icatch.force_shutdown_on_vm_exit", + "com.atomikos.icatch.default_max_wait_time_on_shutdown", "com.atomikos.icatch.log_base_name", "com.atomikos.icatch.checkpoint_interval", "com.atomikos.icatch.threaded_2pc", "com.atomikos.icatch.forget_orphaned_log_entries_delay", "com.atomikos.icatch.oltp_max_retries", - "com.atomikos.icatch.oltp_retry_interval", - "com.atomikos.icatch.default_max_wait_time_on_shutdown")); + "com.atomikos.icatch.oltp_retry_interval")); assertThat(properties).contains(entry("com.atomikos.icatch.recovery_delay", defaultSettings.get("com.atomikos.icatch.default_jta_timeout"))); assertThat(properties).hasSize(15);