@Async
Spring アプリで返すvoid
(またはUnit
、Kotlin で書いている)メソッドに少し問題があります。
理由はわかりませんが、@Async
メソッドが返さvoid
れたときに実行されないか、少なくとも本来の動作が行われません。私の非同期メソッドでは、 を使用してメールを送信したいJavaMailSender
ので、大したことはありません。メソッドは次のとおりです。
@Async
override fun sendEmail(locale: Locale, subject: String, message: String, to: String) {
val msg = sender.createMimeMessage()
println("1")
val helper = MimeMessageHelper(msg, true, "utf-8")
helper.setFrom("email@example.com")
helper.setTo(to)
println("2")
helper.setSubject(getSubject(locale, null))
println("3")
helper.setText(processTemplate(locale, null, null), true)
println("4")
sender.send(msg)
println("5")
}
しかし、電子メールは決して来ません。例外はログに記録されません (私は testNG テストを実行しています)。
関数のシグネチャを変更して関数を返すようにしFuture<String>
、ダミーの return 行を関数の最後に追加してから を呼び出すservice.sendEmail(...).get()
と、メソッドの本体が魔法のように実行され、電子メールが届きます。
私の@Configuration
クラスには、 があり@EnableAsync
ます。また、独自のエグゼキューターと例外ハンドラーを実装AsyncConfigurer
して提供しました。これは、エグゼキューター Bean の定義に問題がある可能性があると考えたからですが、何も役に立ちませんでした。
バックグラウンドで何かを静かに実行したいだけで、うまくいかないので、これは私を夢中にさせています。静かにということは、内部でスローされる例外に悩まされたくないということです。
あなたはなにか考えはありますか?
更新:
@pleftがアドバイスしたように、メソッド内にいくつかのプリントを入れました。を実行すると、毎回ではなくmvn clean test
、1,2,3 が出力されていることがわかります。1 と 2 だけが印刷されることもありました。print も入れましたAsyncUncaughtExceptionHandler
が、それは呼び出されません。バックグラウンド スレッドが殺されるのが早すぎるか何かのようです。
更新 2:
私のサービス構成:
@Configuration
@EnableScheduling
@EnableAsync
@ComponentScan
class ServiceConfig : ApplicationContextAware, EnvironmentAware, AsyncConfigurer {
override fun getAsyncUncaughtExceptionHandler(): AsyncUncaughtExceptionHandler {
return AsyncUncaughtExceptionHandler { ex, method, params ->
println("Exception thrown")
}
}
override fun getAsyncExecutor(): Executor {
val executor = ThreadPoolTaskExecutor()
executor.corePoolSize = 2
executor.maxPoolSize = 2
executor.setQueueCapacity(500)
executor.threadNamePrefix = "asyncThread"
executor.initialize()
return executor
}
}
/// other beans definitions..
重要かもしれませんが、重要ではないかもしれませんが、私はそのprocessTemplate
方法で Thymeleaf を使用しています。