update core event protocol

buko [2003-10-26 21:38:41]
update core event protocol
Filename
aether2/core/aether-core.ipr
aether2/core/aether-core.iws
aether2/core/src/java/aether/event/Message.java
aether2/hercules/hercules.iws
aether2/hercules/src/java/aether/server/DefaultThreadPool.java
aether2/hercules/src/java/aether/server/ManagedPublisher.java
aether2/hercules/src/java/aether/server/ThreadPool.java
aether2/hercules/src/java/aether/server/responder/DefaultSwitchBoard.java
aether2/hercules/src/java/aether/server/responder/RequestExecutor.java
aether2/hercules/src/java/aether/server/responder/Responder.java
aether2/hercules/src/java/aether/server/responder/SwitchBoard.java
aether2/hercules/src/java/aether/server/responder/SwitchboardNotificationListener.java
aether2/hercules/src/java/memento/world/manager/WorldController.java
aether2/hercules/src/test/aether/server/PublisherProviderTest.java
aether2/hercules/src/test/aether/server/ThreadPoolProviderTest.java
aether2/hercules/src/test/aether/server/domain/DomainAgentTest.java
aether2/hercules/src/test/aether/server/domain/RemoteDomainAgentTest.java
aether2/hercules/src/test/memento/world/manager/WorldManagerTest.java
aether2/lib/aether-core-0.1.jar
diff --git a/aether2/core/aether-core.ipr b/aether2/core/aether-core.ipr
index b3f852e..3369351 100644
--- a/aether2/core/aether-core.ipr
+++ b/aether2/core/aether-core.ipr
@@ -76,7 +76,7 @@
       <maximumHeapSize value="128" />
       <viewClosedWhenNoErrors value="false" />
       <additionalClassPath>
-        <entry path="file://file://file://$PROJECT_DIR$/../../common-lib/junit.jar" />
+        <entry path="file://file://file://file://file://$PROJECT_DIR$/../../common-lib/junit.jar" />
       </additionalClassPath>
       <targetFilters>
         <filter targetName="init" isVisible="false" />
diff --git a/aether2/core/aether-core.iws b/aether2/core/aether-core.iws
index 1df1ba6..3da2614 100644
--- a/aether2/core/aether-core.iws
+++ b/aether2/core/aether-core.iws
@@ -4,17 +4,9 @@
     <history>
       <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/event/SimpleEventQueue.java" line="0" column="24" vertical-scroll-proportion="0.0" horizontal-scroll-proportion="0.37086093" />
       <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/event/BlockingEventQueue.java" line="11" column="13" vertical-scroll-proportion="0.33212996" horizontal-scroll-proportion="0.200883" />
-      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/net/AbstractConnection.java" line="2" column="26" vertical-scroll-proportion="0.07317073" horizontal-scroll-proportion="0.2524272">
-        <folding>
-          <element signature="imports" expanded="true" />
-        </folding>
-      </source-position-entry>
+      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/net/AbstractConnection.java" line="2" column="26" vertical-scroll-proportion="0.07317073" horizontal-scroll-proportion="0.2524272" />
       <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/net/Link.java" line="53" column="54" vertical-scroll-proportion="0.4512195" horizontal-scroll-proportion="0.52427185" />
-      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/net/AbstractLink.java" line="252" column="51" vertical-scroll-proportion="0.9268293" horizontal-scroll-proportion="0.49514562">
-        <folding>
-          <element signature="imports" expanded="true" />
-        </folding>
-      </source-position-entry>
+      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/net/AbstractLink.java" line="252" column="51" vertical-scroll-proportion="0.9268293" horizontal-scroll-proportion="0.49514562" />
       <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/net/DefaultLink.java" line="15" column="13" vertical-scroll-proportion="0.5487805" horizontal-scroll-proportion="0.1262136" />
       <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/net/Connection.java" line="11" column="17" vertical-scroll-proportion="-0.10627177" horizontal-scroll-proportion="0.16504854" />
       <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/net/Publisher.java" line="12" column="17" vertical-scroll-proportion="0.36585367" horizontal-scroll-proportion="0.16504854" />
@@ -22,18 +14,17 @@
       <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/net/AbstractMonitor.java" line="260" column="40" vertical-scroll-proportion="0.9602888" horizontal-scroll-proportion="0.3883495" />
       <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/net/DefaultConnection.java" line="8" column="25" vertical-scroll-proportion="0.028880866" horizontal-scroll-proportion="0.24271844" />
       <source-position-entry url="file://$PROJECT_DIR$/.cvsignore" line="6" column="15" vertical-scroll-proportion="0.22743683" horizontal-scroll-proportion="0.14563107" />
-      <source-position-entry url="file://$PROJECT_DIR$/build.xml" line="71" column="0" vertical-scroll-proportion="2.5278745" horizontal-scroll-proportion="0.0" />
-      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/event/Request.java" line="12" column="65" vertical-scroll-proportion="0.33275262" horizontal-scroll-proportion="0.63106793" />
-      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/event/Message.java" line="18" column="47" vertical-scroll-proportion="0.29616725" horizontal-scroll-proportion="0.4563107" />
+      <source-position-entry url="file://$PROJECT_DIR$/build.xml" line="71" column="0" vertical-scroll-proportion="2.597561" horizontal-scroll-proportion="0.0" />
+      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/event/Message.java" line="1" column="92" vertical-scroll-proportion="0.036585364" horizontal-scroll-proportion="0.89196676" />
+      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/event/Request.java" line="35" column="1" vertical-scroll-proportion="0.40592334" horizontal-scroll-proportion="0.009695291" />
     </history>
     <open-files>
-      <source-position-entry url="file://$PROJECT_DIR$/build.xml" line="71" column="0" vertical-scroll-proportion="2.5278745" horizontal-scroll-proportion="0.0" />
-      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/event/Request.java" line="12" column="65" vertical-scroll-proportion="0.33275262" horizontal-scroll-proportion="0.63106793" />
-      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/event/Message.java" line="18" column="47" vertical-scroll-proportion="0.29616725" horizontal-scroll-proportion="0.4563107" selected="true" />
+      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/event/Message.java" line="1" column="92" vertical-scroll-proportion="0.036585364" horizontal-scroll-proportion="0.89196676" />
+      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/event/Request.java" line="35" column="1" vertical-scroll-proportion="0.40592334" horizontal-scroll-proportion="0.009695291" selected="true" />
     </open-files>
   </component>
   <component name="ToolWindowManager">
-    <frame x="65" y="12" width="834" height="719" extended-state="0" />
+    <frame x="65" y="12" width="835" height="719" extended-state="0" />
     <editor active="true" />
     <layout>
       <window_info id="Ant Build" active="false" anchor="right" auto_hide="true" internal_type="docked" type="docked" visible="false" weight="0.25" order="1" />
@@ -42,7 +33,7 @@
       <window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.25" order="2" />
       <window_info id="TODO" active="false" anchor="bottom" auto_hide="true" internal_type="docked" type="docked" visible="false" weight="0.32991204" order="7" />
       <window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="sliding" type="sliding" visible="false" weight="0.4004065" order="0" />
-      <window_info id="Project" active="false" anchor="left" auto_hide="true" internal_type="docked" type="docked" visible="false" weight="0.33375636" order="0" />
+      <window_info id="Project" active="false" anchor="left" auto_hide="true" internal_type="docked" type="docked" visible="false" weight="0.33333334" order="0" />
       <window_info id="Debug" active="false" anchor="bottom" auto_hide="true" internal_type="docked" type="docked" visible="false" weight="0.40029326" order="3" />
       <window_info id="Structure" active="false" anchor="left" auto_hide="true" internal_type="docked" type="docked" visible="false" weight="0.25" order="1" />
       <window_info id="Find" active="false" anchor="bottom" auto_hide="true" internal_type="docked" type="docked" visible="false" weight="0.32961783" order="1" />
