You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by ch...@apache.org on 2011/06/29 21:31:59 UTC

svn commit: r1141211 - in /activemq/activemq-apollo/trunk: apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/ apollo-cli/src/main/scala/org/apache/activemq/apollo/cli/commands/ apollo-dto/ apollo-dto/src/main/java/org/apache/activemq/apoll...

Author: chirino
Date: Wed Jun 29 19:31:58 2011
New Revision: 1141211

URL: http://svn.apache.org/viewvc?rev=1141211&view=rev
Log:
Fixes https://issues.apache.org/jira/browse/APLO-55 : Added an option to enable strict validation against the XSD schema.

Modified:
    activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/ConfigStore.scala
    activemq/activemq-apollo/trunk/apollo-cli/src/main/scala/org/apache/activemq/apollo/cli/commands/Run.scala
    activemq/activemq-apollo/trunk/apollo-cli/src/main/scala/org/apache/activemq/apollo/cli/commands/StoreExport.scala
    activemq/activemq-apollo/trunk/apollo-cli/src/main/scala/org/apache/activemq/apollo/cli/commands/StoreImport.scala
    activemq/activemq-apollo/trunk/apollo-dto/pom.xml
    activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/BrokerDTO.java
    activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/JsonCodec.java
    activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/XmlCodec.java
    activemq/activemq-apollo/trunk/apollo-util/src/main/scala/org/apache/activemq/apollo/util/BaseService.scala
    activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/JacksonJsonProvider.java
    activemq/activemq-apollo/trunk/apollo-website/src/documentation/user-manual.md

Modified: activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/ConfigStore.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/ConfigStore.scala?rev=1141211&r1=1141210&r2=1141211&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/ConfigStore.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/ConfigStore.scala Wed Jun 29 19:31:58 2011
@@ -21,8 +21,9 @@ import security.EncryptionSupport
 import org.apache.activemq.apollo.util._
 import FileSupport._
 import java.util.Properties
-import java.io.{FileInputStream, File}
 import org.apache.activemq.apollo.dto.{XmlCodec, BrokerDTO}
