Author: dblevins
Date: Sun Apr  1 06:52:32 2012
New Revision: 1308022

URL: http://svn.apache.org/viewvc?rev=1308022&view=rev
Log:
OPENEJB-1813: EJBd Protocol communicates server/container invocation times to 
client
OPENEJB-1814: JMX Management of Multipoint discovery server service
OPENEJB-1815: Ability to restart Multipoint ServerService
OPENEJB-1816: Client ConnectionPoolCreated and ConnectionPoolTimeout events

Added:
    
openejb/trunk/openejb/server/openejb-client/src/main/java/org/apache/openejb/client/event/ConnectionPoolCreated.java
    
openejb/trunk/openejb/server/openejb-client/src/main/java/org/apache/openejb/client/event/ConnectionPoolTimeout.java
Modified:
    
openejb/trunk/openejb/itests/failover/src/test/java/org/apache/openejb/itest/failover/ReconnectDelayTest.java
    
openejb/trunk/openejb/itests/failover/src/test/java/org/apache/openejb/itest/failover/RoundRobinConnectionStrategyTest.java
    
openejb/trunk/openejb/itests/failover/src/test/java/org/apache/openejb/itest/failover/StickyConnectionStrategyTest.java
    
openejb/trunk/openejb/server/openejb-client/src/main/java/org/apache/openejb/client/EJBResponse.java
    
openejb/trunk/openejb/server/openejb-client/src/main/java/org/apache/openejb/client/SocketConnectionFactory.java
    
openejb/trunk/openejb/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/EjbRequestHandler.java
    
openejb/trunk/openejb/server/openejb-multicast/src/main/java/org/apache/openejb/server/discovery/MultipointDiscoveryAgent.java
    
openejb/trunk/openejb/server/openejb-multicast/src/main/java/org/apache/openejb/server/discovery/MultipointServer.java
    
openejb/trunk/openejb/server/openejb-multicast/src/main/java/org/apache/openejb/server/discovery/Tracker.java
    
openejb/trunk/openejb/server/openejb-multicast/src/test/java/org/apache/openejb/server/discovery/MultipointDiscoveryAgentTest.java
    
openejb/trunk/openejb/server/openejb-server/src/main/java/org/apache/openejb/server/ServiceManager.java

Modified: 
openejb/trunk/openejb/itests/failover/src/test/java/org/apache/openejb/itest/failover/ReconnectDelayTest.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/itests/failover/src/test/java/org/apache/openejb/itest/failover/ReconnectDelayTest.java?rev=1308022&r1=1308021&r2=1308022&view=diff
==============================================================================
--- 
openejb/trunk/openejb/itests/failover/src/test/java/org/apache/openejb/itest/failover/ReconnectDelayTest.java
 (original)
+++ 
openejb/trunk/openejb/itests/failover/src/test/java/org/apache/openejb/itest/failover/ReconnectDelayTest.java
 Sun Apr  1 06:52:32 2012