@@ -255,7 +246,10 @@
   <component name="ProjectViewSettings">
     <navigator currentView="ProjectPane" flattenPackages="true" showMembers="false" showStructure="false" autoscrollToSource="false" splitterProportion="0.5" />
     <view id="ProjectPane">
+      <expanded_node type="directory" url="file://$PROJECT_DIR$/src" />
+      <expanded_node type="directory" url="file://$PROJECT_DIR$/src/java" />
       <expanded_node type="directory" url="file://$PROJECT_DIR$" />
+      <expanded_node type="directory" url="file://$PROJECT_DIR$/src/java/aether/event" />
     </view>
     <view id="SourcepathPane" />
     <view id="ClasspathPane" />
diff --git a/aether2/core/src/java/aether/event/Message.java b/aether2/core/src/java/aether/event/Message.java
index 8ac731c..5aa7d8a 100644
--- a/aether2/core/src/java/aether/event/Message.java
+++ b/aether2/core/src/java/aether/event/Message.java
@@ -58,9 +58,10 @@ public abstract class Message extends Event implements Attribute.Message
 	 * Construct a Subscription indicating that a component wants to receive
 	 * messages sent to a certain destination.
 	 *
-	 * @param dest DESTINATION to subscribe to
+	 * @param dest destination to subscribe to (this may be either a GUID or a
+     *             URL)
 	 */
