summaryrefslogtreecommitdiffstats
path: root/container-di
diff options
context:
space:
mode:
authorgjoranv <gv@yahoo-inc.com>2017-05-18 14:32:09 +0200
committergjoranv <gv@yahoo-inc.com>2017-05-18 16:19:13 +0200
commita3ef767b6961450299bbdf7bd813d5a4239917fa (patch)
tree50896cc97b915fdd5cf3fbe39f9dc584b25baad4 /container-di
parent48d803a3cd550f4988981344ba4207fda39a75b7 (diff)
Wrap component constructor exceptions and handle separately.
Diffstat (limited to 'container-di')
-rw-r--r--container-di/src/main/scala/com/yahoo/container/di/Container.scala24
-rw-r--r--container-di/src/main/scala/com/yahoo/container/di/componentgraph/core/ComponentNode.scala19
2 files changed, 26 insertions, 17 deletions
diff --git a/container-di/src/main/scala/com/yahoo/container/di/Container.scala b/container-di/src/main/scala/com/yahoo/container/di/Container.scala
index cd5339cc313..bc3f9fbe79e 100644
--- a/container-di/src/main/scala/com/yahoo/container/di/Container.scala
+++ b/container-di/src/main/scala/com/yahoo/container/di/Container.scala
@@ -1,8 +1,8 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.container.di
-import com.yahoo.container.di.ConfigRetriever.{ComponentsConfigs, BootstrapConfigs}
-import com.yahoo.container.di.componentgraph.core.{JerseyNode, ComponentGraph, ComponentNode}
+import com.yahoo.container.di.ConfigRetriever.{BootstrapConfigs, ComponentsConfigs}
+import com.yahoo.container.di.componentgraph.core.{ComponentGraph, ComponentNode, JerseyNode}
import com.yahoo.container.di.config.{RestApiContext, SubscriberFactory}
import Container._
@@ -11,10 +11,13 @@ import scala.math.max
import com.yahoo.config._
import com.yahoo.vespa.config.ConfigKey
import java.util.IdentityHashMap
-import java.util.logging.Logger
+import java.util.logging.{Level, Logger}
+
import com.yahoo.container.bundle.BundleInstantiationSpecification
-import com.google.inject.{Injector, Guice}
+import com.google.inject.{Guice, Injector}
+import com.yahoo.container.di.componentgraph.core.ComponentNode.ComponentConstructorException
import com.yahoo.container.{BundlesConfig, ComponentsConfig}
+import com.yahoo.log.LogLevel
/**
@@ -49,20 +52,23 @@ class Container(
}
try {
- //TODO: wrap user exceptions.
val newGraph = createNewGraph(oldGraph, fallbackInjector)
newGraph.reuseNodes(oldGraph)
constructComponents(newGraph)
deconstructObsoleteComponents(oldGraph, newGraph)
newGraph
} catch {
- case e : Throwable =>
- invalidateGeneration()
- throw e
+ case userException : ComponentConstructorException =>
+ invalidateGeneration("Failed to set up new component graph due to error when constructing one of the components.", userException)
+ throw userException
+ case t : Throwable =>
+ invalidateGeneration("Failed to set up new component graph.", t)
+ throw t
}
}
- private def invalidateGeneration() {
+ private def invalidateGeneration(message: String, cause: Throwable) {
+ log.log(Level.WARNING, message, cause)
leastGeneration = max(configurer.getComponentsGeneration, configurer.getBootstrapGeneration) + 1
}
diff --git a/container-di/src/main/scala/com/yahoo/container/di/componentgraph/core/ComponentNode.scala b/container-di/src/main/scala/com/yahoo/container/di/componentgraph/core/ComponentNode.scala
index 16856930e54..e689b7b7b3d 100644
--- a/container-di/src/main/scala/com/yahoo/container/di/componentgraph/core/ComponentNode.scala
+++ b/container-di/src/main/scala/com/yahoo/container/di/componentgraph/core/ComponentNode.scala
@@ -99,19 +99,19 @@ class ComponentNode(componentId: ComponentId,
constructor.newInstance(actualArguments: _*)
} catch {
case e: InvocationTargetException =>
- throw removeStackTrace(constructThrowable(cutStackTraceAtConstructor(e.getCause), s"Error constructing $idAndType"))
+ throw removeStackTrace(ErrorOrComponentConstructorException(cutStackTraceAtConstructor(e.getCause), s"Error constructing $idAndType"))
}
initId(instance)
}
- private def constructThrowable(cause: Throwable, message: String) : Throwable = {
+ private def ErrorOrComponentConstructorException(cause: Throwable, message: String) : Throwable = {
if (cause != null && cause.isInstanceOf[Error]) // don't convert Errors to RuntimeExceptions
new Error(message, cause)
else
- new RuntimeException(message, cause)
+ new ComponentConstructorException(message, cause)
}
-
+
private def initId(component: AnyRef) = {
def checkAndSetId(c: AbstractComponent) {
if (c.hasInitializedId && c.getId != componentId )
@@ -180,7 +180,7 @@ object ComponentNode {
publicConstructors filter {_.getAnnotation(classOf[Inject]) != null} match {
case Array() => None
case Array(single) => Some(single)
- case _ => throwRuntimeExceptionRemoveStackTrace("Multiple constructors annotated with inject in class " + clazz.getName)
+ case _ => throwComponentConstructorException("Multiple constructors annotated with inject in class " + clazz.getName)
}
}
@@ -188,7 +188,7 @@ object ComponentNode {
def isConfigInstance(clazz: Class[_]) = classOf[ConfigInstance].isAssignableFrom(clazz)
publicConstructors match {
- case Array() => throwRuntimeExceptionRemoveStackTrace("No public constructors in class " + clazz.getName)
+ case Array() => throwComponentConstructorException("No public constructors in class " + clazz.getName)
case Array(single) => single
case _ =>
log.warning("Multiple public constructors found in class %s, there should only be one. ".format(clazz.getName) +
@@ -202,9 +202,12 @@ object ComponentNode {
constructorAnnotatedWithInject getOrElse constructorWithMostConfigParameters
}
- private def throwRuntimeExceptionRemoveStackTrace(message: String) =
- throw removeStackTrace(new RuntimeException(message))
+ private def throwComponentConstructorException(message: String) =
+ throw removeStackTrace(new ComponentConstructorException(message))
+ class ComponentConstructorException(message: String, cause: Throwable) extends RuntimeException(message, cause) {
+ def this(message: String) = this(message, null)
+ }
def isAbstract(clazz: Class[_ <: AnyRef]) = Modifier.isAbstract(clazz.getModifiers)
}