@@ -52,7 +52,7 @@ public class ReconnectDelayTest {
     public void test() throws Exception {
 
         // To run in an IDE, uncomment and update this line
-        System.setProperty("version", "4.0.0-beta-3-SNAPSHOT");
+        //System.setProperty("version", "4.0.0-beta-3-SNAPSHOT");
 
         Duration reconnectDelay = new Duration("1 second");
 

Modified: 
openejb/trunk/openejb/itests/failover/src/test/java/org/apache/openejb/itest/failover/RoundRobinConnectionStrategyTest.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/itests/failover/src/test/java/org/apache/openejb/itest/failover/RoundRobinConnectionStrategyTest.java?rev=1308022&r1=1308021&r2=1308022&view=diff
==============================================================================
--- 
openejb/trunk/openejb/itests/failover/src/test/java/org/apache/openejb/itest/failover/RoundRobinConnectionStrategyTest.java
 (original)
+++ 
openejb/trunk/openejb/itests/failover/src/test/java/org/apache/openejb/itest/failover/RoundRobinConnectionStrategyTest.java
 Sun Apr  1 06:52:32 2012
@@ -33,7 +33,7 @@ import javax.naming.Context;
 import javax.naming.InitialContext;
 import java.io.File;
 import java.net.URI;
-import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -55,10 +55,15 @@ public class RoundRobinConnectionStrateg
     static final Logger logger = Logger.getLogger("org.apache.openejb.client");
 
     static {
+//        set(logger, Level.FINEST);
+//        set(Logger.getLogger("OpenEJB.client"), Level.FINEST);
+    }
+
+    private static void set(Logger logger, Level level) {
         final ConsoleHandler consoleHandler = new ConsoleHandler();
-        consoleHandler.setLevel(Level.FINER);
+        consoleHandler.setLevel(level);
         logger.addHandler(consoleHandler);
-        logger.setLevel(Level.FINER);
+        logger.setLevel(level);
         logger.setUseParentHandlers(false);
     }
 
@@ -72,6 +77,7 @@ public class RoundRobinConnectionStrateg
         final File zip = Repository.getArtifact("org.apache.openejb", 
"openejb-standalone", "zip");
         final File app = Repository.getArtifact("org.apache.openejb.itests", 
"failover-ejb", "jar");
 
+
         final File dir = Files.tmpdir();
 
         final StandaloneServer root;
@@ -243,6 +249,7 @@ public class RoundRobinConnectionStrateg
         private final Condition condition = lock.newCondition();
 
         private final Set<URI> expected = new HashSet<URI>();
+        private final Set<URI> found = new HashSet<URI>();
 
         public Services() {
         }
@@ -260,8 +267,8 @@ public class RoundRobinConnectionStrateg
         }
 
         public void observe(@Observes ClusterMetaDataUpdated updated) {
-            final URI[] locations = 
updated.getClusterMetaData().getLocations();
-            final Set<URI> found = new HashSet<URI>(Arrays.asList(locations));
+            found.clear();
+            Collections.addAll(found, 
updated.getClusterMetaData().getLocations());
 
             if (expected.equals(found)) {
                 lock.lock();
@@ -300,7 +307,10 @@ public class RoundRobinConnectionStrateg
             }
         }
 
+
         public boolean await(long timeout, TimeUnit unit) throws 
InterruptedException {
+            if (expected.equals(found)) return true;
+
             lock.lock();
             try {
                 return condition.await(timeout, unit);
@@ -319,7 +329,13 @@ public class RoundRobinConnectionStrateg
 
         @Override
         public Object call() throws Exception {
-            return bean.name();
+            try {
+                logger.info("Invoke");
+                return bean.name();
+            } catch (Exception e) {
+                logger.log(Level.SEVERE, "bean invocation failed", e);
+                throw e;
+            }
         }
     }
 }

Modified: 
openejb/trunk/openejb/itests/failover/src/test/java/org/apache/openejb/itest/failover/StickyConnectionStrategyTest.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/itests/failover/src/test/java/org/apache/openejb/itest/failover/StickyConnectionStrategyTest.java?rev=1308022&r1=1308021&r2=1308022&view=diff
==============================================================================
--- 
openejb/trunk/openejb/itests/failover/src/test/java/org/apache/openejb/itest/failover/StickyConnectionStrategyTest.java
 (original)
+++ 
openejb/trunk/openejb/itests/failover/src/test/java/org/apache/openejb/itest/failover/StickyConnectionStrategyTest.java
 Sun Apr  1 06:52:32 2012
@@ -69,7 +69,7 @@ public class StickyConnectionStrategyTes
     public void test() throws Exception {
 
         // To run in an IDE, uncomment and update this line
-//        System.setProperty("version", "4.0.0-beta-3-SNAPSHOT");
+        System.setProperty("version", "4.0.0-beta-3-SNAPSHOT");
 
         final File zip = Repository.getArtifact("org.apache.openejb", 
"openejb-standalone", "zip");
         final File app = Repository.getArtifact("org.apache.openejb.itests", 
"failover-ejb", "jar");

Modified: 
openejb/trunk/openejb/server/openejb-client/src/main/java/org/apache/openejb/client/EJBResponse.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/server/openejb-client/src/main/java/org/apache/openejb/client/EJBResponse.java?rev=1308022&r1=1308021&r2=1308022&view=diff
==============================================================================
--- 
openejb/trunk/openejb/server/openejb-client/src/main/java/org/apache/openejb/client/EJBResponse.java
 (original)
+++ 
openejb/trunk/openejb/server/openejb-client/src/main/java/org/apache/openejb/client/EJBResponse.java
 Sun Apr  1 06:52:32 2012
@@ -19,13 +19,13 @@ package org.apache.openejb.client;
 import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
-import java.net.URI;
 
 public class EJBResponse implements ClusterableResponse {
 
     private transient int responseCode = -1;
     private transient Object result;
     private transient ServerMetaData server;
+    private transient long[] times = new long[Time.values().length];
 
     public EJBResponse() {
 
@@ -90,11 +90,21 @@ public class EJBResponse implements Clus
             default:
                 s = new StringBuffer("UNKNOWN_RESPONSE");
         }
-        s.append(':').append(result);
+        s.append(", 
serverTime=").append(times[Time.TOTAL.ordinal()]).append("ns");
+        s.append(", 
containerTime").append(times[Time.CONTAINER.ordinal()]).append("ns");
+        s.append(" : ").append(result);
 
         return s.toString();
     }
 
+    public void start(EJBResponse.Time time) {
+        times[time.ordinal()] = System.nanoTime();
+    }
+
+    public void stop(EJBResponse.Time time) {
+        times[time.ordinal()] = System.nanoTime() - times[time.ordinal()];
+    }
+
     public void readExternal(ObjectInput in) throws IOException, 
ClassNotFoundException {
         byte version = in.readByte(); // future use
 
@@ -107,6 +117,11 @@ public class EJBResponse implements Clus
         responseCode = in.readByte();
 
         result = in.readObject();
+
+        times = new long[in.readByte()];
+        for (int i = 0; i < times.length; i++) {
+            times[i] = in.readLong();
+        }
     }
 
     public void writeExternal(ObjectOutput out) throws IOException {
@@ -131,7 +146,22 @@ public class EJBResponse implements Clus
                     result = new ThrowableArtifact(throwable);
                 }
         }
+
+        start(Time.SERIALIZATION);
         out.writeObject(result);
+        stop(Time.SERIALIZATION);
+        stop(Time.TOTAL);
+
+        out.writeByte(times.length);
+        for (int i = 0; i < times.length; i++) {
+            out.writeLong(times[i]);
+        }
     }
 
+    public static enum Time {
+        TOTAL,
+        CONTAINER,
+        SERIALIZATION,
+        DESERIALIZATION
+    }
 }

Modified: 
openejb/trunk/openejb/server/openejb-client/src/main/java/org/apache/openejb/client/SocketConnectionFactory.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/server/openejb-client/src/main/java/org/apache/openejb/client/SocketConnectionFactory.java?rev=1308022&r1=1308021&r2=1308022&view=diff
==============================================================================
--- 
openejb/trunk/openejb/server/openejb-client/src/main/java/org/apache/openejb/client/SocketConnectionFactory.java
 (original)
+++ 
openejb/trunk/openejb/server/openejb-client/src/main/java/org/apache/openejb/client/SocketConnectionFactory.java
 Sun Apr  1 06:52:32 2012
@@ -17,6 +17,8 @@
 package org.apache.openejb.client;
 
 import org.apache.openejb.client.event.ConnectionOpened;
+import org.apache.openejb.client.event.ConnectionPoolCreated;
+import org.apache.openejb.client.event.ConnectionPoolTimeout;
 
 import javax.net.ssl.SSLSocket;
 import javax.net.ssl.SSLSocketFactory;
@@ -176,6 +178,7 @@ public class SocketConnectionFactory imp
         private final Lock lock = new ReentrantLock();
         private OutputStream out;
         private BufferedInputStream in;
+        private long checkoutTime;
 
         public SocketConnection(final URI uri, final Pool pool) {
             this.uri = uri;
@@ -327,6 +330,8 @@ public class SocketConnectionFactory imp
             for (int i = 0; i < size; i++) {
                 pool.push(null);
             }
+
+            Client.fireEvent(new ConnectionPoolCreated(uri, size, timeout, 
timeUnit));
         }
 
         public SocketConnection get() throws IOException {
@@ -338,7 +343,10 @@ public class SocketConnectionFactory imp
                 Thread.interrupted();
             }
 
-            throw new ConnectionPoolTimeoutException("No connections available 
in pool (size " + size + ").  Waited for " + timeout + " milliseconds for a 
connection.");
+            ConnectionPoolTimeoutException exception = new 
ConnectionPoolTimeoutException("No connections available in pool (size " + size 
+ ").  Waited for " + timeout + " milliseconds for a connection.");
+            exception.fillInStackTrace();
+            Client.fireEvent(new ConnectionPoolTimeout(uri, size, timeout, 
timeUnit, exception));
+            throw exception;
         }
 
         public void put(final SocketConnection connection) {

Added: 
openejb/trunk/openejb/server/openejb-client/src/main/java/org/apache/openejb/client/event/ConnectionPoolCreated.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/server/openejb-client/src/main/java/org/apache/openejb/client/event/ConnectionPoolCreated.java?rev=1308022&view=auto
==============================================================================
--- 
openejb/trunk/openejb/server/openejb-client/src/main/java/org/apache/openejb/client/event/ConnectionPoolCreated.java
 (added)
+++ 
openejb/trunk/openejb/server/openejb-client/src/main/java/org/apache/openejb/client/event/ConnectionPoolCreated.java
 Sun Apr  1 06:52:32 2012
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.openejb.client.event;
+
+import java.net.URI;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @version $Rev$ $Date$
+ */
+@Log(Log.Level.FINE)
+public class ConnectionPoolCreated {
+
+    private final long timeout;
+    private final TimeUnit timeUnit;
+    private final int size;
+    private final URI uri;
+
+    public ConnectionPoolCreated(URI uri, int size, long timeout, TimeUnit 
timeUnit) {
+        this.uri = uri;
+        this.size = size;
+        this.timeUnit = timeUnit;
+        this.timeout = timeout;
+    }
+
+    public long getTimeout() {
+        return timeout;
+    }
+
+    public TimeUnit getTimeUnit() {
+        return timeUnit;
+    }
+
+    public int getSize() {
+        return size;
+    }
+
+    public URI getUri() {
+        return uri;
+    }
+
+    @Override
+    public String toString() {
+        return "ConnectionPoolCreated{" +
+                "uri=" + uri +
+                ", size=" + size +
+                ", timeout='" + timeout + " " + timeUnit + "'" +
+                '}';
+    }
+}

Added: 
openejb/trunk/openejb/server/openejb-client/src/main/java/org/apache/openejb/client/event/ConnectionPoolTimeout.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/server/openejb-client/src/main/java/org/apache/openejb/client/event/ConnectionPoolTimeout.java?rev=1308022&view=auto
==============================================================================
--- 
openejb/trunk/openejb/server/openejb-client/src/main/java/org/apache/openejb/client/event/ConnectionPoolTimeout.java
 (added)
+++ 
openejb/trunk/openejb/server/openejb-client/src/main/java/org/apache/openejb/client/event/ConnectionPoolTimeout.java
 Sun Apr  1 06:52:32 2012
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.openejb.client.event;
+
+import java.net.URI;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @version $Rev$ $Date$
+ */
+@Log(Log.Level.FINE)
+public class ConnectionPoolTimeout {
+
+    private final URI uri;
+    private final int size;
+    private final long timeout;
+    private final TimeUnit timeUnit;
+    private final Throwable caller;
+
+    public ConnectionPoolTimeout(URI uri, int size, long timeout, TimeUnit 
timeUnit, Throwable caller) {
+        this.uri = uri;
+        this.size = size;
+        this.timeout = timeout;
+        this.timeUnit = timeUnit;
+        this.caller = caller;
+    }
+
+    public long getTimeout() {
+        return timeout;
+    }
+
+    public TimeUnit getTimeUnit() {
+        return timeUnit;
+    }
+
+    public int getSize() {
+        return size;
+    }
+
+    public URI getUri() {
+        return uri;
+    }
+
+    @Override
+    public String toString() {
+        return "ConnectionPoolCreated{" +
+                "uri=" + uri +
+                ", size=" + size +
+                ", timeout='" + timeout + " " + timeUnit + "'" +
+                '}';
+    }
+}

Modified: 
openejb/trunk/openejb/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/EjbRequestHandler.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/EjbRequestHandler.java?rev=1308022&r1=1308021&r2=1308022&view=diff
==============================================================================
--- 
openejb/trunk/openejb/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/EjbRequestHandler.java
 (original)
+++ 
openejb/trunk/openejb/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/EjbRequestHandler.java
 Sun Apr  1 06:52:32 2012
@@ -57,6 +57,7 @@ class EjbRequestHandler {
     }
 
     public void processRequest(final ObjectInputStream in, final 
ObjectOutputStream out) {
+
         // Setup the client proxy replacement to replace
         // the proxies with the IntraVM proxy implementations
         EJBHomeProxyHandle.resolver.set(SERVER_SIDE_RESOLVER);
@@ -65,6 +66,8 @@ class EjbRequestHandler {
         final EJBRequest req = new EJBRequest();
         final EJBResponse res = new EJBResponse();
 
+        res.start(EJBResponse.Time.TOTAL);
+
         try {
             req.readExternal(in);
         } catch (Throwable t) {
@@ -105,7 +108,11 @@ class EjbRequestHandler {
         Thread.currentThread().setContextClassLoader(classLoader);
 
         try {
+            res.start(EJBResponse.Time.DESERIALIZATION);
+
             req.getBody().readExternal(in);
+
+            res.stop(EJBResponse.Time.DESERIALIZATION);
         } catch (Throwable t) {
             replyWithFatalError(out, t, "Error caught during request 
processing");
             return;
@@ -120,6 +127,7 @@ class EjbRequestHandler {
             return;
         }
 
+        res.start(EJBResponse.Time.CONTAINER);
         boolean respond = true;
         try {
             switch (req.getRequestMethod()) {
@@ -194,6 +202,7 @@ class EjbRequestHandler {
                     doFUTURE_CANCEL_METHOD(req, res);
                     break;
             }
+            res.stop(EJBResponse.Time.CONTAINER);
 
         } catch (org.apache.openejb.InvalidateReferenceException e) {
             res.setResponse(ResponseCodes.EJB_SYS_EXCEPTION, new 
ThrowableArtifact(e.getRootCause()));

Modified: 
openejb/trunk/openejb/server/openejb-multicast/src/main/java/org/apache/openejb/server/discovery/MultipointDiscoveryAgent.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/server/openejb-multicast/src/main/java/org/apache/openejb/server/discovery/MultipointDiscoveryAgent.java?rev=1308022&r1=1308021&r2=1308022&view=diff
==============================================================================
--- 
openejb/trunk/openejb/server/openejb-multicast/src/main/java/org/apache/openejb/server/discovery/MultipointDiscoveryAgent.java
 (original)
+++ 
openejb/trunk/openejb/server/openejb-multicast/src/main/java/org/apache/openejb/server/discovery/MultipointDiscoveryAgent.java
 Sun Apr  1 06:52:32 2012
@@ -16,6 +16,8 @@
  */
 package org.apache.openejb.server.discovery;
 
+import org.apache.openejb.monitoring.Event;
+import org.apache.openejb.monitoring.Managed;
 import org.apache.openejb.server.SelfManaging;
 import org.apache.openejb.server.ServerService;
 import org.apache.openejb.server.ServiceException;
@@ -33,6 +35,7 @@ import java.io.OutputStream;
 import java.net.Socket;
 import java.net.URI;
 import java.util.LinkedHashSet;
+import java.util.List;
 import java.util.Properties;
 import java.util.Set;
 import java.util.StringTokenizer;
@@ -47,21 +50,30 @@ public class MultipointDiscoveryAgent im
 
     private AtomicBoolean running = new AtomicBoolean(false);
 
+    @Managed
     private String host = "127.0.0.1";
+
+    @Managed
     private int port = 4212;
 
     private String initialServers = "";
 
     private long heartRate = 500;
 
+    @Managed(append = false)
     private Tracker tracker;
+
     private MultipointServer multipointServer;
+
     private boolean debug = true;
     private String name;
     private String discoveryHost;
     private Set<URI> roots;
     private Duration reconnectDelay;
 
+    @Managed
+    private final Event restarts = new Event();
+
     public MultipointDiscoveryAgent() {
     }
 
@@ -80,7 +92,7 @@ public class MultipointDiscoveryAgent im
         initialServers = options.get("initialServers", initialServers);
         heartRate = options.get("heart_rate", heartRate);
         discoveryHost = options.get("discoveryHost", host);
-        name = options.get("discoveryName", MultipointServer.randomColor());
+        name = name != null ? name : options.get("discoveryName", 
MultipointServer.randomColor());
         reconnectDelay = options.get("reconnectDelay", new Duration("30 
seconds"));
 
         final Set<URI> uris = new LinkedHashSet<URI>();
@@ -88,8 +100,14 @@ public class MultipointDiscoveryAgent im
         // Connect the initial set of peer servers
         StringTokenizer st = new StringTokenizer(initialServers, ",");
         while (st.hasMoreTokens()) {
-            URI uri = URI.create("conn://" + st.nextToken().trim());
-            uris.add(uri);
+            final String string = st.nextToken().trim();
+            if (string.startsWith("conn://")) {
+                final URI uri = URI.create(string);
+                uris.add(uri);
+            } else {
+                final URI uri = URI.create("conn://" + string);
+                uris.add(uri);
+            }
         }
 
         roots = uris;
@@ -111,6 +129,7 @@ public class MultipointDiscoveryAgent im
         return host;
     }
 
+    @Override
     public String getName() {
         return "multipoint";
     }
@@ -147,11 +166,13 @@ public class MultipointDiscoveryAgent im
      *
      * @throws Exception
      */
+    @Managed
     public void start() throws ServiceException {
         try {
             if (running.compareAndSet(false, true)) {
-
+                log.info("MultipointDiscoveryAgent Starting");
                 multipointServer = new MultipointServer(host, discoveryHost, 
port, tracker, name, debug, roots, reconnectDelay).start();
+                log.info("MultipointDiscoveryAgent Started");
 
                 this.port = multipointServer.getPort();
 
@@ -161,13 +182,22 @@ public class MultipointDiscoveryAgent im
         }
     }
 
+    @Managed
+    public void restart() throws ServiceException {
+        stop();
+        start();
+        restarts.record();
+    }
+
     /**
      * stop the channel
      *
      * @throws Exception
      */
+    @Managed
     public void stop() throws ServiceException {
         if (running.compareAndSet(true, false)) {
+            log.info("MultipointDiscoveryAgent Stopping");
             multipointServer.stop();
         }
     }
@@ -185,4 +215,95 @@ public class MultipointDiscoveryAgent im
     public void setHost(String host) {
         this.host = host;
     }
+
+    @Managed
+    public URI getURI() {
+        return multipointServer.getMe();
+    }
+
+    @Managed
+    public Set<URI> getRoots() {
+        return multipointServer.getRoots();
+    }
+
+    @Managed
+    public long getRuns() {
+        return multipointServer.getRuns().get();
+    }
+
+    @Managed
+    public String getRunsLatest() {
+        return multipointServer.getRuns().getLatest();
+    }
+
+    @Managed
+    public long getRunsLatestTime() {
+        return multipointServer.getRuns().getLatestTime();
+    }
+
+    @Managed
+    public long getHeartbeats() {
+        return multipointServer.getHeartbeats().get();
+    }
+
+    @Managed
+    public String getHeartbeatsLatest() {
+        return multipointServer.getHeartbeats().getLatest();
+    }
+
+    @Managed
+    public long getHeartbeatsLatestTime() {
+        return multipointServer.getHeartbeats().getLatestTime();
+    }
+
+    @Managed
+    public long getSessionsCreated() {
+        return multipointServer.getSessionsCreated().get();
+    }
+
+    @Managed
+    public String getSessionsCreatedLatest() {
+        return multipointServer.getSessionsCreated().getLatest();
+    }
+
+    @Managed
+    public long getSessionsCreatedLatestTime() {
+        return multipointServer.getSessionsCreated().getLatestTime();
+    }
+
+    @Managed
+    public long getReconnects() {
+        return multipointServer.getReconnects().get();
+    }
+
+    @Managed
+    public String getReconnectsLatest() {
+        return multipointServer.getReconnects().getLatest();
+    }
+
+    @Managed
+    public long getReconnectsLatestTime() {
+        return multipointServer.getReconnects().getLatestTime();
+    }
+
+    @Managed
+    public long getJoined() {
+        return multipointServer.getJoined();
+    }
+
+    @Managed
+    public List<URI> getSessions() {
+        return multipointServer.getSessions();
+    }
+
+    @Managed
+    public List<URI> getConnectionsQueued() {
+        return multipointServer.getConnectionsQueued();
+    }
+
+    @Managed
+    public long getReconnectDelay() {
+        return multipointServer.getReconnectDelay();
+    }
+
 }
\ No newline at end of file

Modified: 
openejb/trunk/openejb/server/openejb-multicast/src/main/java/org/apache/openejb/server/discovery/MultipointServer.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/server/openejb-multicast/src/main/java/org/apache/openejb/server/discovery/MultipointServer.java?rev=1308022&r1=1308021&r2=1308022&view=diff
==============================================================================
--- 
openejb/trunk/openejb/server/openejb-multicast/src/main/java/org/apache/openejb/server/discovery/MultipointServer.java
 (original)
+++ 
openejb/trunk/openejb/server/openejb-multicast/src/main/java/org/apache/openejb/server/discovery/MultipointServer.java
 Sun Apr  1 06:52:32 2012
@@ -16,6 +16,8 @@
  */
 package org.apache.openejb.server.discovery;
 
+import org.apache.openejb.monitoring.Event;
+import org.apache.openejb.monitoring.Managed;
 import org.apache.openejb.server.ServerRuntimeException;
 import org.apache.openejb.util.Duration;
 import org.apache.openejb.util.Join;
@@ -51,20 +53,32 @@ import java.util.Random;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 /**
  * @version $Rev$ $Date$
  */
+@Managed
 public class MultipointServer {
-    private static final Logger log = 
Logger.getInstance(LogCategory.OPENEJB_SERVER.createChild("discovery"), 
MultipointServer.class);
+    private static final Logger log = 
Logger.getInstance(LogCategory.OPENEJB_SERVER.createChild("discovery").createChild("multipoint"),
 MultipointServer.class);
 
     private static final URI END_LIST = URI.create("end:list");
 
     private final int port;
-    private final Selector selector;
+
     private final URI me;
+
     private final Set<URI> roots = new LinkedHashSet<URI>();
 
+    private final Event runs = new Event();
+
+    private final Event heartbeats = new Event();
+
+    private final Event reconnects = new Event();
+    private final Event sessionsCreated = new Event();
+
     /**
      * Only used for toString to make debugging easier
      */
@@ -74,11 +88,19 @@ public class MultipointServer {
 
     private final LinkedList<URI> connect = new LinkedList<URI>();
     private final Map<URI, Session> connections = new HashMap<URI, Session>();
-    private boolean debug = true;
 
     private long joined = 0;
+
     private long reconnectDelay;
 
+    private ServerSocketChannel serverChannel;
+
+    private final Selector selector;
+
+    private final Lock lock = new ReentrantLock();
+    private final Condition started = lock.newCondition();
+    private final Condition stopped = lock.newCondition();
+
     public MultipointServer(int port, Tracker tracker) throws IOException {
         this("localhost", "localhost", port, tracker, randomColor(), true, 
Collections.EMPTY_SET, new Duration(30, TimeUnit.SECONDS));
     }
@@ -92,7 +114,7 @@ public class MultipointServer {
 
         this.tracker = tracker;
         this.name = name;
-        this.debug = debug;
+
         if (roots != null) {
             this.roots.addAll(roots);
         }
@@ -110,9 +132,11 @@ public class MultipointServer {
 
         log.debug(format);
 
-        final InetSocketAddress address = new InetSocketAddress(bindHost, 
port);
 
-        final ServerSocketChannel serverChannel = ServerSocketChannel.open();
+        selector = Selector.open();
+
+        final InetSocketAddress address = new InetSocketAddress(bindHost, 
port);
+        serverChannel = ServerSocketChannel.open();
         serverChannel.configureBlocking(false);
 
         final ServerSocket serverSocket = serverChannel.socket();
@@ -125,13 +149,55 @@ public class MultipointServer {
             me = URI.create("conn://" + broadcastHost + ":" + this.port);
         }
 
-        selector = Selector.open();
-
         serverChannel.register(selector, SelectionKey.OP_ACCEPT);
 
         println("Broadcasting");
     }
 
+    public URI getMe() {
+        return me;
+    }
+
+    public Set<URI> getRoots() {
+        return roots;
+    }
+
+    public Event getRuns() {
+        return runs;
+    }
+
+    public Event getHeartbeats() {
+        return heartbeats;
+    }
+
+    public Event getReconnects() {
+        return reconnects;
+    }
+
+    public Event getSessionsCreated() {
+        return sessionsCreated;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public long getJoined() {
+        return joined;
+    }
+
+    public List<URI> getSessions() {
+        return new ArrayList<URI>(connections.keySet());
+    }
+
+    public List<URI> getConnectionsQueued() {
+        return new ArrayList<URI>(connect);
+    }
+
+    public long getReconnectDelay() {
+        return reconnectDelay;
+    }
+
     public int getPort() {
         return port;
     }
@@ -147,6 +213,10 @@ public class MultipointServer {
         if (connect.size() > 0) return;
         if (System.nanoTime() - joined <= reconnectDelay) return;
 
+        log.info("MultipointReconnect{initialServers=" + roots.size() + "}");
+
+        reconnects.record();
+
         for (URI root : roots) {
             connect(root);
         }
@@ -155,19 +225,63 @@ public class MultipointServer {
     }
     public MultipointServer start() {
         if (running.compareAndSet(false, true)) {
+
+            String multipointServer = Join.join(".", "MultipointServer", name, 
port);
+            log.info("MultipointServer Starting : Thread '" + multipointServer 
+ "'");
+
             Thread thread = new Thread(new Runnable() {
                 public void run() {
-                    _run();
+                    signal(started);
+                    try {
+                        _run();
+                    } finally {
+                        signal(stopped);
+                    }
                 }
             });
-            thread.setName(Join.join(".", "MultipointServer", name, port));
+            thread.setName(multipointServer);
             thread.start();
+
+            await(started, 10, TimeUnit.SECONDS);
         }
         return this;
     }
 
+    private void signal(Condition condition) {
+        lock.lock();
+        try {
+            condition.signal();
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    private void await(Condition condition, long time, TimeUnit unit) {
+        lock.lock();
+        try {
+            condition.await(time, unit);
+        } catch (InterruptedException e) {
+            Thread.interrupted();
+        } finally {
+            lock.unlock();
+        }
+    }
+
     public void stop() {
         running.set(false);
+        try {
+            serverChannel.close();
+        } catch (IOException e) {
+            throw new CloseException(e);
+        } finally {
+            await(stopped, 10, TimeUnit.SECONDS);
+        }
+    }
+
+    public static class CloseException extends RuntimeException {
+        public CloseException(Throwable cause) {
+            super(cause);
+        }
     }
 
     public class Session {
@@ -178,8 +292,11 @@ public class MultipointServer {
         private final ByteBuffer read = ByteBuffer.allocate(1024);
         private final SelectionKey key;
         private final List<URI> listed = new ArrayList<URI>();
+        private final long created = System.currentTimeMillis();
 
         private ByteBuffer write;
+
+        @Managed
         private State state = State.OPEN;
         private URI uri;
         public boolean hangup;
@@ -190,6 +307,8 @@ public class MultipointServer {
             this.client = uri != null;
             this.uri = uri != null ? uri : URI.create("conn://" + 
address.getHostName() + ":" + address.getPort());
             this.key = channel.register(selector, 0, this);
+            sessionsCreated.record();
+            log.info("Constructing " + this);
         }
 
         public Session ops(int ops) {
@@ -197,8 +316,17 @@ public class MultipointServer {
             return this;
         }
 
+        public long getCreated() {
+            return created;
+        }
+
         public void state(int ops, State state) {
 //            trace("transition "+state +"  "+ops);
+            if (this.state != state) {
+                if (log.isDebugEnabled()) {
+                    log.debug(message(state.name()));
+                }
+            }
             this.state = state;
             if (ops > 0) key.interestOps(ops);
         }
@@ -210,8 +338,9 @@ public class MultipointServer {
         private void trace(String str) {
 //            println(message(str));
 
-            if (debug && log.isDebugEnabled()) {
+            if (log.isDebugEnabled()) {
                 log.debug(message(str));
+//                new Exception().fillInStackTrace().printStackTrace();
             }
         }
 
@@ -297,6 +426,7 @@ public class MultipointServer {
         public String toString() {
             return "Session{" +
                     "uri=" + uri +
+                    ", created=" + created +
                     ", state=" + state +
                     ", owner=" + port +
                     ", s=" + (client ? channel.socket().getPort() : 
channel.socket().getLocalPort()) +
@@ -321,11 +451,12 @@ public class MultipointServer {
         }
 
         private void heartbeat() throws IOException {
+            heartbeats.record();
 
             final Set<String> strings = tracker.getRegisteredServices();
-            for (String string : strings) {
-                trace(string);
-            }
+//            for (String string : strings) {
+//                trace(string);
+//            }
             write(strings);
             state(SelectionKey.OP_READ | SelectionKey.OP_WRITE, 
State.HEARTBEAT);
         }
@@ -351,15 +482,26 @@ public class MultipointServer {
         // on each iteration of the loop, shrinking it down just a little to a
         // account for the execution time of the loop itself.
 
+        int failed = 0;
         while (running.get()) {
+            runs.record();
 
             final long start = System.nanoTime();
 
             try {
                 selector.select(selectorTimeout);
+                failed = 0;
             } catch (IOException ex) {
-                ex.printStackTrace();
-                break;
+                if (failed++ > 100) {
+                    log.fatal("Too many Multipoint Failures.  Terminating 
service.", ex);
+                    return;
+                }
+                log.error("Multipoint Failure.", ex);
+                try {
+                    Thread.sleep(100);
+                } catch (InterruptedException e) {
+                    Thread.interrupted();
+                }
             }
 
             final Set keys = selector.selectedKeys();
@@ -494,7 +636,7 @@ public class MultipointServer {
                         // CLIENTs list last, so at this point we've read
                         // the server's list and have written ours
 
-                        session.trace("DONE WRITING");
+//                        session.trace("DONE WRITING");
 
                         session.state(SelectionKey.OP_READ, State.HEARTBEAT);
 
@@ -515,7 +657,7 @@ public class MultipointServer {
 
                     session.last = System.currentTimeMillis();
 
-                    session.trace("send");
+//                    session.trace("send");
 
                     session.state(SelectionKey.OP_READ, State.HEARTBEAT);
 
@@ -580,7 +722,7 @@ public class MultipointServer {
 
                 while ((message = session.read()) != null) {
 
-                    session.trace(message);
+//                    session.trace(message);
 
                     final URI uri = URI.create(message);
 
@@ -648,7 +790,7 @@ public class MultipointServer {
 
                 String message = null;
                 while ((message = session.read()) != null) {
-                    session.trace(message);
+//                    session.trace(message);
                     tracker.processData(message);
                 }
             }
@@ -718,7 +860,6 @@ public class MultipointServer {
     private void close(SelectionKey key) {
         final Session session = (Session) key.attachment();
 
-        session.state(0, State.CLOSED);
 
         if (session.hangup) {
             // This was a duplicate connection and was closed
@@ -726,14 +867,17 @@ public class MultipointServer {
             // map as this particular session is not in that
             // map -- only the good session that will not be
             // closed is in there.
+            log.info("Hungup " + session);
             session.trace("hungup");
         } else {
+            log.info("Closed " + session);
             session.trace("closed");
             synchronized (connect) {
                 connections.remove(session.uri);
             }
         }
 
+        session.state(0, State.CLOSED);
         hangup(key);
     }
 
@@ -759,6 +903,7 @@ public class MultipointServer {
 
         synchronized (connect) {
             if (!connections.containsKey(uri) && !connect.contains(uri)) {
+                log.debug("Queuing{uri=" + uri + "}");
                 connect.addLast(uri);
             }
         }
@@ -771,15 +916,36 @@ public class MultipointServer {
 //            Session duplicate = null;
 
             if (duplicate != null) {
+
+
                 session.trace("duplicate");
 
                 // At this point we know we have two sockets open
-                // to the client, one created by them and one created
-                // by us.  We will both have detected this situation
+                // to the client, this can happen in two different ways
+                //
+                //  1. one created by them and one created by us.
+                //  2. two created by them and none created by us.
+                //
+                // For case #1, we will both have detected this situation
                 // and know it needs fixing.  Only one of us can hangup
+                //
+                // For case #2, the client was likely disconnected and
+                // is calling back.
 
                 final Session[] sessions = {session, duplicate};
-                Arrays.sort(sessions, new Comparator<Session>() {
+
+                if (!sessions[0].client && !sessions[1].client) {
+                    // Case 1 -- Client is calling back
+                    Arrays.sort(sessions, new Comparator<Session>() {
+                        @Override
+                        public int compare(Session a, Session b) {
+                            return (int) (b.created - a.created);
+                        }
+                    });
+                } else {
+                    // Case 2 -- We called each other at the same time
+
+                    Arrays.sort(sessions, new Comparator<Session>() {
                     // Goal: Keep the connection with the lowest port number
                     ///
                     // Low vs high is not very significant.  The critical
@@ -812,6 +978,7 @@ public class MultipointServer {
                         return !a.client ? socket.getPort() : 
socket.getLocalPort();
                     }
                 });
+                }
 
                 session = sessions[0];
                 duplicate = sessions[1];

Modified: 
openejb/trunk/openejb/server/openejb-multicast/src/main/java/org/apache/openejb/server/discovery/Tracker.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/server/openejb-multicast/src/main/java/org/apache/openejb/server/discovery/Tracker.java?rev=1308022&r1=1308021&r2=1308022&view=diff
==============================================================================
--- 
openejb/trunk/openejb/server/openejb-multicast/src/main/java/org/apache/openejb/server/discovery/Tracker.java
 (original)
+++ 
openejb/trunk/openejb/server/openejb-multicast/src/main/java/org/apache/openejb/server/discovery/Tracker.java
 Sun Apr  1 06:52:32 2012
@@ -16,10 +16,12 @@
  */
 package org.apache.openejb.server.discovery;
 
+import org.apache.openejb.monitoring.Managed;
 import org.apache.openejb.server.DiscoveryListener;
 import org.apache.openejb.util.Logger;
 import org.apache.openejb.util.LogCategory;
 
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
@@ -35,14 +37,21 @@ import java.io.IOException;
 /**
  * @version $Rev$ $Date$
 */
+@Managed(append = false)
 public class Tracker {
     
     private final Logger log;
     
+    @Managed
     private final String group;
     private final String groupPrefix;
+
+    @Managed
     private final long heartRate;
+
+    @Managed
     private final int maxMissedHeartbeats;
+
     private final long reconnectDelay;
     private final long maxReconnectDelay;
     private final int maxReconnectAttempts;
@@ -87,6 +96,16 @@ public class Tracker {
         return registeredServices.keySet();
     }
 
+    @Managed
+    public Set<String> getServicesRegistered() {
+        return new HashSet<String>(registeredServices.keySet());
+    }
+
+    @Managed
+    public Set<String> getServicesDiscovered() {
+        return new HashSet<String>(discoveredServices.keySet());
+    }
+
     public void registerService(URI serviceUri) throws IOException {
         Service service = new Service(serviceUri);
         this.registeredServices.put(service.broadcastString, service);
@@ -226,8 +245,11 @@ public class Tracker {
         }
     }
 
+    @Managed
     public class Service {
+        @Managed
         private final URI uri;
+        @Managed
         private final String broadcastString;
 
         public Service(URI uri) {
@@ -253,11 +275,16 @@ public class Tracker {
 
     private class ServiceVitals {
 
+        @Managed
         private final Service service;
 
+        @Managed
         private long lastHeartBeat;
+        @Managed
         private long recoveryTime;
+        @Managed
         private int failureCount;
+        @Managed
         private boolean dead;
 
         public ServiceVitals(Service service) {

Modified: 
openejb/trunk/openejb/server/openejb-multicast/src/test/java/org/apache/openejb/server/discovery/MultipointDiscoveryAgentTest.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/server/openejb-multicast/src/test/java/org/apache/openejb/server/discovery/MultipointDiscoveryAgentTest.java?rev=1308022&r1=1308021&r2=1308022&view=diff
==============================================================================
--- 
openejb/trunk/openejb/server/openejb-multicast/src/test/java/org/apache/openejb/server/discovery/MultipointDiscoveryAgentTest.java
 (original)
+++ 
openejb/trunk/openejb/server/openejb-multicast/src/test/java/org/apache/openejb/server/discovery/MultipointDiscoveryAgentTest.java
 Sun Apr  1 06:52:32 2012
@@ -17,10 +17,16 @@
 package org.apache.openejb.server.discovery;
 
 import junit.framework.TestCase;
+import org.apache.openejb.monitoring.LocalMBeanServer;
+import org.apache.openejb.monitoring.ManagedMBean;
+import org.apache.openejb.monitoring.ObjectNameBuilder;
 import org.apache.openejb.server.DiscoveryListener;
 import org.apache.openejb.server.DiscoveryRegistry;
 import org.apache.openejb.util.Join;
 
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.List;
@@ -28,18 +34,42 @@ import java.util.Properties;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.ErrorManager;
+import java.util.logging.Filter;
+import java.util.logging.Formatter;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
 
 /**
  * @version $Rev$ $Date$
  */
 public class MultipointDiscoveryAgentTest extends TestCase {
 
+//    static {
+//        final FilteredHandler consoleHandler = new FilteredHandler(new 
ConsoleHandler(), new LogRecordFilter() {
+//            @Override
+//            public boolean accept(LogRecord record) {
+//                return Thread.currentThread().getName().contains("red");
+//            }
+//        });
+//        consoleHandler.setLevel(Level.FINEST);
+//
+//        final Logger logger = Logger.getLogger("OpenEJB.server.discovery");
+//        logger.addHandler(consoleHandler);
+//        logger.setLevel(Level.FINEST);
+//        logger.setUseParentHandlers(false);
+//    }
+
     public void test() throws Exception {
-        System.setProperty("log4j.category.OpenEJB.server.discovery", "debug");
+//        System.setProperty("logging.level.OpenEJB.server.discovery", 
"debug");
 
         final URI testService = new URI("green://localhost:0");
 
-        final int PEERS = 4;
+        final String[] names = {"red"};
+        final int PEERS = names.length;
 
         final CountDownLatch[] latches = {
                 new CountDownLatch(PEERS + 1),
@@ -63,13 +93,12 @@ public class MultipointDiscoveryAgentTes
         };
 
         final List<Node> nodes = new ArrayList<Node>();
-        final Node root = new Node(0, listener);
-
+        final Node root = new Node(0, listener, "root");
 
         nodes.add(root);
 
-        for (int i = 0; i < PEERS; i++) {
-            final Node node = new Node(0, listener, root.getAgent().getPort());
+        for (String name : names) {
+            final Node node = new Node(0, listener, name, root.getURI());
             nodes.add(node);
         }
 
@@ -124,7 +153,7 @@ public class MultipointDiscoveryAgentTes
 
     private Node launch(Node green, String color, int port) throws Exception {
         final URI orangeService = new URI(color + "://localhost:"+ port);
-        final Node orange = new Node(port, new Listener(color), 
green.getPort());
+        final Node orange = new Node(port, new Listener(color), color, 
green.getURI());
         orange.getRegistry().registerService(orangeService);
         Thread.sleep(100);
         return orange;
@@ -133,21 +162,18 @@ public class MultipointDiscoveryAgentTes
     public static class Node {
         private final MultipointDiscoveryAgent agent;
         private final DiscoveryRegistry registry;
+        private final String name;
 
-        public Node(int p, DiscoveryListener listener, int... peers) throws 
Exception {
-            this(p, listener, false, null, 100, 2, peers);
+        public Node(int p, DiscoveryListener listener, String name, URI... 
uris) throws Exception {
+            this(p, listener, false, name, 100, 2, uris);
         }
 
-        public Node(int p, DiscoveryListener listener, boolean debug, String 
name, int heartRate, int maxMissHeartBeats, int... peers) throws Exception {
+        public Node(int p, DiscoveryListener listener, boolean debug, String 
name, int heartRate, int maxMissHeartBeats, URI... uris) throws Exception {
             this.agent = new MultipointDiscoveryAgent(debug, name);
+            this.name = name;
             final Properties props = new Properties();
             props.put("port", p+"");
 
-            List<String> uris = new ArrayList<String>(peers.length);
-            for (int port : peers) {
-                uris.add("localhost:"+port);
-            }
-
             props.put("initialServers", Join.join(",", uris));
             props.put("max_missed_heartbeats", "1");
             props.put("heart_rate", "" + heartRate);
@@ -156,7 +182,23 @@ public class MultipointDiscoveryAgentTes
 
             this.registry = new DiscoveryRegistry(agent);
             this.registry.addDiscoveryListener(listener);
+
+
             agent.start();
+
+//            final ObjectNameBuilder jmxName = new 
ObjectNameBuilder("openejb.management");
+//            jmxName.set("type", "ServerService");
+//            jmxName.set("name", "multipoint");
+//            jmxName.set("port", Integer.toString(agent.getPort()));
+//
+//            MBeanServer server = LocalMBeanServer.get();
+//            try {
+//                final ObjectName objectName = jmxName.build();
+//                server.registerMBean(new ManagedMBean(agent), objectName);
+//            } catch (Exception e) {
+//                e.printStackTrace();
+//            }
+
         }
 
         public MultipointDiscoveryAgent getAgent() {
@@ -170,11 +212,19 @@ public class MultipointDiscoveryAgentTes
         public int getPort() {
             return agent.getPort();
         }
+
+        public URI getURI() {
+            return URI.create("conn://localhost:" + getPort() + "/" + name);
+        }
     }
 
     private static class Listener implements DiscoveryListener {
         private final String name;
 
+        public String getName() {
+            return name;
+        }
+
         private Listener(String name) {
             this.name = name;
         }
@@ -186,5 +236,98 @@ public class MultipointDiscoveryAgentTes
         public void serviceRemoved(URI service) {
 //            System.out.printf("[%s] removed = %s\n", name, service);
         }
+
+        @Override
+        public String toString() {
+            return name;
+        }
+    }
+
+
+    public static interface LogRecordFilter {
+        public boolean accept(LogRecord record);
+    }
+
+    public static class FilteredHandler extends Handler {
+
+        private final Handler handler;
+        private final LogRecordFilter filter;
+
+        public FilteredHandler(Handler handler, LogRecordFilter filter) {
+            this.handler = handler;
+            this.filter = filter;
+        }
+
+        @Override
+        public void publish(LogRecord record) {
+            handler.publish(record);
+//            if (filter.accept(record)) {
+//            }
+        }
+
+        @Override
+        public void flush() {
+            handler.flush();
+        }
+
+        @Override
+        public void close() throws SecurityException {
+            handler.close();
+        }
+
+        @Override
+        public void setFormatter(Formatter newFormatter) throws 
SecurityException {
+            handler.setFormatter(newFormatter);
+        }
+
+        @Override
+        public Formatter getFormatter() {
+            return handler.getFormatter();
+        }
+
+        @Override
+        public void setEncoding(String encoding) throws SecurityException, 
UnsupportedEncodingException {
+            handler.setEncoding(encoding);
+        }
+
+        @Override
+        public String getEncoding() {
+            return handler.getEncoding();
+        }
+
+        @Override
+        public void setFilter(Filter newFilter) throws SecurityException {
+            handler.setFilter(newFilter);
+        }
+
+        @Override
+        public Filter getFilter() {
+            return handler.getFilter();
+        }
+
+        @Override
+        public void setErrorManager(ErrorManager em) {
+            handler.setErrorManager(em);
+        }
+
+        @Override
+        public ErrorManager getErrorManager() {
+            return handler.getErrorManager();
+        }
+
+        @Override
+        public void setLevel(Level newLevel) throws SecurityException {
+            handler.setLevel(newLevel);
+        }
+
+        @Override
+        public Level getLevel() {
+            return handler.getLevel();
+        }
+
+        @Override
+        public boolean isLoggable(LogRecord record) {
+            return handler.isLoggable(record);
+        }
     }
 }

Modified: 
openejb/trunk/openejb/server/openejb-server/src/main/java/org/apache/openejb/server/ServiceManager.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/server/openejb-server/src/main/java/org/apache/openejb/server/ServiceManager.java?rev=1308022&r1=1308021&r2=1308022&view=diff
==============================================================================
--- 
openejb/trunk/openejb/server/openejb-server/src/main/java/org/apache/openejb/server/ServiceManager.java
 (original)
+++ 
openejb/trunk/openejb/server/openejb-server/src/main/java/org/apache/openejb/server/ServiceManager.java
 Sun Apr  1 06:52:32 2012
@@ -22,11 +22,16 @@ import org.apache.openejb.assembler.clas
 import org.apache.openejb.loader.FileUtils;
 import org.apache.openejb.loader.IO;
 import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.monitoring.LocalMBeanServer;
+import org.apache.openejb.monitoring.ManagedMBean;
+import org.apache.openejb.monitoring.ObjectNameBuilder;
 import org.apache.openejb.util.LogCategory;
 import org.apache.openejb.util.Logger;
 import org.apache.xbean.recipe.ObjectRecipe;
 import org.apache.xbean.recipe.Option;
 
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -157,6 +162,19 @@ public abstract class ServiceManager {
                     registry.addDiscoveryAgent(agent);
                 }
 
+                MBeanServer server = LocalMBeanServer.get();
+
+                final ObjectNameBuilder jmxName = new 
ObjectNameBuilder("openejb");
+                jmxName.set("type", "ServerService");
+                jmxName.set("name", serviceName);
+
+                try {
+                    final ObjectName objectName = jmxName.build();
+                    server.registerMBean(new ManagedMBean(service), 
objectName);
+                } catch (Exception e) {
+                    logger.error("Unable to register MBean ", e);
+                }
+
                 return service;
             } catch (Throwable t) {
                 logger.error("service.instantiation.err", t, 
serviceClass.getName(), t.getClass().getName(), t.getMessage());


Reply via email to