+import java.io.{InputStream, FileInputStream, File}
+import javax.xml.bind.{ValidationEvent, ValidationEventHandler}
 
 /**
  * <p>
@@ -32,12 +33,26 @@ import org.apache.activemq.apollo.dto.{X
  */
 object ConfigStore {
 
-  def load(file:File) = {
-    XmlCodec.decode(classOf[BrokerDTO], new FileInputStream(file), config_properties(file))
+  def load(file:File, func: (String)=>Unit):BrokerDTO = {
+    load(new FileInputStream(file), config_properties(file), func)
   }
 
-  def load_xml(in:Array[Byte]) = {
-    XmlCodec.decode(classOf[BrokerDTO], new ByteArrayInputStream(in), config_properties(null))
+  def load_xml(in:Array[Byte], func: (String)=>Unit):BrokerDTO = {
+    load(new ByteArrayInputStream(in), config_properties(null), func)
+  }
+
+  def load(is: => InputStream, prop:Properties, func: (String)=>Unit):BrokerDTO = {
+    XmlCodec.decode(classOf[BrokerDTO], is, prop, new ValidationEventHandler(){
+        def handleEvent(event: ValidationEvent): Boolean = {
+          val level = event.getSeverity match {
+            case 0=> "warning"
+            case 1=> "error"
+            case 2=> "fatal error"
+          }
+          func("% at (%d:%d): %s ".format(level, event.getLocator().getLineNumber(), event.getLocator().getColumnNumber(), event.getMessage()))
+          true
+        }
+    })
   }
 
   def config_properties(file:File): Properties = {

Modified: activemq/activemq-apollo/trunk/apollo-cli/src/main/scala/org/apache/activemq/apollo/cli/commands/Run.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-cli/src/main/scala/org/apache/activemq/apollo/cli/commands/Run.scala?rev=1141211&r1=1141210&r2=1141211&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-cli/src/main/scala/org/apache/activemq/apollo/cli/commands/Run.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-cli/src/main/scala/org/apache/activemq/apollo/cli/commands/Run.scala Wed Jun 29 19:31:58 2011
@@ -26,6 +26,8 @@ import org.apache.activemq.apollo.util.{
 import org.apache.log4j.PropertyConfigurator
 import java.io.{FileInputStream, File}
 import java.util.logging.LogManager
+import org.apache.activemq.apollo.dto.BrokerDTO
+import collection.mutable.ListBuffer
 
 /**
  * The apollo run command
@@ -73,17 +75,39 @@ class Run extends Action {
 
       Apollo.print_banner(session.getConsole)
 
+      def println(value:String) = session.getConsole.println(value)
+
       // Load the configs and start the brokers up.
-      session.getConsole.println("Loading configuration file '%s'.".format(conf))
+      println("Loading configuration file '%s'.".format(conf))
 
       val broker = new Broker()
-      broker.config = ConfigStore.load(conf)
+
+      val validation_messages = ListBuffer[String]()
+      try {
+        broker.config = ConfigStore.load(conf, validation_messages += _)
+      } finally {
+        if( !validation_messages.isEmpty) {
+          println("")
+          println("Broker configuration file failed the following validations:")
+          validation_messages.foreach{ v =>
+            println("")
+            println("  "+v)
+          }
+          println("")
+        }
+      }
+
+      if( broker.config.validation == "strict" && !validation_messages.isEmpty) {
+        session.getConsole.println("Strict validation was configured, shutting down")
+        return null
+      }
+
       broker.tmp = tmp
       broker.start()
 
       val broker_config_monitor = new FileMonitor(conf,broker.dispatch_queue {
         broker.console_log.info("Reloading configuration file '%s'.".format(conf))
-        broker.update(ConfigStore.load(conf), ^{
+        broker.update(ConfigStore.load(conf, x=> broker.console_log.info(x) ), ^{
         })
       })
       val log4j_config_monitor = new FileMonitor(log4j_config, {

Modified: activemq/activemq-apollo/trunk/apollo-cli/src/main/scala/org/apache/activemq/apollo/cli/commands/StoreExport.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-cli/src/main/scala/org/apache/activemq/apollo/cli/commands/StoreExport.scala?rev=1141211&r1=1141210&r2=1141211&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-cli/src/main/scala/org/apache/activemq/apollo/cli/commands/StoreExport.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-cli/src/main/scala/org/apache/activemq/apollo/cli/commands/StoreExport.scala Wed Jun 29 19:31:58 2011
@@ -59,7 +59,7 @@ class StoreExport extends Action {
         error("Configuration file'%s' does not exist.\n\nTry creating a broker instance using the 'apollo create' command.".format(conf));
       }
 
-      val config = ConfigStore.load(conf)
+      val config = ConfigStore.load(conf, session.getConsole.println _)
 
       val hosts = collection.JavaConversions.collectionAsScalaIterable(config.virtual_hosts).toArray
       val vho:Option[VirtualHostDTO] = if( host==null ) {

Modified: activemq/activemq-apollo/trunk/apollo-cli/src/main/scala/org/apache/activemq/apollo/cli/commands/StoreImport.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-cli/src/main/scala/org/apache/activemq/apollo/cli/commands/StoreImport.scala?rev=1141211&r1=1141210&r2=1141211&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-cli/src/main/scala/org/apache/activemq/apollo/cli/commands/StoreImport.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-cli/src/main/scala/org/apache/activemq/apollo/cli/commands/StoreImport.scala Wed Jun 29 19:31:58 2011
@@ -60,7 +60,7 @@ class StoreImport extends Action {
         error("Configuration file'%s' does not exist.\n\nTry creating a broker instance using the 'apollo create' command.".format(conf));
       }
 
-      val config = ConfigStore.load(conf)
+      val config = ConfigStore.load(conf, session.getConsole.println _)
 
       val hosts = collection.JavaConversions.collectionAsScalaIterable(config.virtual_hosts).toArray
       val vho:Option[VirtualHostDTO] = if( host==null ) {

Modified: activemq/activemq-apollo/trunk/apollo-dto/pom.xml
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-dto/pom.xml?rev=1141211&r1=1141210&r2=1141211&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-dto/pom.xml (original)
+++ activemq/activemq-apollo/trunk/apollo-dto/pom.xml Wed Jun 29 19:31:58 2011
@@ -95,92 +95,66 @@
     </resources>
       
     <plugins>
-
-<!--
-
-    jaxb schemagen plugin does not work quite well for our use case (classpath problems),
-    so we're using it as an ant task (see below)
-    try to switch back to this in some future version
-
--->
-<!--
-       <plugin>
-        <groupId>com.sun.tools.jxc.maven2</groupId>
-        <artifactId>maven-jaxb-schemagen-plugin</artifactId>
-        <executions>
-          <execution>
-            <phase>process-sources</phase>
-            <configuration>
-              <destdir>${project.build.directory}/schema</destdir>
-              <includes>
-                <include>**/jaxb/package-info.java</include>
-                <include>**/jaxb/*Xml.java</include>
-              </includes>
-              <schemas>
-                <schema>
-                  <namespace>http://activemq.apache.org/schema/activemq/apollo</namespace>
-                  <file>apollo-apollo.xsd</file>
-                </schema>
-              </schemas>
-            </configuration>
-            <goals>
-              <goal>generate</goal>
-            </goals> 
-          </execution>
-        </executions>
-      </plugin>  
--->
-       <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
+      
+      <plugin>
         <artifactId>maven-antrun-plugin</artifactId>
+        <version>1.6</version>
         <executions>
           <execution>
-            <id>generate schema</id>
-            <phase>process-sources</phase>
+            <phase>generate-resources</phase>
             <configuration>
-                <tasks>        
+              <tasks>
                 <taskdef name="schemagen" classname="com.sun.tools.jxc.SchemaGenTask">
-                    <classpath refid="maven.compile.classpath" />
+                  <classpath refid="maven.compile.classpath" />
                 </taskdef>
-                <mkdir dir="${project.build.directory}/schema" />
-                <schemagen srcdir="${project.build.sourceDirectory}" destdir="${project.build.directory}/schema">
-                    <schema namespace="http://activemq.apache.org/schema/activemq/apollo" file="apollo-apollo.xsd" />
-                    <classpath refid="maven.compile.classpath" />
-                    <include name="**/jaxb/package-info.java" />
-                    <include name="**/jaxb/*Xml.java" />
+                <mkdir dir="${project.build.directory}/schema/org/apache/activemq/apollo/dto" />
+                <schemagen srcdir="${basedir}/.." destdir="${project.build.directory}/schema/org/apache/activemq/apollo/dto">
+                  <schema namespace="http://activemq.apache.org/schema/activemq/apollo" file="apollo.xsd" />
+                  <classpath refid="maven.compile.classpath" />
+                  <include name="**/package-info.java" />
+                  <include name="**/*DTO.java" />
+                  <exclude name="apollo-hawtdb/**" />
+                  <exclude name="apollo-cassandra/**" />
+                  <exclude name="**/.git/**" />
+                  <exclude name="**/.svn/**" />
                 </schemagen>
-                </tasks>
+                
+                <replace 
+                  token='&lt;xs:sequence&gt;' 
+                  value='&lt;xs:choice minOccurs="0" maxOccurs="unbounded"&gt;&lt;xs:choice&gt;' 
+                  dir="${basedir}/target/schema/org/apache/activemq/apollo/dto">
+                  <include name="**/*.xsd"/>
+                </replace>
+                <replace 
+                  token= "&lt;/xs:sequence&gt;" 
+                  value="&lt;/xs:choice&gt;&lt;/xs:choice&gt;" 
+                  dir="${basedir}/target/schema/org/apache/activemq/apollo/dto">
+                  <include name="**/*.xsd"/>
+                </replace>
+              </tasks>
             </configuration>
             <goals>
               <goal>run</goal>
             </goals>
           </execution>
         </executions>
-        
         <dependencies>
-          <dependency>
-            <groupId>com.sun.xml.bind</groupId>
-            <artifactId>jaxb-xjc</artifactId>
-            <version>${xjc-version}</version>
-            <exclusions>
-              <exclusion>
-                <groupId>com.sun.xml.bind</groupId>
-                <artifactId>jaxb-impl</artifactId>
-              </exclusion>
-            </exclusions>            
-          </dependency>  
-          <dependency>
-            <groupId>com.sun.xml.bind</groupId>
-            <artifactId>jaxb-impl</artifactId>
-            <version>${jaxb-version}</version>
-            <exclusions>
-              <exclusion>
-                <groupId>javax.jws</groupId>
-                <artifactId>jsr181-api</artifactId>
-              </exclusion>
-            </exclusions>
-          </dependency>
-        </dependencies>
+           <dependency>
+              <groupId>javax.xml.bind</groupId>
+              <artifactId>jaxb-api</artifactId>
+              <version>${jaxb-api-version}</version>
+           </dependency>
+           <dependency>
+              <groupId>com.sun.xml.bind</groupId>
+              <artifactId>jaxb-impl</artifactId>
+              <version>${jaxb-version}</version>
+           </dependency>
+           <dependency>
+              <groupId>com.sun.xml.bind</groupId>
+              <artifactId>jaxb-xjc</artifactId>
+              <version>${jaxb-version}</version>
+           </dependency>
+        </dependencies>      
       </plugin>
 
     </plugins>

Modified: activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/BrokerDTO.java
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/BrokerDTO.java?rev=1141211&r1=1141210&r2=1141211&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/BrokerDTO.java (original)
+++ activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/BrokerDTO.java Wed Jun 29 19:31:58 2011
@@ -80,6 +80,14 @@ public class BrokerDTO {
     @XmlElement(name="service")
     public List<String> services = new ArrayList<String>();
 
+    @Deprecated
     @XmlAttribute(name="sticky_dispatching")
     public Boolean sticky_dispatching;
+
+    /**
+     * If set to strict, then the broker will not start up if there
+     * are any validation errors in the configuration file.
+     */
+    @XmlAttribute(name="validation")
+    public String validation;
 }

Modified: activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/JsonCodec.java
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/JsonCodec.java?rev=1141211&r1=1141210&r2=1141211&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/JsonCodec.java (original)
+++ activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/JsonCodec.java Wed Jun 29 19:31:58 2011
@@ -17,6 +17,8 @@
 package org.apache.activemq.apollo.dto;
 
 import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.SerializationConfig;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
 import org.fusesource.hawtbuf.Buffer;
 import org.fusesource.hawtbuf.ByteArrayOutputStream;
 
@@ -28,7 +30,10 @@ import java.io.IOException;
  * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
  */
 public class JsonCodec {
-    private static ObjectMapper mapper = new ObjectMapper();
+    final public static ObjectMapper mapper = new ObjectMapper();
+    static {
+        mapper.getSerializationConfig().setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
+    }
 
     static public <T> T decode(Buffer buffer, Class<T> type) throws IOException {
         ClassLoader original = Thread.currentThread().getContextClassLoader();

Modified: activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/XmlCodec.java
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/XmlCodec.java?rev=1141211&r1=1141210&r2=1141211&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/XmlCodec.java (original)
+++ activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/XmlCodec.java Wed Jun 29 19:31:58 2011
@@ -19,11 +19,10 @@ package org.apache.activemq.apollo.dto;
 import org.apache.activemq.apollo.util.ClassFinder;
 import org.apache.activemq.apollo.util.Module;
 import org.apache.activemq.apollo.util.ModuleRegistry;
+import org.xml.sax.SAXException;
 
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.Marshaller;
-import javax.xml.bind.Unmarshaller;
+import javax.xml.XMLConstants;
+import javax.xml.bind.*;
 import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamReader;
@@ -34,6 +33,8 @@ import java.util.HashSet;
 import java.util.Properties;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
 
 /**
  * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
@@ -106,19 +107,23 @@ public class XmlCodec {
         return JAXBContext.newInstance(packages);
     }
 
-    static public <T> T decode(Class<T> clazz, URL url) throws IOException, XMLStreamException, JAXBException {
+    static public <T> T decode(Class<T> clazz, URL url) throws IOException, XMLStreamException, JAXBException, SAXException {
         return decode(clazz, url, null);
     }
 
-    static public <T> T decode(Class<T> clazz, URL url, Properties props) throws IOException, XMLStreamException, JAXBException {
+    static public <T> T decode(Class<T> clazz, URL url, Properties props) throws IOException, XMLStreamException, JAXBException, SAXException {
         return decode(clazz, url.openStream(), props);
     }
 
-    static public <T> T decode(Class<T> clazz, InputStream is) throws IOException, XMLStreamException, JAXBException {
+    static public <T> T decode(Class<T> clazz, InputStream is) throws IOException, XMLStreamException, JAXBException, SAXException {
         return decode(clazz, is, null);
     }
 
-    static public <T> T decode(Class<T> clazz, InputStream is, Properties props) throws IOException, XMLStreamException, JAXBException {
+    static public <T> T decode(Class<T> clazz, InputStream is, Properties props) throws IOException, XMLStreamException, JAXBException, SAXException {
+        return decode(clazz, is, props, null);
+    }
+
+    static public <T> T decode(Class<T> clazz, InputStream is, Properties props, ValidationEventHandler validationHandler) throws IOException, XMLStreamException, JAXBException, SAXException {
         ClassLoader original = Thread.currentThread().getContextClassLoader();
         try {
             Thread.currentThread().setContextClassLoader(ClassFinder.class_loader());
@@ -131,6 +136,17 @@ public class XmlCodec {
                     reader = new PropertiesFilter(reader, props);
                 }
                 Unmarshaller unmarshaller = context().createUnmarshaller();
+                if( validationHandler !=null ) {
+                    try {
+                        SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+                        sf.setFeature("http://apache.org/xml/features/validation/schema-full-checking", false);
+                        Schema schema = sf.newSchema(XmlCodec.class.getResource("apollo.xsd"));
+                        unmarshaller.setSchema(schema);
+                        unmarshaller.setEventHandler(validationHandler);
+                    } catch (Exception e) {
+                        System.err.println("Could not load schema: "+e.getMessage());
+                    }
+                }
                 return clazz.cast(unmarshaller.unmarshal(reader));
             } finally {
                 is.close();
@@ -141,6 +157,8 @@ public class XmlCodec {
         }
     }
 
+
+
     static public void encode(Object in, OutputStream os, boolean format) throws JAXBException {
         ClassLoader original = Thread.currentThread().getContextClassLoader();
         try {

Modified: activemq/activemq-apollo/trunk/apollo-util/src/main/scala/org/apache/activemq/apollo/util/BaseService.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-util/src/main/scala/org/apache/activemq/apollo/util/BaseService.scala?rev=1141211&r1=1141210&r2=1141211&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-util/src/main/scala/org/apache/activemq/apollo/util/BaseService.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-util/src/main/scala/org/apache/activemq/apollo/util/BaseService.scala Wed Jun 29 19:31:58 2011
@@ -73,48 +73,59 @@ trait BaseService extends Service with D
   protected var _serviceFailure:Exception = null
   def serviceFailure = _serviceFailure
 
-  final def start(on_completed:Runnable) = ^{
-    def do_start = {
-      val state = new STARTING()
-      state << on_completed
-      _service_state = state
-      try {
-        _start(^ {
-          _service_state = new STARTED
-          state.done
-        })
+  private var pending_actions = List[Runnable]()
+
+  final def start(on_completed:Runnable) = {
+    val start_task = ^{
+      def do_start = {
+        val state = new STARTING()
+        state << on_completed
+        _service_state = state
+        try {
+          _start(^ {
+            _service_state = new STARTED
+            state.done
+          })
+        }
+        catch {
+          case e:Exception =>
+            error(e, "Start failed due to %s", e)
+            _serviceFailure = e
+            _service_state = new FAILED
+            state.done
+        }
       }
-      catch {
-        case e:Exception =>
-          error(e, "Start failed due to %s", e)
-          _serviceFailure = e
-          _service_state = new FAILED
-          state.done
+      def done = {
+        pending_actions.foreach(dispatch_queue.execute _)
+        pending_actions = Nil
+        if( on_completed!=null ) {
+          on_completed.run
+        }
       }
-    }
-    def done = {
-      if( on_completed!=null ) {
-        on_completed.run
+      _service_state match {
+        case state:CREATED =>
+          do_start
+        case state:STOPPED =>
+          do_start
+        case state:STOPPING =>
+          pending_actions += start_task
+        case state:STARTING =>
+          pending_actions += start_task
+        case state:STARTED =>
+          done
+        case state =>
+          done
+          error("Start should not be called from state: %s", state);
       }
     }
-    _service_state match {
-      case state:CREATED =>
-        do_start
-      case state:STOPPED =>
-        do_start
-      case state:STARTING =>
-        state << on_completed
-      case state:STARTED =>
-        done
-      case state =>
-        done
-        error("Start should not be called from state: %s", state);
-    }
-  } |>>: dispatch_queue
+    start_task |>>: dispatch_queue
+  }
 
   final def stop(on_completed:Runnable) = {
-    def stop_task = {
+    val stop_task = ^{
       def done = {
+        pending_actions.foreach(dispatch_queue.execute _)
+        pending_actions = Nil
         if( on_completed!=null ) {
           on_completed.run
         }
@@ -137,16 +148,18 @@ trait BaseService extends Service with D
               _service_state = new FAILED
               state.done
           }
-        case state:STOPPING =>
-          state << on_completed
         case state:STOPPED =>
           done
+        case state:STOPPING =>
+          pending_actions += stop_task
+        case state:STARTING =>
+          pending_actions += stop_task
         case state =>
           done
           error("Stop should not be called from state: %s", state);
       }
     }
-    ^{ stop_task } |>>: dispatch_queue
+    stop_task |>>: dispatch_queue
   }
 
   protected def _start(on_completed:Runnable)

Modified: activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/JacksonJsonProvider.java
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/JacksonJsonProvider.java?rev=1141211&r1=1141210&r2=1141211&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/JacksonJsonProvider.java (original)
+++ activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/JacksonJsonProvider.java Wed Jun 29 19:31:58 2011
@@ -16,6 +16,8 @@
  */
 package org.apache.activemq.apollo.web.resources;
 
+import org.apache.activemq.apollo.dto.JsonCodec;
+
 /**
  * <p>
  * </p>
@@ -26,5 +28,7 @@ package org.apache.activemq.apollo.web.r
 @javax.ws.rs.Consumes({"application/json", "text/json"})
 @javax.ws.rs.Produces({"application/json", "text/json"})
 public class JacksonJsonProvider extends org.codehaus.jackson.jaxrs.JacksonJsonProvider {
-
+    public JacksonJsonProvider() {
+        super(JsonCodec.mapper);
+    }
 }

Modified: activemq/activemq-apollo/trunk/apollo-website/src/documentation/user-manual.md
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-website/src/documentation/user-manual.md?rev=1141211&r1=1141210&r2=1141211&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-website/src/documentation/user-manual.md (original)
+++ activemq/activemq-apollo/trunk/apollo-website/src/documentation/user-manual.md Wed Jun 29 19:31:58 2011
@@ -110,6 +110,20 @@ store.
 
 Brokers can be configured with multiple virtual hosts and connectors.
 
+When a broker is first started up, it will validate the configuration
+file against the the [XSD Schema](schema/apollo.xsd) and report any 
+errors/warnings it finds but it will continue to start the broker even 
+it finds problems.  You would want to the broker to abort starting up
+if any issues are found with the schema validation you should set
+the `broker` element's `validation` attribute to `strict`.  Example:
+
+{pygmentize:: xml}
+<broker validation="strict" 
+   xmlns="http://activemq.apache.org/schema/activemq/apollo">
+  ...
+</broker>
+{pygmentize}
+
 #### Connectors
 
 A broker connector is used to accept new connections to the broker.