diff --git a/akka-actors/src/main/scala/actor/Supervisor.scala b/akka-actors/src/main/scala/actor/Supervisor.scala index a84779a917..e2c5e92ac2 100644 --- a/akka-actors/src/main/scala/actor/Supervisor.scala +++ b/akka-actors/src/main/scala/actor/Supervisor.scala @@ -23,7 +23,7 @@ case class OneForOneStrategy(maxNrOfRetries: Int, withinTimeRange: Int) extends *
  *  val factory = SupervisorFactory(
  *    SupervisorConfig(
- *      RestartStrategy(OneForOne, 3, 10),
+ *      RestartStrategy(OneForOne, 3, 10, List(classOf[Exception]),
  *      Supervise(
  *        myFirstActor,
  *        LifeCycle(Permanent)) ::
@@ -43,6 +43,7 @@ case class OneForOneStrategy(maxNrOfRetries: Int, withinTimeRange: Int) extends
  * @author Jonas Bonér
  */
 class SupervisorFactory(val config: SupervisorConfig) extends Logging {
+  type ExceptionList = List[Class[_ <: Throwable]]
 
   def newInstance: Supervisor = newInstanceFor(config)
 
@@ -55,10 +56,10 @@ class SupervisorFactory(val config: SupervisorConfig) extends Logging {
   }
 
   protected def create(strategy: RestartStrategy): Supervisor = strategy match {
-    case RestartStrategy(scheme, maxNrOfRetries, timeRange) =>
+    case RestartStrategy(scheme, maxNrOfRetries, timeRange, trapExceptions: ExceptionList) =>
       scheme match {
-        case AllForOne => new Supervisor(AllForOneStrategy(maxNrOfRetries, timeRange))
-        case OneForOne => new Supervisor(OneForOneStrategy(maxNrOfRetries, timeRange))
+        case AllForOne => new Supervisor(AllForOneStrategy(maxNrOfRetries, timeRange), trapExceptions)
+        case OneForOne => new Supervisor(OneForOneStrategy(maxNrOfRetries, timeRange), trapExceptions)
       }
   }
 }
@@ -79,21 +80,21 @@ object SupervisorFactory {
  *
  * @author Jonas Bonér
  */                                  
-sealed class Supervisor private[akka] (handler: FaultHandlingStrategy)
-  extends Actor with Logging with Configurator {  
-  trapExit = List(classOf[Throwable])
+sealed class Supervisor private[akka] (handler: FaultHandlingStrategy, trapExceptions: List[Class[_ <: Throwable]])
+  extends Actor with Logging with Configurator {
+  
+  trapExit = trapExceptions
   faultHandler = Some(handler)
   dispatcher = Dispatchers.newThreadBasedDispatcher(this)
 
-  val actors = new ConcurrentHashMap[String, Actor]
+  private val actors = new ConcurrentHashMap[String, Actor]
   
+  // Cheating, should really go through the dispatcher rather than direct access to a CHM
   def getInstance[T](clazz: Class[T]) = actors.get(clazz.getName).asInstanceOf[T]
-
   def getComponentInterfaces: List[Class[_]] = actors.values.toArray.toList.map(_.getClass)
-
   def isDefined(clazz: Class[_]): Boolean = actors.containsKey(clazz.getName)
 
-  override def start = synchronized {
+  override def start: Actor = synchronized {
     ConfiguratorRepository.registerConfigurator(this)
     getLinkedActors.toArray.toList.asInstanceOf[List[Actor]].foreach { actor =>
       actor.start
@@ -112,7 +113,7 @@ sealed class Supervisor private[akka] (handler: FaultHandlingStrategy)
   }
 
   def receive = {
-    case unknown => throw new IllegalArgumentException("Supervisor does not respond to any messages. Unknown message [" + unknown + "]")
+    case unknown => throw new IllegalArgumentException("Supervisor " + toString + " does not respond to any messages. Unknown message [" + unknown + "]")
   }
 
   def configure(config: SupervisorConfig, factory: SupervisorFactory) = config match {
@@ -124,9 +125,11 @@ sealed class Supervisor private[akka] (handler: FaultHandlingStrategy)
             actor.lifeCycle = Some(lifeCycle)
             startLink(actor)
 
-           case SupervisorConfig(_, _) => // recursive configuration
-             factory.newInstanceFor(server.asInstanceOf[SupervisorConfig]).start
-             // FIXME what to do with recursively supervisors?
+           case supervisorConfig @ SupervisorConfig(_, _) => // recursive supervisor configuration
+             val supervisor = factory.newInstanceFor(supervisorConfig).start
+             supervisor.lifeCycle = Some(LifeCycle(Permanent))
+             actors.put(supervisor.getClass.getName, supervisor)
+             link(supervisor)
         })
   }
 }
diff --git a/akka-actors/src/main/scala/config/Config.scala b/akka-actors/src/main/scala/config/Config.scala
index be6c9de707..136725cadd 100644
--- a/akka-actors/src/main/scala/config/Config.scala
+++ b/akka-actors/src/main/scala/config/Config.scala
@@ -22,7 +22,11 @@ object ScalaConfig {
   case class SupervisorConfig(restartStrategy: RestartStrategy, worker: List[Server]) extends Server
   case class Supervise(actor: Actor, lifeCycle: LifeCycle) extends Server
 
-  case class RestartStrategy(scheme: FailOverScheme, maxNrOfRetries: Int, withinTimeRange: Int) extends ConfigElement
+  case class RestartStrategy(
+      scheme: FailOverScheme,
+      maxNrOfRetries: Int,
+      withinTimeRange: Int,
+      trapExceptions: List[Class[_ <: Throwable]]) extends ConfigElement
 
   case object AllForOne extends FailOverScheme
   case object OneForOne extends FailOverScheme
@@ -114,9 +118,10 @@ object JavaConfig {
   class RestartStrategy(
       @BeanProperty val scheme: FailOverScheme,
       @BeanProperty val maxNrOfRetries: Int,
-      @BeanProperty val withinTimeRange: Int) extends ConfigElement {
+      @BeanProperty val withinTimeRange: Int,
+      @BeanProperty val trapExceptions: Array[Class[_ <: Throwable]]) extends ConfigElement {
     def transform = se.scalablesolutions.akka.config.ScalaConfig.RestartStrategy(
-      scheme.transform, maxNrOfRetries, withinTimeRange)
+      scheme.transform, maxNrOfRetries, withinTimeRange, trapExceptions.toList)
   }
   
   class LifeCycle(@BeanProperty val scope: Scope, @BeanProperty val callbacks: RestartCallbacks) extends ConfigElement {
diff --git a/akka-actors/src/test/scala/RemoteSupervisorTest.scala b/akka-actors/src/test/scala/RemoteSupervisorTest.scala
index 0fef2a2e6e..719c88359f 100644
--- a/akka-actors/src/test/scala/RemoteSupervisorTest.scala
+++ b/akka-actors/src/test/scala/RemoteSupervisorTest.scala
@@ -471,7 +471,7 @@ class RemoteSupervisorTest extends JUnitSuite {
 
     val factory = SupervisorFactory(
       SupervisorConfig(
-        RestartStrategy(AllForOne, 3, 100),
+        RestartStrategy(AllForOne, 3, 100, List(classOf[Exception])),
         Supervise(
           pingpong1,
           LifeCycle(Permanent))
@@ -486,7 +486,7 @@ class RemoteSupervisorTest extends JUnitSuite {
 
     val factory = SupervisorFactory(
       SupervisorConfig(
-        RestartStrategy(OneForOne, 3, 100),
+        RestartStrategy(OneForOne, 3, 100, List(classOf[Exception])),
         Supervise(
           pingpong1,
           LifeCycle(Permanent))
@@ -504,7 +504,7 @@ class RemoteSupervisorTest extends JUnitSuite {
 
     val factory = SupervisorFactory(
       SupervisorConfig(
-        RestartStrategy(AllForOne, 3, 100),
+        RestartStrategy(AllForOne, 3, 100, List(classOf[Exception])),
         Supervise(
           pingpong1,
           LifeCycle(Permanent))
@@ -530,7 +530,7 @@ class RemoteSupervisorTest extends JUnitSuite {
 
     val factory = SupervisorFactory(
       SupervisorConfig(
-        RestartStrategy(OneForOne, 3, 100),
+        RestartStrategy(OneForOne, 3, 100, List(classOf[Exception])),
         Supervise(
           pingpong1,
           LifeCycle(Permanent))
@@ -556,13 +556,13 @@ class RemoteSupervisorTest extends JUnitSuite {
 
     val factory = SupervisorFactory(
       SupervisorConfig(
-        RestartStrategy(AllForOne, 3, 100),
+        RestartStrategy(AllForOne, 3, 100, List(classOf[Exception])),
         Supervise(
           pingpong1,
           LifeCycle(Permanent))
             ::
             SupervisorConfig(
-              RestartStrategy(AllForOne, 3, 100),
+              RestartStrategy(AllForOne, 3, 100, List(classOf[Exception])),
               Supervise(
                 pingpong2,
                 LifeCycle(Permanent))
diff --git a/akka-actors/src/test/scala/SupervisorTest.scala b/akka-actors/src/test/scala/SupervisorTest.scala
index b143ef21e7..699b260301 100644
--- a/akka-actors/src/test/scala/SupervisorTest.scala
+++ b/akka-actors/src/test/scala/SupervisorTest.scala
@@ -457,7 +457,7 @@ class SupervisorTest extends JUnitSuite {
     
     val factory = SupervisorFactory(
         SupervisorConfig(
-          RestartStrategy(AllForOne, 3, 100),
+          RestartStrategy(AllForOne, 3, 100, List(classOf[Exception])),
           Supervise(
             pingpong1,
             LifeCycle(Permanent))
@@ -470,7 +470,7 @@ class SupervisorTest extends JUnitSuite {
 
     val factory = SupervisorFactory(
         SupervisorConfig(
-          RestartStrategy(OneForOne, 3, 100),
+          RestartStrategy(OneForOne, 3, 100, List(classOf[Exception])),
           Supervise(
             pingpong1,
             LifeCycle(Permanent))
@@ -485,7 +485,7 @@ class SupervisorTest extends JUnitSuite {
 
     val factory = SupervisorFactory(
         SupervisorConfig(
-          RestartStrategy(AllForOne, 3, 100),
+          RestartStrategy(AllForOne, 3, 100, List(classOf[Exception])),
           Supervise(
             pingpong1,
             LifeCycle(Permanent))
@@ -508,7 +508,7 @@ class SupervisorTest extends JUnitSuite {
 
     val factory = SupervisorFactory(
         SupervisorConfig(
-          RestartStrategy(OneForOne, 3, 100),
+          RestartStrategy(OneForOne, 3, 100, List(classOf[Exception])),
           Supervise(
             pingpong1,
             LifeCycle(Permanent))
@@ -531,13 +531,13 @@ class SupervisorTest extends JUnitSuite {
 
     val factory = SupervisorFactory(
         SupervisorConfig(
-          RestartStrategy(AllForOne, 3, 100),
+          RestartStrategy(AllForOne, 3, 100, List(classOf[Exception])),
           Supervise(
             pingpong1,
             LifeCycle(Permanent))
           ::
           SupervisorConfig(
-            RestartStrategy(AllForOne, 3, 100),
+            RestartStrategy(AllForOne, 3, 100, List(classOf[Exception])),
             Supervise(
               pingpong2,
               LifeCycle(Permanent))
diff --git a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/ActiveObjectGuiceConfiguratorTest.java b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/ActiveObjectGuiceConfiguratorTest.java
index 82347669c1..61ef403f7b 100644
--- a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/ActiveObjectGuiceConfiguratorTest.java
+++ b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/ActiveObjectGuiceConfiguratorTest.java
@@ -37,7 +37,8 @@ public class ActiveObjectGuiceConfiguratorTest extends TestCase {
         bind(Ext.class).to(ExtImpl.class).in(Scopes.SINGLETON);
       }
     }).configure(
-        new RestartStrategy(new AllForOne(), 3, 5000), new Component[]{
+        new RestartStrategy(new AllForOne(), 3, 5000, new Class[]{Exception.class}),
+        new Component[]{
              new Component(
                 Foo.class,
                 new LifeCycle(new Permanent()),
diff --git a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemNestedStateTest.java b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemNestedStateTest.java
index 26c6747eca..825d8f39fa 100644
--- a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemNestedStateTest.java
+++ b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemNestedStateTest.java
@@ -19,7 +19,7 @@ public class InMemNestedStateTest extends TestCase {
 
   public InMemNestedStateTest() {
     conf.configure(
-        new RestartStrategy(new AllForOne(), 3, 5000),
+        new RestartStrategy(new AllForOne(), 3, 5000, new Class[]{Exception.class}),
         new Component[]{
             // FIXME: remove string-name, add ctor to only accept target class
             new Component(InMemStateful.class, new LifeCycle(new Permanent()), 10000000),
diff --git a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemoryStateTest.java b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemoryStateTest.java
index e29e8ef81f..973ac14b6b 100644
--- a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemoryStateTest.java
+++ b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemoryStateTest.java
@@ -23,7 +23,7 @@ public class InMemoryStateTest extends TestCase {
   public InMemoryStateTest() {
     Config.config();
     conf.configure(
-        new RestartStrategy(new AllForOne(), 3, 5000),
+        new RestartStrategy(new AllForOne(), 3, 5000, new Class[] {Exception.class}),
         new Component[]{
             new Component(InMemStateful.class,
                 new LifeCycle(new Permanent()),
diff --git a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentNestedStateTest.java b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentNestedStateTest.java
index 0dcb4ec992..4c74a8b1a2 100644
--- a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentNestedStateTest.java
+++ b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentNestedStateTest.java
@@ -20,7 +20,7 @@ public class PersistentNestedStateTest extends TestCase {
   protected void setUp() {
       PersistenceManager.init();
     conf.configure(
-        new RestartStrategy(new AllForOne(), 3, 5000),
+        new RestartStrategy(new AllForOne(), 3, 5000, new Class[] {Exception.class}),
         new Component[]{
             // FIXME: remove string-name, add ctor to only accept target class
             new Component(PersistentStateful.class, new LifeCycle(new Permanent()), 10000000),
diff --git a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentStateTest.java b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentStateTest.java
index 23f8eb1070..b8f6d7eb3e 100644
--- a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentStateTest.java
+++ b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentStateTest.java
@@ -17,7 +17,7 @@ public class PersistentStateTest extends TestCase {
   protected void setUp() {
     PersistenceManager.init();
     conf.configure(
-        new RestartStrategy(new AllForOne(), 3, 5000),
+        new RestartStrategy(new AllForOne(), 3, 5000, new Class[] {Exception.class}),
         new Component[] {
           new Component(PersistentStateful.class, new LifeCycle(new Permanent()), 10000000),
           new Component(PersistentFailer.class, new LifeCycle(new Permanent()), 1000)
diff --git a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/RemotePersistentStateTest.java b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/RemotePersistentStateTest.java
index 9568d6a6f1..06573759f1 100644
--- a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/RemotePersistentStateTest.java
+++ b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/RemotePersistentStateTest.java
@@ -17,7 +17,7 @@ public class RemotePersistentStateTest extends TestCase {
   protected void setUp() {
     PersistenceManager.init();
     conf.configure(
-        new RestartStrategy(new AllForOne(), 3, 5000),
+        new RestartStrategy(new AllForOne(), 3, 5000, new Class[]{Exception.class}),
         new Component[] {
           new Component(PersistentStateful.class, new LifeCycle(new Permanent()), 1000000, new RemoteAddress("localhost", 9999)),
           new Component(PersistentFailer.class, new LifeCycle(new Permanent()), 1000000, new RemoteAddress("localhost", 9999))
diff --git a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/RestTest.java b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/RestTest.java
index b6d6ef06dc..4eb17ce7e6 100644
--- a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/RestTest.java
+++ b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/RestTest.java
@@ -32,7 +32,7 @@ public class RestTest extends TestCase {
   @BeforeClass
   protected void setUp() {
     conf.configure(
-        new RestartStrategy(new AllForOne(), 3, 5000),
+        new RestartStrategy(new AllForOne(), 3, 5000, new Class[]{Exception.class}),
         new Component[] {
           new Component(
               JerseyFoo.class,
diff --git a/akka-samples-java/src/main/java/sample/java/Boot.java b/akka-samples-java/src/main/java/sample/java/Boot.java
index 55a3de1c1f..888344013d 100644
--- a/akka-samples-java/src/main/java/sample/java/Boot.java
+++ b/akka-samples-java/src/main/java/sample/java/Boot.java
@@ -8,7 +8,7 @@ public class Boot {
 
   public Boot() throws Exception  {
     manager.configure(
-      new RestartStrategy(new OneForOne(), 3, 5000),
+      new RestartStrategy(new OneForOne(), 3, 5000, new Class[]{Exception.class}),
         new Component[] {
           new Component(
             sample.java.SimpleService.class,
diff --git a/akka-samples-lift/src/main/scala/bootstrap/liftweb/Boot.scala b/akka-samples-lift/src/main/scala/bootstrap/liftweb/Boot.scala
index 553d90b277..b6098cfb3c 100644
--- a/akka-samples-lift/src/main/scala/bootstrap/liftweb/Boot.scala
+++ b/akka-samples-lift/src/main/scala/bootstrap/liftweb/Boot.scala
@@ -38,7 +38,7 @@ class Boot {
     
     val factory = SupervisorFactory(
       SupervisorConfig(
-        RestartStrategy(OneForOne, 3, 100),
+        RestartStrategy(OneForOne, 3, 100, List(classOf[Exception])),
         Supervise(
           new SimpleService,
           LifeCycle(Permanent)) ::
diff --git a/akka-samples-scala/src/main/scala/SimpleService.scala b/akka-samples-scala/src/main/scala/SimpleService.scala
index e5642171b7..a1f5e87575 100644
--- a/akka-samples-scala/src/main/scala/SimpleService.scala
+++ b/akka-samples-scala/src/main/scala/SimpleService.scala
@@ -20,7 +20,7 @@ import org.atmosphere.cpr.BroadcastFilter
 class Boot {
   val factory = SupervisorFactory(
     SupervisorConfig(
-      RestartStrategy(OneForOne, 3, 100),
+      RestartStrategy(OneForOne, 3, 100, List(classOf[Exception])),
       Supervise(
         new SimpleService,
         LifeCycle(Permanent)) ::
diff --git a/akka-samples-security/src/main/scala/SimpleService.scala b/akka-samples-security/src/main/scala/SimpleService.scala
index cca4246933..fc8b18367a 100644
--- a/akka-samples-security/src/main/scala/SimpleService.scala
+++ b/akka-samples-security/src/main/scala/SimpleService.scala
@@ -13,7 +13,7 @@ import se.scalablesolutions.akka.state.TransactionalState
 class Boot {
   val factory = SupervisorFactory(
     SupervisorConfig(
-      RestartStrategy(OneForOne, 3, 100),
+      RestartStrategy(OneForOne, 3, 100, List(classOf[Exception])),
       // Dummy implementations of all authentication actors
       // see akka.conf to enable one of these for the AkkaSecurityFilterFactory
       Supervise(