[jboss-cvs] JBossAS SVN: r87971 - in projects/bootstrap/trunk: impl-base/src/main/java/org/jboss/bootstrap/impl/base/server and 4 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Wed Apr 29 00:13:43 EDT 2009


Author: ALRubinger
Date: 2009-04-29 00:13:43 -0400 (Wed, 29 Apr 2009)
New Revision: 87971

Added:
   projects/bootstrap/trunk/impl-base/src/test/java/org/jboss/bootstrap/impl/base/server/TestNoOpServerMBean.java
   projects/bootstrap/trunk/impl-base/src/test/java/org/jboss/bootstrap/impl/base/server/unit/JmxNotificationsTestCase.java
Modified:
   projects/bootstrap/trunk/impl-as/src/main/java/org/jboss/bootstrap/impl/as/server/JBossASServer.java
   projects/bootstrap/trunk/impl-base/src/main/java/org/jboss/bootstrap/impl/base/server/AbstractServer.java
   projects/bootstrap/trunk/impl-base/src/test/java/org/jboss/bootstrap/impl/base/server/TestNoOpServer.java
   projects/bootstrap/trunk/spi/src/main/java/org/jboss/bootstrap/spi/lifecycle/LifecycleState.java
   projects/bootstrap/trunk/spi/src/main/java/org/jboss/bootstrap/spi/server/Server.java
Log:
[JBBOOT-53] Fire JMX start/stop events in server lifecycle