-	public static Subscription createSubForDestination(String dest)
+	public static Subscription createSubscriptionForDestination(String dest)
 	{
 		if (dest == null)
 		{
diff --git a/aether2/hercules/hercules.iws b/aether2/hercules/hercules.iws
index 1e0f9f1..70daa8c 100644
--- a/aether2/hercules/hercules.iws
+++ b/aether2/hercules/hercules.iws
@@ -2,30 +2,45 @@
 <project version="3" relativePaths="false">
   <component name="FileEditorManager">
     <history>
-      <source-position-entry url="file://$PROJECT_DIR$/.cvsignore" line="5" column="5" vertical-scroll-proportion="0.18292683" horizontal-scroll-proportion="0.048476454" />
-      <source-position-entry url="file://$PROJECT_DIR$/build.xml" line="0" column="0" vertical-scroll-proportion="0.0" horizontal-scroll-proportion="0.0" />
-      <source-position-entry url="file://$PROJECT_DIR$/src/java/memento/world/model/Sector.java" line="13" column="38" vertical-scroll-proportion="0.0" horizontal-scroll-proportion="0.36893204" />
-      <source-position-entry url="file://$PROJECT_DIR$/src/java/memento/world/model/LocatableWorldObject.java" line="0" column="27" vertical-scroll-proportion="0.0" horizontal-scroll-proportion="0.26213592" />
-      <source-position-entry url="file://$PROJECT_DIR$/src/java/memento/world/model/Portal.java" line="36" column="5" vertical-scroll-proportion="0.6570397" horizontal-scroll-proportion="0.048543688" />
-      <source-position-entry url="file://$PROJECT_DIR$/src/java/memento/world/model/WorldModel.java" line="13" column="19" vertical-scroll-proportion="0.33275262" horizontal-scroll-proportion="0.18446602">
-        <folding>
-          <element signature="imports" expanded="true" />
-        </folding>
-      </source-position-entry>
-      <source-position-entry url="file://$PROJECT_DIR$/src/java/memento/world/model/Avatar.java" line="17" column="20" vertical-scroll-proportion="0.6219512" horizontal-scroll-proportion="0.19417475" />
-      <source-position-entry url="file://$PROJECT_DIR$/src/java/memento/world/model/WorldObject.java" line="8" column="13" vertical-scroll-proportion="0.2595819" horizontal-scroll-proportion="0.1262136" />
-      <source-position-entry url="file://$PROJECT_DIR$/src/java/memento/world/model/WorldAdvertisement.java" line="10" column="48" vertical-scroll-proportion="0.23170732" horizontal-scroll-proportion="0.46601942" />
       <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/server/domain/Advertisement.java" line="12" column="13" vertical-scroll-proportion="-1.7090592" horizontal-scroll-proportion="0.1262136" />
       <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/server/AetherContainer.java" line="14" column="27" vertical-scroll-proportion="0.40243903" horizontal-scroll-proportion="0.26213592" />
       <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/server/ConnectionFactory.java" line="22" column="48" vertical-scroll-proportion="0.73170733" horizontal-scroll-proportion="0.46601942" />
       <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/server/DefaultConnectionFactory.java" line="41" column="41" vertical-scroll-proportion="0.869338" horizontal-scroll-proportion="0.39805827" />
-      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/server/core/DefaultConnectionProvider.java" line="92" column="11" vertical-scroll-proportion="0.2682927" horizontal-scroll-proportion="0.106796116" />
+      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/server/DefaultThreadPool.java" line="42" column="13" vertical-scroll-proportion="0.07317073" horizontal-scroll-proportion="0.26686218" />
+      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/server/ThreadPool.java" line="8" column="17" vertical-scroll-proportion="0.29268292" horizontal-scroll-proportion="0.3489736" />
+      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/server/responder/SwitchBoard.java" line="1" column="0" vertical-scroll-proportion="0.037906136" horizontal-scroll-proportion="0.0" />
+      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/server/ManagedPublisher.java" line="50" column="39" vertical-scroll-proportion="-1.4638989" horizontal-scroll-proportion="0.37811634" />
+      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/server/responder/SwitchBoardListener.java" line="17" column="36" vertical-scroll-proportion="0.4512195" horizontal-scroll-proportion="0.34903046" />
+      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/server/responder/SwitchBoardEvent.java" line="10" column="13" vertical-scroll-proportion="-1.304878" horizontal-scroll-proportion="0.12603877" />
+      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/server/responder/RuntimeResponderException.java" line="9" column="13" vertical-scroll-proportion="0.101045296" horizontal-scroll-proportion="0.12603877" />
+      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/server/responder/Responder.java" line="32" column="34" vertical-scroll-proportion="0.6707317" horizontal-scroll-proportion="0.32963988">
+        <folding>
+          <element signature="imports" expanded="true" />
+        </folding>
+      </source-position-entry>
+      <source-position-entry url="file://$PROJECT_DIR$/.cvsignore" line="0" column="0" vertical-scroll-proportion="0.0" horizontal-scroll-proportion="0.0" />
+      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/server/responder/DefaultSwitchBoard.java" line="134" column="75" vertical-scroll-proportion="4.902439" horizontal-scroll-proportion="0.7271468">
+        <folding>
+          <element signature="imports" expanded="true" />
+        </folding>
+      </source-position-entry>
     </history>
-    <open-files />
+    <open-files>
+      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/server/responder/Responder.java" line="32" column="34" vertical-scroll-proportion="0.6707317" horizontal-scroll-proportion="0.32963988">
+        <folding>
+          <element signature="imports" expanded="true" />
+        </folding>
+      </source-position-entry>
+      <source-position-entry url="file://$PROJECT_DIR$/src/java/aether/server/responder/DefaultSwitchBoard.java" line="134" column="75" vertical-scroll-proportion="4.902439" horizontal-scroll-proportion="0.7271468" selected="true">
+        <folding>
+          <element signature="imports" expanded="true" />
+        </folding>
+      </source-position-entry>
+    </open-files>
   </component>
   <component name="ToolWindowManager">
-    <frame x="111" y="11" width="834" height="719" extended-state="0" />
-    <editor active="false" />
+    <frame x="155" y="9" width="835" height="719" extended-state="0" />
+    <editor active="true" />
     <layout>
       <window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.25" order="1" />
       <window_info id="Cvs" active="false" anchor="bottom" auto_hide="true" internal_type="docked" type="docked" visible="false" weight="0.4968153" order="5" />
@@ -33,7 +48,7 @@
       <window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.25" order="2" />
       <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.32961783" order="7" />
       <window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="sliding" type="sliding" visible="false" weight="0.4" order="0" />
-      <window_info id="Project" active="true" anchor="left" auto_hide="true" internal_type="docked" type="docked" visible="true" weight="0.4758883" order="0" />
+      <window_info id="Project" active="false" anchor="left" auto_hide="true" internal_type="docked" type="docked" visible="false" weight="0.47528517" order="0" />
       <window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.4" order="3" />
       <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.25" order="1" />
       <window_info id="Find" active="false" anchor="bottom" auto_hide="true" internal_type="docked" type="docked" visible="false" weight="0.32961783" order="1" />
@@ -247,10 +262,9 @@
     <navigator currentView="ProjectPane" flattenPackages="false" showMembers="false" showStructure="false" autoscrollToSource="false" splitterProportion="0.5" />
     <view id="ProjectPane">
       <expanded_node type="directory" url="file://$PROJECT_DIR$/src/java/aether/server" />
-      <expanded_node type="directory" url="file://$PROJECT_DIR$/src/java/aether" />
       <expanded_node type="directory" url="file://$PROJECT_DIR$/src/java" />
-      <expanded_node type="directory" url="file://$PROJECT_DIR$/src/java/aether/server/core" />
       <expanded_node type="directory" url="file://$PROJECT_DIR$" />
+      <expanded_node type="directory" url="file://$PROJECT_DIR$/src/java/aether" />
       <expanded_node type="directory" url="file://$PROJECT_DIR$/src" />
     </view>
     <view id="SourcepathPane" />
diff --git a/aether2/hercules/src/java/aether/server/DefaultThreadPool.java b/aether2/hercules/src/java/aether/server/DefaultThreadPool.java
new file mode 100644
index 0000000..48776c9
--- /dev/null
+++ b/aether2/hercules/src/java/aether/server/DefaultThreadPool.java
@@ -0,0 +1,98 @@
+package aether.server;
+
+import net.concedere.dundee.DefaultComponent;
+import net.concedere.dundee.ComponentException;
+import net.concedere.dundee.framework.Disposable;
+import net.concedere.dundee.framework.Startable;
+import net.concedere.dundee.framework.Initializable;
+import EDU.oswego.cs.dl.util.concurrent.PooledExecutor;
+import EDU.oswego.cs.dl.util.concurrent.LinkedQueue;
+import org.apache.log4j.Logger;
+
+import java.beans.beancontext.BeanContextServiceProvider;
+import java.beans.beancontext.BeanContextServices;
+import java.util.Iterator;
+
+import aether.server.ThreadPool;
+
+/**
+ * Provides a threadpool component that can be aggressively tuned.
+ *
+ * @author Buko O. (buko@concedere.net)
+ * @version 0.1
+ **/
+public class DefaultThreadPool implements ThreadPool
+{
+    private int numWorkers = 5;
+    private PooledExecutor executor;
+
+    private static final Logger log =
+            Logger.getLogger(DefaultThreadPool.class);
+
+    /**
+     * Start the ThreadPool.
+     */
+    public void start()
+    {
+        // setup the threadpool
+        executor = new PooledExecutor(new LinkedQueue());
+        executor.setMinimumPoolSize(numWorkers);
+    }
+
+    /**
+     * Shutdown the ThreadPool after all currently queued tasks are completed.
+     */
+    public void shutdown()
+    {
+        executor.setMinimumPoolSize(0);
+        executor.setKeepAliveTime(10);
+        executor.shutdownAfterProcessingCurrentlyQueuedTasks();
+
+        try
+        {
+            // wait the pool to fully shutdown
+            // todo: this a bug, for some reason it takes 60 seconds if we
+            // completely wait
+            executor.awaitTerminationAfterShutdown(1000);
+            executor.shutdownNow();
+            executor = null;
+        }
+        catch (InterruptedException ie)
+        {
+            String msg = "unexpected interrupted exception!";
+            throw new Error(msg, ie);
+        }
+    }
+
+    /**
+     * Get the number of worker threads being used by the threadpool.
+     *
+     * @return number of workers being used by the pool
+     */
+    public int getNumWorkers()
+    {
+        return numWorkers;
+    }
+
+    /**
+     * Set the number of worker threads being used by the pool.
+     *
+     * @param numWorkers number of workers being used by the pool
+     */
+    public void setNumWorkers(int numWorkers)
+    {
+        this.numWorkers = numWorkers;
+    }
+
+    public void execute(Runnable work)
+    {
+        try
+        {
+            executor.execute(work);
+        }
+        catch (InterruptedException e)
+        {
+            log.warn("unexpected interrupted exception", e);
+        }
+    }
+}
diff --git a/aether2/hercules/src/java/aether/server/ManagedPublisher.java b/aether2/hercules/src/java/aether/server/ManagedPublisher.java
new file mode 100644
index 0000000..5d75868
--- /dev/null
+++ b/aether2/hercules/src/java/aether/server/ManagedPublisher.java
@@ -0,0 +1,109 @@
+package aether.server;
+
+import net.concedere.dundee.DefaultComponent;
+import net.concedere.dundee.ComponentException;
+import net.concedere.dundee.framework.Initializable;
+import net.concedere.dundee.framework.Disposable;
+import net.concedere.dundee.framework.Startable;
+import aether.net.Connection;
+import aether.net.Publisher;
+import aether.event.BlockingEventQueue;
+import aether.event.Event;
+
+import java.beans.beancontext.BeanContextServiceProvider;
+import java.beans.beancontext.BeanContextServices;
+import java.io.IOException;
+import java.util.Iterator;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Provides the publishing service to components in the container for sending
+ * outgoing events. This component provides queued publishing (publish
+ * operations will not block). In the future, this publisher may also provide
+ * transactional publishing by saving outgoing events to a transactional
+ * persistence layer.
+ *
+ * TODO: enforce stop() method contract
+ *
+ * @author Buko O. (buko@concedere.net)
+ * @version 0.1
+ **/
+public class ManagedPublisher implements Publisher
+{
+    private Connection connection;
+    private ThreadPool threadPool;
+
+    private final static Logger log = Logger.getLogger(ManagedPublisher.class);
+
+    /**
+     * Set the Connection to be used by the ManagedPublisher.
+     *
+     * @param conn Connection to be used by the ManagedPublisher
+     */
+    public void setConnection(Connection conn)
+    {
+        if (conn == null)
+        {
+            String msg = "conn can't be null";
+            throw new IllegalArgumentException(msg);
+        }
+
+        this.connection = conn;
+    }
+
+    /**
+     * Get the Connection for the Publisher.
+     *
+     * @return Connection for the Publisher
+     */
+    public Connection getConnection()
+    {
+        return connection;
+    }
+
+    /**
+     * Set the ThreadPool to be used by the Publisher.
+     *
+     * @param pool ThreadPool to be used by the Publisher
+     */
+    public void setThreadPool(ThreadPool pool)
+    {
+        if (pool == null)
+        {
+            String msg = "ThreadPool can't be null";
+            throw new IllegalArgumentException(msg);
+        }
+
+        this.threadPool = pool;
+    }
+
+    /**
+     * Get the ThreadPool used to actually deliver events.
+     *
+     * @return ThreadPool used to deliver events
+     */
+    public ThreadPool getThreadPool()
+    {
+        return threadPool;
+    }
+
+    public void publish(final Event event) throws IOException
+    {
+        Runnable deliver = new Runnable()
+        {
+            public void run()
+            {
+                try
+                {
+                    connection.publish(event);
+                }
+                catch (IOException ioe)
+                {
+                    log.warn("Failed to deliver event " + event, ioe);
+                }
+            }
+        };
+        threadPool.execute(deliver);
+    }
+}
diff --git a/aether2/hercules/src/java/aether/server/ThreadPool.java b/aether2/hercules/src/java/aether/server/ThreadPool.java
new file mode 100644
index 0000000..80cd832
--- /dev/null
+++ b/aether2/hercules/src/java/aether/server/ThreadPool.java
@@ -0,0 +1,17 @@
+package aether.server;
+
+/**
+ * Defines a threadpool that units of work can be queued upon.
+ *
+ * @author Buko O. (buko@concedere.net)
+ * @version 0.1
+ **/
+public interface ThreadPool
+{
+	/**
+	 * Enqueue a unit of work onto the threadpool.
+	 *
+	 * @param work unit of work to enqueue on the threadpool
+	 */
+	public void execute(Runnable work);
+}
diff --git a/aether2/hercules/src/java/aether/server/responder/DefaultSwitchBoard.java b/aether2/hercules/src/java/aether/server/responder/DefaultSwitchBoard.java
index 79f8774..086b4fe 100644
--- a/aether2/hercules/src/java/aether/server/responder/DefaultSwitchBoard.java
+++ b/aether2/hercules/src/java/aether/server/responder/DefaultSwitchBoard.java
@@ -1,377 +1,372 @@
 package aether.server.responder;

-import EDU.oswego.cs.dl.util.concurrent.LinkedQueue;
-import EDU.oswego.cs.dl.util.concurrent.PooledExecutor;
-import aether.event.Message;
+import aether.event.*;
 import aether.net.Connection;
+import aether.server.ThreadPool;
 import org.apache.log4j.Logger;
 import org.elvin.je4.Consumer;
+import org.elvin.je4.Notification;
+import org.elvin.je4.NotificationListener;
 import org.elvin.je4.Subscription;

 import javax.swing.event.EventListenerList;
 import java.io.IOException;
 import java.util.*;
-import java.beans.beancontext.BeanContextServiceProvider;
-import java.beans.beancontext.BeanContextServices;
-
-import net.concedere.dundee.framework.Initializable;
-import net.concedere.dundee.framework.Disposable;
-import net.concedere.dundee.DefaultComponent;
-import net.concedere.dundee.ComponentException;
-import net.concedere.dundee.ServiceDependencyException;
-import net.concedere.dundee.AbstractProvider;

 /**
  * Default implementation of the SwitchBoard interface.
- * <p />
- * By default, when this component is added to a Container it will register
- * itself to provide the 'SwitchBoard' service. If you don't want it to do
- * this you must set the 'serviceProvider' property to false.
- *
  *
  * @author Buko O. (buko@concedere.net)
  * @version 0.1
  **/
-public class DefaultSwitchBoard extends DefaultComponent
-		implements SwitchBoard, Disposable, Initializable
+public class DefaultSwitchBoard implements SwitchBoard
 {
-	/**
-	 * Connection use to route incoming events.
-	 */
-	protected Connection connection;
-
-	/**
-	 * EventListenerList used to store SwitchBoard listeners.
-	 */
-	protected EventListenerList listenerList = new EventListenerList();
-
-	/**
-	 * Mapping between Responders and Subscriptions.
-	 */
-	protected Map subMap = Collections.synchronizedMap(new HashMap());
-
-	/**
-	 * Executor used to process the RequestExecutors.
-	 */
-	protected PooledExecutor threadPool;
-
-	/**
-	 * Number of request processing threads that should be used to process
-	 * incoming requests.
-	 */
-	protected int numRequestWorkers = 5;
-
-	/**
-	 * Determine whether this component is a service provider.
-	 */
-	protected boolean serviceProvider = true;
-
-	private BeanContextServiceProvider spi = null;
-
-	/**
-	 * Mapping between destinations and Responders.
-	 */
-	protected Map destMap = Collections.synchronizedMap(new HashMap());
-
-	private Consumer consumer;
-
-	private static final Logger log =
-			Logger.getLogger(DefaultSwitchBoard.class);
-
-	/**
-	 * Construct a new DefaultSwitchBoard.
-	 */
-	public DefaultSwitchBoard()
-	{
-        ; // do nothing
-	}
-
-	/**
-	 * Get the number of threads used to process incoming requests. By default,
-	 * this is 5.
-	 *
-	 * @return number of threads used to process incoming requests
-	 */
-    public int getRequestWorkerThreads()
-	{
-		return numRequestWorkers;
-	}
-
-	/**
-	 * Set the number of threads used to process incoming requests.
-	 *
-	 * @param num number of threads used to process incoming requests
-	 */
-	public void setRequestWorkerThreads(int num)
-	{
-		this.numRequestWorkers = num;
-	}
-
-	/**
-	 * Determine whether this component is also a service provider. By default
-	 * true.
-	 *
-	 * @return whether this component is also a service provider
-	 */
-	public boolean isServiceProvider()
-	{
-		return serviceProvider;
-	}
-
-	/**
-	 * Determine whether this class should register itself as a service
-	 * provider.
-	 *
-	 * @param provide whether this class should register itself as service
-	 *        provider
-	 */
-	public void setServiceProvider(boolean provide)
-	{
-		this.serviceProvider = provide;
-	}
-
-	public void bind(Responder r, String dest) throws ResponderException,
-			IOException
-	{
-		if ((r == null) || (dest == null))
-		{
-			String msg = "no param can be null";
-			throw new IllegalArgumentException(msg);
-		}
-
-		// make sure that there isn't already a responder bound to dest
-		if (destMap.containsKey(dest))
-		{
+    /**
+     * Connection use to route incoming events.
+     */
+    protected Connection connection;
+
+    /**
+     * EventListenerList used to store SwitchBoard listeners.
+     */
+    protected EventListenerList listenerList = new EventListenerList();
+
+    /**
+     * Mapping from Responder objects to (Elvin) Subscription objects.
+     */
+    protected Map subMap = Collections.synchronizedMap(new IdentityHashMap());
+
+    /**
+     * ThreadPool used to execute the handling of requests.
+     */
+    protected ThreadPool threadPool;
+
+    /**
+     * Mapping from Destination IDs to Responder objects.
+     */
+    protected Map destMap = Collections.synchronizedMap(new HashMap());
+
+    private Consumer consumer;
+    private NotificationListener requestListener;
+
+    private static final Logger log =
+            Logger.getLogger(DefaultSwitchBoard.class);
+
+
+    /**
+     * Set the Connection used for event sending/receiving.
+     *
+     * @param conn Connection used for event sending/receiving
+     */
+    public void setConnection(Connection conn)
+    {
+        if (conn == null)
+        {
+            String msg = "conn can't be null";
+            throw new IllegalArgumentException(msg);
+        }
+
+        this.connection = conn;
+    }
+
+    /**
+     * Get the Connection used for event sending/receiving.
+     *
+     * @return Connecting used for event handling
+     */
+    public Connection getConnection()
+    {
+        return connection;
+    }
+
+    /**
+     * Set the ThreadPool to be used by the DefaultSwitchBoard in order to
+     * handle incoming requests.
+     *
+     * @param threadPool ThreadPool used to handle incoming requests
+     */
+    public void setThreadPool(ThreadPool threadPool)
+    {
+        if (threadPool == null)
+        {
+            String msg = "threadPool can't be null";
+            throw new IllegalArgumentException(msg);
+        }
+
+        this.threadPool = threadPool;
+    }
+
+    /**
+     * Get the ThreadPool used to handle incoming requests.
+     *
+     * @return ThreadPool used to handle incoming requests
+     */
+    public ThreadPool getThreadPool()
+    {
+        return threadPool;
+    }
+
+    public void bind(final Responder responder, String dest)
+            throws ResponderException, IOException
+    {
+        if ((responder == null) || (dest == null))
+        {
+            String msg = "no param can be null";
+            throw new IllegalArgumentException(msg);
+        }
+
+        // make sure that there isn't already a responder bound to dest
+        if (destMap.containsKey(dest))
+        {
             String msg = "responder already bound to dest " + dest;
-			throw new ResponderException(msg);
-		}
-
-        // create a subscription to receive requests to this destination
-		Subscription sub = Message.createSubForDestination(dest);
-
-		// create a new notification listener
-		sub.addNotificationListener(
-				new SwitchboardNotificationListener(r, connection,
-													threadPool));
-
-		// now add this subscription to the consumer
-		synchronized (this) { consumer.addSubscription(sub); }
-
-		// now put this subscription in the map, corresponding to the
-		// responder's uid
-		subMap.put(r.getGuid(), sub);
-
-		// put the responder in the destination map, corresponding to its
-		// dest
-		destMap.put(dest, r);
-
-		// now fire the event
-		fireResponderBound(r, dest);
-	}
-
-	public void unbind(Responder r, String dest) throws ResponderException,
-			IOException
-	{
-        if ((r == null) || (dest == null))
-		{
-			String msg = "no param can be null";
-			throw new IllegalArgumentException(msg);
-		}
-
-       	// make sure that this responder has actually been bound
+            throw new ResponderException(msg);
+        }
+
+        // create a subscription to receive requests sent to this destination
+        Subscription sub = Message.createSubscriptionForDestination(dest);
+
+        // construct a notification listener that will queue the requests sent
+        // to the subscription
+        requestListener = new NotificationListener()
+        {
+            public void notificationAction(Notification notification)
+            {
+                threadPool.execute(
+                        new RequestProcessor(responder, notification));
+            }
+        };
+        sub.addNotificationListener(requestListener);
+
+        // now add this subscription to the consumer
+        synchronized (this) { consumer.addSubscription(sub); }
+
+        // now put this subscription in the map, corresponding to the
+        // responder reference
+        subMap.put(responder, sub);
+
+        // put the responder in the destination map, corresponding to its
+        // dest
+        destMap.put(dest, responder);
+
+        // now fire the event
+        fireResponderBound(responder, dest);
+    }
+
+    public void unbind(Responder responder, String dest) throws ResponderException,
+            IOException
+    {
+        if ((responder == null) || (dest == null))
+        {
+            String msg = "no param can be null";
+            throw new IllegalArgumentException(msg);
+        }
+
+        // make sure that this responder has actually been bound
         if (destMap.containsKey(dest))
-		{
-			Responder responder = (Responder) destMap.get(dest);
-
-			if (responder != r)
-			{
-				String msg = "given Responder is not bound to dest " + dest;
-				throw new ResponderException(msg);
-			}
-		}
-		else
-		{
-			String msg = "no Responder bound to dest " + dest;
-			throw new ResponderException(msg);
-		}
+        {
+            Responder oldResp = (Responder) destMap.get(dest);
+
+            if (oldResp != responder)
+            {
+                String msg = "given Responder is not bound to dest " + dest;
+                throw new ResponderException(msg);
+            }
+        }
+        else
+        {
+            String msg = "no Responder bound to dest " + dest;
+            throw new ResponderException(msg);
+        }

         // get the subscription that this responder was bound to
-        Subscription sub = (Subscription) subMap.get(r.getGuid());
+        Subscription sub = (Subscription) subMap.get(responder);

-		// now stop subscribing to this responder
+        // now stop subscribing to this responder
         synchronized (this) { consumer.removeSubscription(sub); }

         // remove the subscription and the destination binding
-		subMap.remove(r.getGuid());
-
-		// remove the destination binding
-		destMap.remove(dest);
-
-		// fire the unbinding event
-		fireResponderUnbound(r, dest);
-	}
-
-	public void addSwitchBoardListener(SwitchBoardListener sbl)
-	{
-		listenerList.add(SwitchBoardListener.class, sbl);
-	}
-
-	public void removeSwitchBoardListener(SwitchBoardListener sbl)
-	{
-		listenerList.remove(SwitchBoardListener.class, sbl);
-	}
-
-	/**
-	 * Fire a SwitchBoardEvent when a Responder is bound.
-	 *
-	 * @param resp Responder that was bound
-	 * @param dest Destination the Responder was bound to
-	 */
-	protected void fireResponderBound(Responder resp, String dest)
-	{
-		SwitchBoardEvent sbe = new SwitchBoardEvent(this, resp, dest);
+        subMap.remove(responder);
+
+        // remove the destination binding
+        destMap.remove(dest);
+
+        // fire the unbinding event
+        fireResponderUnbound(responder, dest);
+    }
+
+    public void addSwitchBoardListener(SwitchBoardListener sbl)
+    {
+        listenerList.add(SwitchBoardListener.class, sbl);
+    }
+
+    public void removeSwitchBoardListener(SwitchBoardListener sbl)
+    {
+        listenerList.remove(SwitchBoardListener.class, sbl);
+    }
+
+    /**
+     * Fire a SwitchBoardEvent when a Responder is bound.
+     *
+     * @param resp Responder that was bound
+     * @param dest Destination the Responder was bound to
+     */
+    protected void fireResponderBound(Responder resp, String dest)
+    {
+        SwitchBoardEvent sbe = new SwitchBoardEvent(this, resp, dest);

         Object[] listeners = listenerList.getListenerList();

-		for (int i = listeners.length - 2; i >= 0; i -= 2)
-		{
+        for (int i = listeners.length - 2; i >= 0; i -= 2)
+        {
             if (listeners[i] == SwitchBoardListener.class)
-			{
-				((SwitchBoardListener) listeners[i + 1]).responderBound(sbe);
-			}
-		}
-	}
+            {
+                ((SwitchBoardListener) listeners[i + 1]).responderBound(sbe);
+            }
+        }
+    }

     /**
-	 * Fired when a Responder is unbound from the SwitchBoard.
-	 *
-	 * @param resp Responder being unbound
-	 * @param dest Destination the Responder was unbound from
-	 */
-	protected void fireResponderUnbound(Responder resp, String dest)
-	{
-		SwitchBoardEvent sbe = new SwitchBoardEvent(this, resp, dest);
+     * Fired when a Responder is unbound from the SwitchBoard.
+     *
+     * @param resp Responder being unbound
+     * @param dest Destination the Responder was unbound from
+     */
+    protected void fireResponderUnbound(Responder resp, String dest)
+    {
+        SwitchBoardEvent sbe = new SwitchBoardEvent(this, resp, dest);

         Object[] listeners = listenerList.getListenerList();

-		for (int i = listeners.length - 2; i >= 0; i -= 2)
-		{
+        for (int i = listeners.length - 2; i >= 0; i -= 2)
+        {
             if (listeners[i] == SwitchBoardListener.class)
-			{
-				((SwitchBoardListener) listeners[i + 1]).responderUnbound(sbe);
-			}
-		}
-	}
-
-	public void initialize() throws ComponentException
-	{
-		// set up the threadpool
-		threadPool = new PooledExecutor(new LinkedQueue());
-		threadPool.setMinimumPoolSize(numRequestWorkers);
-
-		// look for a connection from this container
-		try
-		{
-			this.connection = (Connection) getContainer()
-					.getService(this, this, Connection.class, null, this);
-		}
-		catch (TooManyListenersException tle)
-		{
-			; // ignore it, temporarily
-		}
-		if (connection == null)
-		{
-			String msg = "couldn't get a Connection object";
-			throw new ServiceDependencyException(msg, Connection.class);
-		}
-
-		// create the consumer
-		consumer = new Consumer(connection.elvinConnection());
-
-		// register as a service provider
-		if (serviceProvider)
-		{
-			spi = new SwitchBoardServiceProvider();
-
-			if (! getContainer().addService(SwitchBoard.class, spi))
-			{
-				String msg = "couldn't register as SwitchBoard provider";
-				throw new ComponentException(msg);
-			}
-		}
-	}
-
-	public void dispose() throws ComponentException
-	{
-		if (serviceProvider)
-		{
-			getContainer().revokeService(SwitchBoard.class, spi, true);
-		}
-
-		// clear the subscription map
-		subMap.clear();
-		subMap = null;
-
-		// close the consumer and all subscriptions to it
-		consumer.close();
-		consumer = null;
-
-			// release the connection
-		getContainer().releaseService(this, this, connection);
-		connection = null;
-
-		// shutdown the threadpool
-		threadPool.setMinimumPoolSize(0);
-		threadPool.setKeepAliveTime(10);
-		threadPool.shutdownAfterProcessingCurrentlyQueuedTasks();
-
-		try
-		{
-    		// wait for the threadpool to fully shutdown, but only wait
-			// 1 second at max
-			// TODO: this is a bug, may not be enuf time to process all queued requests
-			// in the future drain() the threadpool and execute them yourself!
-			threadPool.awaitTerminationAfterShutdown();
-			threadPool.shutdownNow();
-			threadPool = null;
-		}
-		catch (InterruptedException ie)
-		{
-			log.warn("received unexpected interrupted exception " + ie);
-		}
-
-		// now fire unbinding events for all the still-bound responders
+            {
+                ((SwitchBoardListener) listeners[i + 1]).responderUnbound(sbe);
+            }
+        }
+    }
+
+    public void initialize()
+    {
+        // create the consumer
+        consumer = new Consumer(connection.elvinConnection());
+    }
+
+    public void dispose()
+    {
+        // clear the subscription map
+        subMap.clear();
+        subMap = null;
+
+        // close the consumer and all subscriptions to it
+        consumer.close();
+        consumer = null;
+
+        // now fire unbinding events for all the still-bound responders
         for (Iterator i = destMap.entrySet().iterator(); i.hasNext(); )
-		{
-			Map.Entry me = (Map.Entry) i.next();
-			String dest = (String) me.getKey();
-			Responder r = (Responder) me.getValue();
-
-			fireResponderUnbound(r, dest);
-
-			i.remove();
-		}
-		destMap = null;
-	}
-
-	private class SwitchBoardServiceProvider extends AbstractProvider
-	{
-		public Iterator getCurrentServiceSelectors(BeanContextServices bcs,
-												   Class serviceClass)
-		{
-			return null;
-		}
-
-		public void releaseService(BeanContextServices bcs, Object requestor,
-								   Object service)
-		{
-			; // do nothing
-		}
-
-		public Object getService(BeanContextServices bcs, Object requestor,
-								 Class serviceClass, Object serviceSelector)
-		{
-			return DefaultSwitchBoard.this;
-		}
-	}
+        {
+            Map.Entry me = (Map.Entry) i.next();
+            String dest = (String) me.getKey();
+            Responder r = (Responder) me.getValue();
+
+            fireResponderUnbound(r, dest);
+
+            i.remove();
+        }
+
+        destMap = null;
+    }
+
+    /**
+     * Represents a unit of work that must be completed to process some request.
+     * RequestExecutors are usually queued up and then executed asynchronously in
+     * the request processing threads.
+     *
+     * @author Buko O. (buko@concedere.net)
+     * @version 0.1
+     **/
+    private class RequestProcessor implements Runnable
+    {
+        private Responder responder;
+        private Notification notifcation;
+
+        /**
+         * Construct a new RequestProcessor to process the given request.
+         *
+         * @param resp  Responder that generates the response
+         * @param notif Notification containing Request data
+         */
+        public RequestProcessor(Responder resp, Notification notif)
+        {
+            if ((resp == null) || (notif == null))
+            {
+                String msg = "no parameter can be null";
+                throw new IllegalArgumentException(msg);
+            }
+
+            this.responder = resp;
+            this.notifcation = notif;
+        }
+
+        /**
+         * Execute the contained request by running it.
+         */
+        public void run()
+        {
+            Request request = null;
+
+            if (Event.isRequest(notifcation))
+            {
+                try
+                {
+                    request = new Request();
+                    request.parse(notifcation);
+                }
+                catch (EventException ee)
+                {
+                    log.warn("received bad request data", ee);
+                    ee.printStackTrace();
+                }
+
+                // construct the necessary Response object
+                final Response response =
+                        request.createResponse(responder.getResponderId());
+
+                // ask the responder to process it
+                try
+                {
+                    responder.respond(request, response);
+                }
+                catch (ResponderException re)
+                {
+                    throw new RespondFailedException(re);
+                }
+
+                // instead of sending the response back in the request
+                // handling thread, in order to increase throughput we queue
+                // up the actual sending
+                threadPool.execute(new Runnable()
+                {
+                    public void run()
+                    {
+                        try
+                        {
+                            connection.publish(response);
+                        }
+                        catch (IOException ioe)
+                        {
+                            log.warn("Failed to send response "
+                                     + response, ioe);
+                        }
+                    }
+                });
+            }
+            else
+            {
+                // received a notification that wasn't a request
+                log.warn("recieved non-request notification: " + notifcation);
+            }
+        }
+    }
+
 }
diff --git a/aether2/hercules/src/java/aether/server/responder/RequestExecutor.java b/aether2/hercules/src/java/aether/server/responder/RequestExecutor.java
deleted file mode 100644
index d0a1f16..0000000
--- a/aether2/hercules/src/java/aether/server/responder/RequestExecutor.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package aether.server.responder;
-
-import org.elvin.je4.Notification;
-import org.apache.log4j.Logger;
-import aether.net.Connection;
-import aether.event.Event;
-import aether.event.Request;
-import aether.event.Response;
-import aether.event.EventException;
-
-import java.io.IOException;
-
-/**
- * Represents a unit of work that must be completed to process some request.
- * RequestExecutors are usually queued up and then executed asynchronously in
- * the request processing threads.
- *
- * @author Buko O. (buko@concedere.net)
- * @version 0.1
- **/
-public class RequestExecutor implements Runnable
-{
-    private Responder responder;
-	private Notification notifcation;
-	private Connection connection;
-
-	private static final Logger log = Logger.getLogger(RequestExecutor.class);
-
-	/**
-	 * Construct a new RequestExecutor to process the given request.
-	 *
-	 * @param resp  Responder that generates the response
-	 * @param notif Notification containing Request data
-	 * @param conn  Connection to send the response over
-	 */
-	public RequestExecutor(Responder resp, Notification notif, Connection conn)
-	{
-		if ((resp == null) || (notif == null) || (conn == null))
-		{
-			String msg = "no parameter can be null";
-			throw new IllegalArgumentException(msg);
-		}
-
-		this.responder = resp;
-		this.notifcation = notif;
-		this.connection = conn;
-	}
-
-	/**
-	 * Execute the contained request by running it.
-	 */
-	public void run()
-	{
-		Request request = null;
-
-        if (Event.isRequest(notifcation))
-		{
-			try
-			{
-				request = new Request(notifcation);
-			}
-			catch (EventException ee)
-			{
-				log.warn("received bad request data", ee);
-				ee.printStackTrace();
-			}
-
-			// construct the necessary Response object
-			Response response = Request.createResponse(request,
-												   responder.getGuid());
-
-			// ask the responder to process it
-			try
-			{
-            	responder.respond(request, response);
-			}
-            catch (ResponderException re)
-			{
-				throw new RespondFailedException(re);
-			}
-
-			// now send the response back
-			try
-			{
-				connection.publish(response);
-			}
-            catch (IOException ioe)
-			{
-                throw new SendResponseException(ioe);
-			}
-		}
-		else
-		{
-			// received a notification that wasn't a request
-			log.warn("recieved non-request notification: " + notifcation);
-		}
-	}
-}
diff --git a/aether2/hercules/src/java/aether/server/responder/Responder.java b/aether2/hercules/src/java/aether/server/responder/Responder.java
index 59caade..927e5b4 100644
--- a/aether2/hercules/src/java/aether/server/responder/Responder.java
+++ b/aether2/hercules/src/java/aether/server/responder/Responder.java
@@ -8,15 +8,11 @@ import aether.server.framework.Identifiable;
  * A Responder is an object that will process requests and generate responses.
  * In order for Responders to receive requests they must utilize the
  * Switchboard service.
- * <p />
- * Responders are full beans/components. When they are bound to a Switchboard
- * they will be added to the BeanContext/Container (unless they've already
- * been added before).
  *
  * @author Buko O. (buko@concedere.net)
  * @version 0.1
  **/
-public interface Responder extends Identifiable
+public interface Responder
 {
 	/**
 	 * Proces an incoming request by setting variables on the approriate
@@ -30,17 +26,12 @@ public interface Responder extends Identifiable
 	public void respond(Request request, Response response)
 			throws ResponderException;

-	/**
-	 * Get the SwitchBoard service used by this Responder.
-	 *
-	 * @return SwitchBoard service used by this Responder
-	 */
-	public SwitchBoard getSwitchBoard();
+    /**
+     * Get the unique ResponderID. This ResponderID will be used to establish
+     * the source of the responses generated by this Responder.
+     *
+     * @return unique responder ID
+     */
+    public String getResponderId();

-	/**
-	 * Set the SwitchBoard service used by this Responder.
-	 *
-	 * @param sb SwitchBoard service used by this responder
-	 */
-	public void setSwitchBoard(SwitchBoard sb);
 }
diff --git a/aether2/hercules/src/java/aether/server/responder/SwitchBoard.java b/aether2/hercules/src/java/aether/server/responder/SwitchBoard.java
index cd46d84..a718de2 100644
--- a/aether2/hercules/src/java/aether/server/responder/SwitchBoard.java
+++ b/aether2/hercules/src/java/aether/server/responder/SwitchBoard.java
@@ -1,6 +1,5 @@
 package aether.server.responder;

-import aether.net.Connection;

 import java.io.IOException;

diff --git a/aether2/hercules/src/java/aether/server/responder/SwitchboardNotificationListener.java b/aether2/hercules/src/java/aether/server/responder/SwitchboardNotificationListener.java
deleted file mode 100644
index 4ee1402..0000000
--- a/aether2/hercules/src/java/aether/server/responder/SwitchboardNotificationListener.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package aether.server.responder;
-
-import org.elvin.je4.NotificationListener;
-import org.elvin.je4.Notification;
-import org.apache.log4j.Logger;
-
-import aether.net.Connection;
-
-import EDU.oswego.cs.dl.util.concurrent.Executor;
-
-/**
- * A special NotifcationListener that dispatches incoming Requests to a given
- * Responder.
- *
- * @author Buko O. (buko@concedere.net)
- * @version 0.1
- **/
-public class SwitchboardNotificationListener implements NotificationListener
-{
-    private Responder responder;
-	private Connection connection;
-	private Executor executor;
-
-	private static final Logger log =
-			Logger.getLogger(SwitchboardNotificationListener.class);
-
-	/**
-	 * Construct a new listener to dispatched received requests to the
-	 * responder.
-	 *
-	 * @param resp Responder to receive notification/requests
-	 * @param conn Connection used to send responses
-	 * @param exec Executor to place request executors on
-	 */
-	public SwitchboardNotificationListener(Responder resp, Connection conn,
-										   Executor exec)
-	{
-		if ((resp == null) || (conn == null) || (exec == null))
-		{
-			String msg = "no parameter be null";
-			throw new IllegalArgumentException(msg);
-		}
-
-		this.responder = resp;
-		this.connection = conn;
-		this.executor = exec;
-	}
-
-	/**
-	 * Called when an Elvin Notification arrives which is probably a Request
-	 * that needs to be responded to.
-	 *
-	 * @param notif Notification that may be a request
-	 */
-	public void notificationAction(Notification notif)
-	{
-     	// queue up a new RequestExecutor
-		try
-		{
-			executor.execute(new RequestExecutor(responder, notif, connection));
-		}
-		catch (InterruptedException e)
-		{
-			log.warn("got unexpected interrupted exception " + e);
-			e.printStackTrace();
-		}
-	}
-
-}
diff --git a/aether2/hercules/src/java/memento/world/manager/WorldController.java b/aether2/hercules/src/java/memento/world/manager/WorldController.java
index c57cb33..a5edd7a 100644
--- a/aether2/hercules/src/java/memento/world/manager/WorldController.java
+++ b/aether2/hercules/src/java/memento/world/manager/WorldController.java
@@ -5,7 +5,7 @@ import memento.world.model.WorldAdvertisement;
 import aether.net.Monitor;
 import aether.net.Connection;
 import aether.server.domain.Advertisement;
-import aether.server.core.ThreadPool;
+import aether.server.ThreadPool;
 import aether.event.EventHandler;
 import aether.event.Event;
 import aether.event.Notice;
diff --git a/aether2/hercules/src/test/aether/server/PublisherProviderTest.java b/aether2/hercules/src/test/aether/server/PublisherProviderTest.java
new file mode 100644
index 0000000..c6b2f27
--- /dev/null
+++ b/aether2/hercules/src/test/aether/server/PublisherProviderTest.java
@@ -0,0 +1,76 @@
+package aether.server;
+
+import aether.AetherTestCase;
+import aether.event.Notice;
+import aether.event.EventQueue;
+import aether.event.BlockingEventQueue;
+import aether.event.Attribute;
+import aether.net.Connection;
+import aether.net.DefaultConnection;
+import aether.net.Publisher;
+import aether.server.AetherContainer;
+import aether.server.ManagedPublisher;
+
+import java.beans.beancontext.BeanContextChildSupport;
+
+import org.elvin.je4.Consumer;
+import org.elvin.je4.Subscription;
+
+/**
+ *
+ * @author Buko O. (buko@concedere.net)
+ * @version 0.1
+ **/
+public class PublisherProviderTest extends AetherTestCase
+{
+    public void testService() throws Exception
+	{
+		AetherContainer container = new AetherContainer();
+
+		DefaultConnectionProvider dcp = new DefaultConnectionProvider();
+		Connection conn = new DefaultConnection(getElvinHost(), getElvinPort());
+		dcp.setDefaultConnection(conn);
+
+		ManagedPublisher pub = new ManagedPublisher();
+
+		container.add(dcp);
+		container.add(pub);
+
+		assertTrue(container.hasService(Publisher.class));
+
+
+		container.remove(pub);
+		container.remove(dcp);
+
+		assertFalse(container.hasService(Publisher.class));
+
+	}
+
+	public void testPublish() throws Exception
+	{
+    	AetherContainer container = new AetherContainer();
+
+		DefaultConnectionProvider dcp = new DefaultConnectionProvider();
+		Connection conn = new DefaultConnection(getElvinHost(), getElvinPort());
+		dcp.setDefaultConnection(conn);
+
+		ManagedPublisher pub = new ManagedPublisher();
+
+		container.add(dcp);
+		container.add(pub);
+
+		BeanContextChildSupport bean = new BeanContextChildSupport();
+        container.add(bean);
+
+		Publisher publisher = (Publisher) container
+				.getService(bean, bean, Publisher.class, null, bean);
+		assertNotNull(publisher);
+
+
+		Notice n = new Notice();
+        publisher.publish(n);
+
+		container.remove(pub);
+		container.remove(dcp);
+	}
+}
diff --git a/aether2/hercules/src/test/aether/server/ThreadPoolProviderTest.java b/aether2/hercules/src/test/aether/server/ThreadPoolProviderTest.java
new file mode 100644
index 0000000..d72479b
--- /dev/null
+++ b/aether2/hercules/src/test/aether/server/ThreadPoolProviderTest.java
@@ -0,0 +1,61 @@
+package aether.server;
+
+import aether.AetherTestCase;
+import aether.server.AetherContainer;
+import aether.server.ThreadPool;
+import aether.server.DefaultThreadPool;
+
+import java.beans.beancontext.BeanContextChildSupport;
+
+/**
+ *
+ * @author Buko O. (buko@concedere.net)
+ * @version 0.1
+ **/
+public class ThreadPoolProviderTest extends AetherTestCase
+{
+    public void testThreadPoolService() throws Exception
+	{
+        AetherContainer container = new AetherContainer();
+        DefaultThreadPool tpp = new DefaultThreadPool();
+        container.add(tpp);
+
+        assertTrue(container.hasService(ThreadPool.class));
+
+        container.remove(tpp);
+
+		assertFalse(container.hasService(ThreadPool.class));
+	}
+
+	public void testThreadPoolWork() throws Exception
+	{
+		AetherContainer container = new AetherContainer();
+        DefaultThreadPool tpp = new DefaultThreadPool();
+        container.add(tpp);
+
+        BeanContextChildSupport bccs = new BeanContextChildSupport();
+		container.add(bccs);
+
+      	ThreadPool pool = (ThreadPool)
+				  container.getService(bccs, bccs, ThreadPool.class, null,
+									   bccs);
+
+		assertNotNull(pool);
+
+		final boolean[] gotRun = new boolean[] { false };
+        Runnable run = new Runnable()
+		{
+			public void run()
+			{
+				gotRun[0] = true;
+				synchronized (gotRun) { gotRun.notify(); };
+			}
+		};
+
+        pool.execute(run);
+		synchronized (gotRun) { gotRun.wait(); }
+
+		assertTrue(gotRun[0]);
+        container.remove(tpp);
+	}
+}
diff --git a/aether2/hercules/src/test/aether/server/domain/DomainAgentTest.java b/aether2/hercules/src/test/aether/server/domain/DomainAgentTest.java
index 9dbfed9..2313098 100644
--- a/aether2/hercules/src/test/aether/server/domain/DomainAgentTest.java
+++ b/aether2/hercules/src/test/aether/server/domain/DomainAgentTest.java
@@ -6,8 +6,8 @@ import aether.net.DefaultConnection;
 import aether.net.Monitor;
 import aether.server.AetherContainer;
 import aether.server.core.DefaultConnectionProvider;
-import aether.server.core.PublisherProvider;
-import aether.server.core.ThreadPoolProvider;
+import aether.server.ManagedPublisher;
+import aether.server.DefaultThreadPool;
 import memento.world.manager.WorldManager;
 import memento.world.manager.DefaultWorldManager;
 import memento.world.model.WorldModel;
@@ -29,13 +29,13 @@ public class DomainAgentTest extends AetherTestCase
 		dcp.setDefaultConnection(conn);
 		container.add(dcp);

-		PublisherProvider pub = new PublisherProvider();
+		ManagedPublisher pub = new ManagedPublisher();
 		container.add(pub);

 		MonitorProvider mon = new MonitorProvider();
 		container.addService(Monitor.class, mon);

-		ThreadPoolProvider tpp = new ThreadPoolProvider();
+		DefaultThreadPool tpp = new DefaultThreadPool();
 		container.add(tpp);

 		// before we add the world manager, add the domain agent
diff --git a/aether2/hercules/src/test/aether/server/domain/RemoteDomainAgentTest.java b/aether2/hercules/src/test/aether/server/domain/RemoteDomainAgentTest.java
index 8945ad3..2e69ed0 100644
--- a/aether2/hercules/src/test/aether/server/domain/RemoteDomainAgentTest.java
+++ b/aether2/hercules/src/test/aether/server/domain/RemoteDomainAgentTest.java
@@ -6,8 +6,8 @@ import aether.net.DefaultConnection;
 import aether.net.Monitor;
 import aether.server.AetherContainer;
 import aether.server.core.DefaultConnectionProvider;
-import aether.server.core.PublisherProvider;
-import aether.server.core.ThreadPoolProvider;
+import aether.server.ManagedPublisher;
+import aether.server.DefaultThreadPool;

 /**
  *
@@ -25,13 +25,13 @@ public class RemoteDomainAgentTest extends AetherTestCase
 		dcp.setDefaultConnection(conn);
 		container.add(dcp);

-		PublisherProvider pub = new PublisherProvider();
+		ManagedPublisher pub = new ManagedPublisher();
 		container.add(pub);

 		MonitorProvider mon = new MonitorProvider();
 		container.addService(Monitor.class, mon);

-		ThreadPoolProvider tpp = new ThreadPoolProvider();
+		DefaultThreadPool tpp = new DefaultThreadPool();
 		container.add(tpp);

 		// before we add the world manager, add the domain agent
diff --git a/aether2/hercules/src/test/memento/world/manager/WorldManagerTest.java b/aether2/hercules/src/test/memento/world/manager/WorldManagerTest.java
index 34688ef..82bdc45 100644
--- a/aether2/hercules/src/test/memento/world/manager/WorldManagerTest.java
+++ b/aether2/hercules/src/test/memento/world/manager/WorldManagerTest.java
@@ -7,8 +7,8 @@ import aether.net.Monitor;
 import aether.server.AetherContainer;
 import aether.server.domain.Advertisement;
 import aether.server.core.DefaultConnectionProvider;
-import aether.server.core.PublisherProvider;
-import aether.server.core.ThreadPoolProvider;
+import aether.server.ManagedPublisher;
+import aether.server.DefaultThreadPool;
 import memento.world.model.WorldModel;
 import memento.world.model.WorldModel;
 import memento.world.model.WorldAdvertisement;
@@ -31,13 +31,13 @@ public class WorldManagerTest extends AetherTestCase
 		dcp.setDefaultConnection(conn);
 		container.add(dcp);

-        PublisherProvider pub = new PublisherProvider();
+        ManagedPublisher pub = new ManagedPublisher();
 		container.add(pub);

         MonitorProvider mon = new MonitorProvider();
 		container.addService(Monitor.class, mon);

-		ThreadPoolProvider tpp = new ThreadPoolProvider();
+		DefaultThreadPool tpp = new DefaultThreadPool();
 		container.add(tpp);

         WorldManager worldMan = new DefaultWorldManager();
diff --git a/aether2/lib/aether-core-0.1.jar b/aether2/lib/aether-core-0.1.jar
index d74298b..593f4cc 100644
Binary files a/aether2/lib/aether-core-0.1.jar and b/aether2/lib/aether-core-0.1.jar differ