diff --git a/airframe-jmx/src/main/scala/wvlet/airframe/jmx/JMXUtil.scala b/airframe-jmx/src/main/scala/wvlet/airframe/jmx/JMXUtil.scala index a8d04adb99..7b1a354d08 100644 --- a/airframe-jmx/src/main/scala/wvlet/airframe/jmx/JMXUtil.scala +++ b/airframe-jmx/src/main/scala/wvlet/airframe/jmx/JMXUtil.scala @@ -104,7 +104,7 @@ object JMXUtil extends LogSupport { private[jmx] def startAndGetAgentURL(config: JMXConfig): String = { Try(startAgent(config)) match { case Success(x) => - info(s"Started JMX agent at localhost:${x.port}") + debug(s"Started JMX agent at localhost:${x.port}") s"service:jmx:rmi:///jndi/rmi://localhost:${x.port}/jmxrmi" case Failure(e) => warn(e) diff --git a/airframe-log/jvm/src/test/scala/wvlet/log/LoggerJMXTest.scala b/airframe-log/jvm/src/test/scala/wvlet/log/LoggerJMXTest.scala index 3c8b4e526c..56803552f4 100644 --- a/airframe-log/jvm/src/test/scala/wvlet/log/LoggerJMXTest.scala +++ b/airframe-log/jvm/src/test/scala/wvlet/log/LoggerJMXTest.scala @@ -14,13 +14,13 @@ package wvlet.log import java.lang.management.ManagementFactory -import javax.management.{Attribute, JMX, ObjectName} +import javax.management.{Attribute, ObjectName} /** * */ class LoggerJMXTest extends Spec { - "LoggerJXM" should { + "LoggerJMX" should { "be registered" in { // Initialize a logger val l = Logger.rootLogger diff --git a/airframe/.jvm/src/main/scala/wvlet/airframe/AddShutdownHook.scala b/airframe/.jvm/src/main/scala/wvlet/airframe/AddShutdownHook.scala index 66e70af5da..1444445d97 100644 --- a/airframe/.jvm/src/main/scala/wvlet/airframe/AddShutdownHook.scala +++ b/airframe/.jvm/src/main/scala/wvlet/airframe/AddShutdownHook.scala @@ -13,26 +13,50 @@ */ package wvlet.airframe -import java.util.concurrent.atomic.{AtomicBoolean, AtomicInteger} - import wvlet.log.AirframeLogManager +import scala.collection.mutable +import scala.sys.ShutdownHookThread + /** * */ object AddShutdownHook extends LifeCycleEventHandler { - private val registered = new AtomicInteger(0) + private val shutdownHooks = new mutable.WeakHashMap[LifeCycleManager, ShutdownHookThread]() + + private def removeShutdownHooksFor(lifeCycleManager: LifeCycleManager): Unit = { + synchronized { + shutdownHooks.get(lifeCycleManager).map { h => + // Properly unregister shutdown hooks + // This will be a workaround for sbt-1.3.0-RC2 https://github.com/sbt/sbt/issues/4794 (user class will not be visible at sbt shutdown) + if (h != null) { + h.remove() + } + shutdownHooks.remove(lifeCycleManager) + } + } + } override def beforeStart(lifeCycleManager: LifeCycleManager): Unit = { - registered.incrementAndGet() - sys.addShutdownHook { + val shutdownHookThread = sys.addShutdownHook { lifeCycleManager.shutdown - if (registered.decrementAndGet() <= 0) { + removeShutdownHooksFor(lifeCycleManager) + if (shutdownHooks.isEmpty) { // Resetting the logger when all lifecycle have terminated AirframeLogManager.resetFinally } } + + // Remember the shutdown hooks registered + synchronized { + shutdownHooks.put(lifeCycleManager, shutdownHookThread) + } + } + + override def afterShutdown(lifeCycleManager: LifeCycleManager): Unit = { + // Unregister shutdown hooks + removeShutdownHooksFor(lifeCycleManager) } } diff --git a/build.sbt b/build.sbt index 104713939a..0100aa702f 100644 --- a/build.sbt +++ b/build.sbt @@ -52,7 +52,6 @@ val buildSettings = Seq[Setting[_]]( crossScalaVersions := targetScalaVersions, crossPaths := true, publishMavenStyle := true, - logBuffered in Test := false, scalacOptions ++= Seq("-feature", "-deprecation"), // ,"-Ytyper-debug"), sonatypeProfileName := "org.wvlet", licenses += ("Apache-2.0", url("https://www.apache.org/licenses/LICENSE-2.0.html")), @@ -310,8 +309,9 @@ lazy val airframe = ) ) .jvmSettings( - // Workaround for https://github.com/scala/scala/pull/7624 - fork in Test := (scalaVersion.value.startsWith("2.13.")), + // Workaround for https://github.com/scala/scala/pull/7624 in Scala 2.13, and also + // testing shtudown hooks requires consistent application lifecycle between sbt and JVM https://github.com/sbt/sbt/issues/4794 + fork in Test := scalaBinaryVersion.value == "2.13", // include the macro classes and resources in the main jar mappings in (Compile, packageBin) ++= mappings.in(airframeMacrosJVM, Compile, packageBin).value, // include the macro sources in the main source jar diff --git a/project/build.properties b/project/build.properties index e34d504da3..8f92a593b8 100755 --- a/project/build.properties +++ b/project/build.properties @@ -12,4 +12,4 @@ # limitations under the License. # -sbt.version=1.3.0-RC1 +sbt.version=1.3.0-RC2