Modified: projects/bootstrap/trunk/impl-as/src/main/java/org/jboss/bootstrap/impl/as/server/JBossASServer.java
===================================================================
--- projects/bootstrap/trunk/impl-as/src/main/java/org/jboss/bootstrap/impl/as/server/JBossASServer.java	2009-04-29 02:11:13 UTC (rev 87970)
+++ projects/bootstrap/trunk/impl-as/src/main/java/org/jboss/bootstrap/impl/as/server/JBossASServer.java	2009-04-29 04:13:43 UTC (rev 87971)
@@ -39,12 +39,10 @@
  */
 public interface JBossASServer extends MCBasedServer<JBossASServer, JBossASServerConfig>
 {
-   /** The JMX notification event type sent on end of server startup */
-   public final String START_NOTIFICATION_TYPE = "org.jboss.system.server.started";
+   //-------------------------------------------------------------------------------------||
+   // Contracts --------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
 
-   /** The JMX notification event type sent on begin of the server shutdown */
-   public final String STOP_NOTIFICATION_TYPE = "org.jboss.system.server.stopped";
-
    /** @return The server start date */
    Date getStartDate();
 

Modified: projects/bootstrap/trunk/impl-base/src/main/java/org/jboss/bootstrap/impl/base/server/AbstractServer.java
===================================================================
--- projects/bootstrap/trunk/impl-base/src/main/java/org/jboss/bootstrap/impl/base/server/AbstractServer.java	2009-04-29 02:11:13 UTC (rev 87970)
+++ projects/bootstrap/trunk/impl-base/src/main/java/org/jboss/bootstrap/impl/base/server/AbstractServer.java	2009-04-29 04:13:43 UTC (rev 87971)
@@ -30,6 +30,10 @@
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.CopyOnWriteArraySet;
 
+import javax.management.Notification;
+import javax.management.NotificationBroadcaster;
+import javax.management.NotificationBroadcasterSupport;
+
 import org.jboss.bootstrap.spi.Bootstrap;
 import org.jboss.bootstrap.spi.config.ConfigurationInitializer;
 import org.jboss.bootstrap.spi.config.ConfigurationValidator;
@@ -45,12 +49,14 @@
 /**
  * AbstractServer
  * 
- * Generic support for 
+ * Generic support for Server implementations
  *
  * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
  * @version $Revision: $
  */
-public abstract class AbstractServer<K extends Server<K, T>, T extends ServerConfig<T>> implements Server<K, T>
+public abstract class AbstractServer<K extends Server<K, T>, T extends ServerConfig<T>>
+      extends
+         NotificationBroadcasterSupport implements Server<K, T>, NotificationBroadcaster
 {
 
    //-------------------------------------------------------------------------------------||
@@ -73,7 +79,7 @@
     * Underlying configuration.  Must be a Thread-safe implementation
     * as it's exported
     */
-   private T configuration;
+   private volatile T configuration;
 
    /**
     * Validator for the configuration.  Synchronized on "this".  Requires
@@ -83,15 +89,17 @@
 
    /**
     * Initializer for the configuration.  Synchronized on "this".  Requires
-    * Thread-safe impl (as it's exported)
+    * Thread-safe impl (as it's exported).  Volatile for immediate 
+    * accessor return.
     */
-   private ConfigurationInitializer<T> configInitializer;
+   private volatile ConfigurationInitializer<T> configInitializer;
 
    /**
     * Server initializer.  Synchronized on "this".  Requires
-    * Thread-safe impl (as it's exported)
+    * Thread-safe impl (as it's exported).  Volatile for immediate 
+    * accessor return.
     */
-   private ServerInitializer<K, T> serverInitializer;
+   private volatile ServerInitializer<K, T> serverInitializer;
 
    /**
     * The list of bootstraps to run upon start, requires Thread-safe impl.
@@ -169,15 +177,9 @@
 
       // Set properties
       this.setConfiguration(configToSet);
-      try
-      {
-         this.setState(LifecycleState.PRE_INIT);
-      }
-      catch (final LifecycleEventException e)
-      {
-         // No handlers can be registered yet (this is still construction),
-         // so we can safely ignore lifecycle event problems
-      }
+      // Set the state directly (ie. bypass callback contract of setState()), 
+      // this isn't *really* a state change so much as an initialization
+      this.state = LifecycleState.PRE_INIT;
    }
 
    //-------------------------------------------------------------------------------------||
@@ -195,7 +197,9 @@
    /* (non-Javadoc)
     * @see org.jboss.bootstrap.spi.server.Server#setConfiguration(org.jboss.bootstrap.spi.config.ServerConfig)
     */
-   public void setConfiguration(final T configuration)
+   // Synchronized on "this" to ensure we don't set the config in the middle of some
+   // other lifecycle operation
+   public synchronized void setConfiguration(final T configuration)
    {
       // Log and set
       if (log.isTraceEnabled())
@@ -221,6 +225,7 @@
    /* (non-Javadoc)
     * @see org.jboss.bootstrap.spi.server.Server#shutdown()
     */
+   // Synchronized for atomicity
    public synchronized void shutdown() throws IllegalStateException, Exception
    {
       // Log
@@ -263,14 +268,21 @@
          serverInitializer.cleanup(this);
       }
 
-      // Done
+      // Send JMX Notification
+      this.sendStopJmxNotification();
+
+      // Done and set states
       log.info("Stopped: " + this);
+      // So we fire "stopped" events and draw the difference
+      // between IDLE (which may also designate pre-start)
+      this.setState(LifecycleState.STOPPED);
       this.setState(LifecycleState.IDLE);
    }
 
    /* (non-Javadoc)
     * @see org.jboss.bootstrap.spi.server.Server#start()
     */
+   // Synchronized for atomicity
    public synchronized void start() throws IllegalStateException, Exception
    {
       // Log
@@ -309,6 +321,9 @@
       }
       this.startBootstraps();
 
+      // Send JMX Start Notification
+      this.sendStartJmxNotification();
+
       // Done
       log.info("Started: " + this);
       this.setState(LifecycleState.STARTED);
@@ -356,6 +371,7 @@
    /* (non-Javadoc)
     * @see org.jboss.bootstrap.spi.server.Server#initialize()
     */
+   // Synchronized for atomicity
    public synchronized void initialize() throws IllegalStateException, InvalidConfigurationException,
          LifecycleEventException
    {
@@ -428,7 +444,7 @@
    /* (non-Javadoc)
     * @see org.jboss.bootstrap.spi.server.Server#getInitializer()
     */
-   public synchronized final ServerInitializer<K, T> getServerInitializer()
+   public final ServerInitializer<K, T> getServerInitializer()
    {
       return this.serverInitializer;
    }
@@ -449,7 +465,7 @@
    /* (non-Javadoc)
     * @see org.jboss.bootstrap.spi.server.Server#getConfigInitializer()
     */
-   public synchronized final ConfigurationInitializer<T> getConfigInitializer()
+   public final ConfigurationInitializer<T> getConfigInitializer()
    {
       return this.configInitializer;
    }
@@ -608,6 +624,38 @@
    //-------------------------------------------------------------------------------------||
 
    /**
+    * Sends the JMX Notification with type signaling the start of the server
+    */
+   protected void sendStartJmxNotification()
+   {
+      this.sendNotificationWithCurrentTimeUserData(START_NOTIFICATION_TYPE, 1);
+   }
+
+   /**
+    * Sends the JMX Notification with type signaling the stop of the server
+    */
+   protected void sendStopJmxNotification()
+   {
+      this.sendNotificationWithCurrentTimeUserData(STOP_NOTIFICATION_TYPE, 2);
+   }
+
+   /**
+    * Sends a JMX Notification with specified type and sequence number, 
+    * setting user data to the number of milliseconds since the epoch.
+    * 
+    * @param type
+    * @param sequenceNumber
+    */
+   protected final void sendNotificationWithCurrentTimeUserData(final String type, final int sequenceNumber)
+   {
+      // Send JMX Notification
+      final Notification startNotification = new Notification(type, this, sequenceNumber);
+      startNotification.setUserData(System.currentTimeMillis());
+      this.sendNotification(startNotification);
+      log.debug("Sent JMX Notification: " + type);
+   }
+
+   /**
     * Starts the bootstraps
     * 
     * @throws Exception
@@ -634,13 +682,13 @@
       final List<Bootstrap> startedBootstraps = this.getStartedBootstraps();
 
       // Signal 
-      for (Bootstrap bootstrap : startedBootstraps)
+      for (final Bootstrap bootstrap : startedBootstraps)
       {
          bootstrap.prepareShutdown(this);
       }
 
       // Do the bootstraps in reverse order
-      for (Bootstrap bootstrap : startedBootstraps)
+      for (final Bootstrap bootstrap : startedBootstraps)
       {
          try
          {
@@ -721,7 +769,7 @@
     * @throws InvalidConfigurationException If the configuration is invalid
     * @throws IllegalArgumentException If the confirguation has not been set
     */
-   private void validate(T configuration) throws InvalidConfigurationException, IllegalArgumentException
+   private void validate(final T configuration) throws InvalidConfigurationException, IllegalArgumentException
    {
       // Precondition check
       if (configuration == null)
@@ -730,7 +778,7 @@
       }
 
       // Get the validator
-      ConfigurationValidator<T> validator = this.getValidator();
+      final ConfigurationValidator<T> validator = this.getValidator();
 
       // Is specified, validate
       if (validator != null)

Modified: projects/bootstrap/trunk/impl-base/src/test/java/org/jboss/bootstrap/impl/base/server/TestNoOpServer.java
===================================================================
--- projects/bootstrap/trunk/impl-base/src/test/java/org/jboss/bootstrap/impl/base/server/TestNoOpServer.java	2009-04-29 02:11:13 UTC (rev 87970)
+++ projects/bootstrap/trunk/impl-base/src/test/java/org/jboss/bootstrap/impl/base/server/TestNoOpServer.java	2009-04-29 04:13:43 UTC (rev 87971)
@@ -36,7 +36,8 @@
  */
 public class TestNoOpServer extends AbstractServer<TestNoOpServer, TestServerConfig>
       implements
-         Server<TestNoOpServer, TestServerConfig>
+         Server<TestNoOpServer, TestServerConfig>,
+         TestNoOpServerMBean
 {
 
    //-------------------------------------------------------------------------------------||

Added: projects/bootstrap/trunk/impl-base/src/test/java/org/jboss/bootstrap/impl/base/server/TestNoOpServerMBean.java
===================================================================
--- projects/bootstrap/trunk/impl-base/src/test/java/org/jboss/bootstrap/impl/base/server/TestNoOpServerMBean.java	                        (rev 0)
+++ projects/bootstrap/trunk/impl-base/src/test/java/org/jboss/bootstrap/impl/base/server/TestNoOpServerMBean.java	2009-04-29 04:13:43 UTC (rev 87971)
@@ -0,0 +1,37 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.bootstrap.impl.base.server;
+
+/**
+ * TestNoOpServerMBean
+ * 
+ * Interface to meet JMX standard for registry of the 
+ * {@link TestNoOpServer} with an MBean Server 
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public interface TestNoOpServerMBean
+{
+   // Marker only
+}

Added: projects/bootstrap/trunk/impl-base/src/test/java/org/jboss/bootstrap/impl/base/server/unit/JmxNotificationsTestCase.java
===================================================================
--- projects/bootstrap/trunk/impl-base/src/test/java/org/jboss/bootstrap/impl/base/server/unit/JmxNotificationsTestCase.java	                        (rev 0)
+++ projects/bootstrap/trunk/impl-base/src/test/java/org/jboss/bootstrap/impl/base/server/unit/JmxNotificationsTestCase.java	2009-04-29 04:13:43 UTC (rev 87971)
@@ -0,0 +1,188 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.bootstrap.impl.base.server.unit;
+
+import java.lang.management.ManagementFactory;
+
+import javax.management.MBeanServer;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+
+import junit.framework.TestCase;
+
+import org.jboss.bootstrap.impl.base.server.TestNoOpServer;
+import org.jboss.bootstrap.spi.server.Server;
+import org.jboss.logging.Logger;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * JmxNotificationsTestCase
+ * 
+ * Tests to ensure that the JMX Notifications for 
+ * start/stop are received
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public class JmxNotificationsTestCase
+{
+   //-------------------------------------------------------------------------------------||
+   // Class Members ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   private static final Logger log = Logger.getLogger(JmxNotificationsTestCase.class);
+
+   /**
+    * JMX Object Name of the test server
+    */
+   private static final String OBJECT_NAME_TEST_SERVER = "org.jboss:type=TestServer";
+
+   //-------------------------------------------------------------------------------------||
+   // Instance Members -------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * The Server
+    */
+   private TestNoOpServer server;
+
+   /**
+    * Whether or not we got the start notification
+    */
+   private boolean gotStartNotification;
+
+   /**
+    * Whether or not we got the stop notification
+    */
+   private boolean gotStopNotification;
+
+   //-------------------------------------------------------------------------------------||
+   // Lifecycle --------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Initializes the test server, MBean server, and registers
+    * our test event listener
+    */
+   @Before
+   public void init() throws Throwable
+   {
+      // Make and set the test server
+      final TestNoOpServer server = new TestNoOpServer();
+      this.server = server;
+
+      // Make and set the MBean Server
+      final MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
+
+      // Install the test server into the MBean server
+      final ObjectName serverName = new ObjectName(OBJECT_NAME_TEST_SERVER);
+      mbeanServer.registerMBean(server, serverName);
+
+      // Register a listener
+      final NotificationListener listener = new JmxNotificationListener();
+      mbeanServer.addNotificationListener(serverName, listener, null, null);
+   }
+
+   @After
+   public void cleanup() throws Throwable
+   {
+      // Reset everything
+      this.gotStartNotification = false;
+      this.server = null;
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Tests ------------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Ensures that the JMX Notifications for start and stop
+    * were fired
+    */
+   @Test
+   public void testJmxNotifications() throws Throwable
+   {
+      // Log
+      log.info("testJmxNotifications");
+
+      // Get the server
+      final TestNoOpServer server = this.server;
+
+      // Start the server
+      server.start();
+
+      // Test
+      TestCase.assertTrue("Did not receive start notification", this.gotStartNotification);
+
+      // Stop the server
+      server.shutdown();
+
+      // Test
+      TestCase.assertTrue("Did not receive stop notification", this.gotStopNotification);
+
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Inner Classes ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Listens for JMX Notification events
+    */
+   private class JmxNotificationListener implements NotificationListener
+   {
+      //-------------------------------------------------------------------------------------||
+      // Required Implementations -----------------------------------------------------------||
+      //-------------------------------------------------------------------------------------||
+
+      /* (non-Javadoc)
+       * @see javax.management.NotificationListener#handleNotification(javax.management.Notification, java.lang.Object)
+       */
+      public void handleNotification(final Notification notification, final Object handback)
+      {
+         // Log
+         log.info("Got notification: " + notification);
+         log.debug("Notification handback: " + handback);
+
+         // Figure out the notification received
+         final String type = notification.getType();
+
+         // Take appropriate action
+         if (Server.START_NOTIFICATION_TYPE.equals(type))
+         {
+            // Set received
+            gotStartNotification = true;
+         }
+         else if (Server.STOP_NOTIFICATION_TYPE.equals(type))
+         {
+            // Set received
+            gotStopNotification = true;
+         }
+
+      }
+   }
+
+}

Modified: projects/bootstrap/trunk/spi/src/main/java/org/jboss/bootstrap/spi/lifecycle/LifecycleState.java
===================================================================
--- projects/bootstrap/trunk/spi/src/main/java/org/jboss/bootstrap/spi/lifecycle/LifecycleState.java	2009-04-29 02:11:13 UTC (rev 87970)
+++ projects/bootstrap/trunk/spi/src/main/java/org/jboss/bootstrap/spi/lifecycle/LifecycleState.java	2009-04-29 04:13:43 UTC (rev 87971)
@@ -28,10 +28,11 @@
  * Describes current state of the Server lifecycle
  * 
  * PREINIT == Instanciated, open to configuration, mutable operations permitted
- * IDLE == Not yet started, or has stopped.  Awaiting start.
+ * IDLE == Not yet started, or has previously stopped.  Awaiting start.
  * STARTING == In start lifecycle
  * STARTED == Fully started, in service
  * STOPPING == In stop lifecycle
+ * STOPPED == Transition state to denote fully stopped before returning to IDLE
  *
  * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
  * @version $Revision: $
@@ -42,5 +43,5 @@
     * Lifecycle States for Servers
     */
 
-   PRE_INIT, IDLE, STARTING, STARTED, STOPPING
+   PRE_INIT, IDLE, STARTING, STARTED, STOPPING, STOPPED
 }

Modified: projects/bootstrap/trunk/spi/src/main/java/org/jboss/bootstrap/spi/server/Server.java
===================================================================
--- projects/bootstrap/trunk/spi/src/main/java/org/jboss/bootstrap/spi/server/Server.java	2009-04-29 02:11:13 UTC (rev 87970)
+++ projects/bootstrap/trunk/spi/src/main/java/org/jboss/bootstrap/spi/server/Server.java	2009-04-29 04:13:43 UTC (rev 87971)
@@ -43,7 +43,20 @@
  */
 public interface Server<K extends Server<K, T>, T extends ServerConfig<T>>
 {
+   //-------------------------------------------------------------------------------------||
+   // Constants --------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
 
+   /** 
+    * The JMX notification event type sent on end of server startup 
+    */
+   public final String START_NOTIFICATION_TYPE = "org.jboss.system.server.started";
+
+   /** 
+    * The JMX notification event type sent on begin of the server shutdown  
+    */
+   public final String STOP_NOTIFICATION_TYPE = "org.jboss.system.server.stopped";
+
    //-------------------------------------------------------------------------------------||
    // Contracts --------------------------------------------------------------------------||
    //-------------------------------------------------------------------------------------||




More information about the jboss-cvs-commits mailing list