You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by gt...@apache.org on 2013/08/23 00:47:21 UTC

svn commit: r1516650 - in /activemq/trunk/activemq-runtime-config/src: main/java/org/apache/activemq/plugin/ main/java/org/apache/activemq/plugin/jmx/ test/java/org/apache/activemq/ test/resources/org/apache/activemq/

Author: gtully
Date: Thu Aug 22 22:47:21 2013
New Revision: 1516650

URL: http://svn.apache.org/r1516650
Log:
https://issues.apache.org/jira/browse/AMQ-4682 - add jmx mbean, manual update, validation and test refactor

Added:
    activemq/trunk/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/jmx/
    activemq/trunk/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/jmx/RuntimeConfigurationView.java   (with props)
    activemq/trunk/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/jmx/RuntimeConfigurationViewMBean.java   (with props)
    activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/MBeanTest.java   (with props)
    activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/RuntimeConfigTestSupport.java   (with props)
    activemq/trunk/activemq-runtime-config/src/test/resources/org/apache/activemq/emptyManualUpdateConfig.xml   (with props)
    activemq/trunk/activemq-runtime-config/src/test/resources/org/apache/activemq/parseErrorConfig.xml   (with props)
Modified:
    activemq/trunk/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/RuntimeConfigurationBroker.java
    activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/NetworkConnectorTest.java
    activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/VirtualDestTest.java

Modified: activemq/trunk/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/RuntimeConfigurationBroker.java
URL: http://svn.apache.org/viewvc/activemq/trunk/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/RuntimeConfigurationBroker.java?rev=1516650&r1=1516649&r2=1516650&view=diff
==============================================================================
--- activemq/trunk/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/RuntimeConfigurationBroker.java (original)
+++ activemq/trunk/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/RuntimeConfigurationBroker.java Thu Aug 22 22:47:21 2013
@@ -17,6 +17,7 @@
 package org.apache.activemq.plugin;
 
 import java.io.IOException;
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
@@ -26,6 +27,9 @@ import java.util.Properties;
 import java.util.TreeMap;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
+import javax.management.JMException;
+import javax.management.ObjectName;
+import javax.xml.XMLConstants;
 import javax.xml.bind.JAXBContext;
 import javax.xml.bind.JAXBElement;
 import javax.xml.bind.JAXBException;
@@ -33,14 +37,20 @@ import javax.xml.bind.Unmarshaller;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+import javax.xml.validation.ValidatorHandler;
 import org.apache.activemq.broker.BrokerFilter;
 import org.apache.activemq.broker.ConnectionContext;
+import org.apache.activemq.broker.jmx.ManagementContext;
 import org.apache.activemq.broker.region.CompositeDestinationInterceptor;
 import org.apache.activemq.broker.region.Destination;
 import org.apache.activemq.broker.region.DestinationInterceptor;
 import org.apache.activemq.broker.region.RegionBroker;
 import org.apache.activemq.broker.region.virtual.VirtualDestination;
 import org.apache.activemq.command.ActiveMQDestination;
+import org.apache.activemq.plugin.jmx.RuntimeConfigurationView;
 import org.apache.activemq.schema.core.Broker;
 import org.apache.activemq.schema.core.CompositeQueue;
 import org.apache.activemq.schema.core.CompositeTopic;
@@ -59,6 +69,7 @@ import org.xml.sax.SAXException;
 public class RuntimeConfigurationBroker extends BrokerFilter {
 
     public static final Logger LOG = LoggerFactory.getLogger(RuntimeConfigurationBroker.class);
+    public static final String objectNamePropsAppendage = ",service=RuntimeConfiguration,name=Plugin";
     private long checkPeriod;
     private long lastModified = -1;
     private Resource configToMonitor;
@@ -66,6 +77,8 @@ public class RuntimeConfigurationBroker 
     private Runnable monitorTask;
     private ConcurrentLinkedQueue<Runnable> destinationInterceptorUpdateWork = new ConcurrentLinkedQueue<Runnable>();
     private final ReentrantReadWriteLock addDestinationBarrier = new ReentrantReadWriteLock();
+    private ObjectName objectName;
+    private String infoString;
 
     public RuntimeConfigurationBroker(org.apache.activemq.broker.Broker next) {
         super(next);
@@ -82,6 +95,7 @@ public class RuntimeConfigurationBroker 
 
         currentConfiguration = loadConfiguration(configToMonitor);
         monitorModification(configToMonitor);
+        registerMbean();
     }
 
     @Override
@@ -93,9 +107,31 @@ public class RuntimeConfigurationBroker 
                 LOG.warn("Failed to cancel config monitor task", letsNotStopStop);
             }
         }
+        unregisterMbean();
         super.stop();
     }
 
+    private void registerMbean() {
+        if (getBrokerService().isUseJmx()) {
+            ManagementContext managementContext = getBrokerService().getManagementContext();
+            try {
+                objectName = new ObjectName(getBrokerService().getBrokerObjectName().toString() + objectNamePropsAppendage);
+                managementContext.registerMBean(new RuntimeConfigurationView(this), objectName);
+            } catch (Exception ignored) {
+                LOG.debug("failed to register RuntimeConfigurationMBean", ignored);
+            }
+        }
+    }
+
+    private void unregisterMbean() {
+        if  (objectName != null) {
+            try {
+                getBrokerService().getManagementContext().unregisterMBean(objectName);
+            } catch (JMException ignored) {
+            }
+        }
+    }
+
     // modification to virtual destinations interceptor needs exclusive access to destination add
     @Override
     public Destination addDestination(ConnectionContext context, ActiveMQDestination destination, boolean createIfTemporary) throws Exception {
@@ -121,6 +157,15 @@ public class RuntimeConfigurationBroker 
         }
     }
 
+    public String updateNow() {
+        LOG.info("Manual configuration update triggered");
+        infoString = "";
+        applyModifications(configToMonitor);
+        String result = infoString;
+        infoString = null;
+        return result;
+    }
+
     private void monitorModification(final Resource configToMonitor) {
         monitorTask = new Runnable() {
             @Override
@@ -134,22 +179,40 @@ public class RuntimeConfigurationBroker 
                 }
             }
         };
-        if (lastModified > 0) {
+        if (lastModified > 0 && checkPeriod > 0) {
             this.getBrokerService().getScheduler().executePeriodically(monitorTask, checkPeriod);
-            LOG.info("Monitoring for updates (every " + checkPeriod + "millis) : " + configToMonitor);
+            info("Monitoring for updates (every " + checkPeriod + "millis) : " + configToMonitor);
         }
     }
 
+    private void info(String s) {
+        LOG.info(s);
+        if (infoString != null) {
+            infoString += s;
+            infoString += ";";
+        }
+    }
+
+    private void info(String s, Throwable t) {
+        LOG.info(s, t);
+        if (infoString != null) {
+            infoString += s;
+            infoString += ", " + t;
+            infoString += ";";
+        }
+    }
+
+
     private void applyModifications(Resource configToMonitor) {
         Broker changed = loadConfiguration(configToMonitor);
-        if (!currentConfiguration.equals(changed)) {
-            LOG.info("configuration change in " + configToMonitor + " at: " + new Date(lastModified));
-            LOG.info("current:" + currentConfiguration);
-            LOG.info("new    :" + changed);
+        if (changed != null && !currentConfiguration.equals(changed)) {
+            LOG.info("change in " + configToMonitor + " at: " + new Date(lastModified));
+            LOG.debug("current:" + currentConfiguration);
+            LOG.debug("new    :" + changed);
             processSelectiveChanges(currentConfiguration, changed);
             currentConfiguration = changed;
         } else {
-            LOG.info("file modification but no material change to configuration in " + configToMonitor + " at: " + new Date(lastModified));
+            info("No material change to configuration in " + configToMonitor + " at: " + new Date(lastModified));
         }
     }
 
@@ -192,7 +255,7 @@ public class RuntimeConfigurationBroker 
         try {
             return (List<Object>) o.getClass().getMethod("getContents", new Class[]{}).invoke(o, new Object[]{});
         } catch (Exception e) {
-            LOG.info("Failed to access getContents for " + o + ", runtime modifications not supported", e);
+            info("Failed to access getContents for " + o + ", runtime modifications not supported", e);
         }
         return new ArrayList<Object>();
     }
@@ -203,7 +266,7 @@ public class RuntimeConfigurationBroker 
             Object existing = current.get(currentIndex);
             Object candidate = modification.get(modIndex);
             if (! existing.equals(candidate)) {
-                LOG.info("modification to:" + existing + " , with: " + candidate);
+                info("modification to:" + existing + " , with: " + candidate);
                 remove(existing);
                 addNew(candidate);
             }
@@ -227,9 +290,9 @@ public class RuntimeConfigurationBroker 
                     if (getBrokerService().removeNetworkConnector(existingCandidate)) {
                         try {
                             existingCandidate.stop();
-                            LOG.info("stopped and removed networkConnector: " + existingCandidate);
+                            info("stopped and removed networkConnector: " + existingCandidate);
                         } catch (Exception e) {
-                            LOG.error("Failed to stop removed network connector: " + existingCandidate);
+                            info("Failed to stop removed network connector: " + existingCandidate);
                         }
                     }
                 }
@@ -247,11 +310,11 @@ public class RuntimeConfigurationBroker 
                     DestinationInterceptor[] destinationInterceptors = interceptorsList.toArray(new DestinationInterceptor[]{});
                     getBrokerService().setDestinationInterceptors(destinationInterceptors);
                     ((CompositeDestinationInterceptor) ((RegionBroker) getBrokerService().getRegionBroker()).getDestinationInterceptor()).setInterceptors(destinationInterceptors);
-                    LOG.trace("removed VirtualDestinationInterceptor from: " + interceptorsList);
+                    info("removed VirtualDestinationInterceptor from: " + interceptorsList);
                 }
             });
         } else {
-            LOG.info("No runtime support for removal of: " + o);
+            info("No runtime support for removal of: " + o);
         }
     }
 
@@ -284,9 +347,9 @@ public class RuntimeConfigurationBroker 
                     LOG.trace("applying networkConnector props: " + properties);
                     IntrospectionSupport.setProperties(nc, properties);
                     nc.start();
-                    LOG.info("started new network connector: " + nc);
+                    info("started new network connector: " + nc);
                 } catch (Exception e) {
-                    LOG.error("Failed to add new networkConnector " + networkConnector, e);
+                    info("Failed to add new networkConnector " + networkConnector, e);
                 }
             }
         } else if (o instanceof VirtualDestinationInterceptor) {
@@ -303,7 +366,7 @@ public class RuntimeConfigurationBroker 
                                     (org.apache.activemq.broker.region.virtual.VirtualDestinationInterceptor) destinationInterceptor;
 
                             virtualDestinationInterceptor.setVirtualDestinations(fromDto(dto));
-                            LOG.trace("applied updates to: " + virtualDestinationInterceptor);
+                            info("applied updates to: " + virtualDestinationInterceptor);
                             updatedExistingInterceptor = true;
                         }
                     }
@@ -321,12 +384,12 @@ public class RuntimeConfigurationBroker 
                         DestinationInterceptor[] destinationInterceptors = interceptorsList.toArray(new DestinationInterceptor[]{});
                         getBrokerService().setDestinationInterceptors(destinationInterceptors);
                         ((CompositeDestinationInterceptor) ((RegionBroker) getBrokerService().getRegionBroker()).getDestinationInterceptor()).setInterceptors(destinationInterceptors);
-                        LOG.trace("applied new: " + interceptorsList);
+                        info("applied new: " + interceptorsList);
                     }
                 }
             });
         } else {
-            LOG.info("No runtime support for modifications to " + o);
+            info("No runtime support for modifications to " + o);
         }
     }
 
@@ -381,6 +444,7 @@ public class RuntimeConfigurationBroker 
             try {
                 JAXBContext context = JAXBContext.newInstance(Broker.class);
                 Unmarshaller unMarshaller = context.createUnmarshaller();
+                unMarshaller.setSchema(getSchema());
 
                 // skip beans and pull out the broker node to validate
                 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
@@ -397,19 +461,41 @@ public class RuntimeConfigurationBroker 
                 lastModified = configToMonitor.lastModified();
 
             } catch (IOException e) {
-                LOG.error("Failed to access: " + configToMonitor, e);
+                info("Failed to access: " + configToMonitor, e);
             } catch (JAXBException e) {
-                LOG.error("Failed to parse: " + configToMonitor, e);
+                info("Failed to parse: " + configToMonitor, e);
             } catch (ParserConfigurationException e) {
-                LOG.error("Failed to document parse: " + configToMonitor, e);
+                info("Failed to document parse: " + configToMonitor, e);
             } catch (SAXException e) {
-                LOG.error("Failed to find broker element in: " + configToMonitor, e);
+                info("Failed to find broker element in: " + configToMonitor, e);
             }
         }
         return jaxbConfig;
     }
 
+    private Schema schema;
+    private Schema getSchema() throws SAXException {
+        if (schema == null) {
+            SchemaFactory schemaFactory = SchemaFactory.newInstance(
+                                    XMLConstants.W3C_XML_SCHEMA_NS_URI);
+                schema = schemaFactory.newSchema(getClass().getResource("/activemq.xsd"));
+        }
+        return schema;
+    }
+
     public void setCheckPeriod(long checkPeriod) {
         this.checkPeriod = checkPeriod;
     }
+
+    public long getLastModified() {
+        return lastModified;
+    }
+
+    public Resource getConfigToMonitor() {
+        return configToMonitor;
+    }
+
+    public long getCheckPeriod() {
+        return checkPeriod;
+    }
 }
\ No newline at end of file

Added: activemq/trunk/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/jmx/RuntimeConfigurationView.java
URL: http://svn.apache.org/viewvc/activemq/trunk/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/jmx/RuntimeConfigurationView.java?rev=1516650&view=auto
==============================================================================
--- activemq/trunk/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/jmx/RuntimeConfigurationView.java (added)
+++ activemq/trunk/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/jmx/RuntimeConfigurationView.java Thu Aug 22 22:47:21 2013
@@ -0,0 +1,54 @@
+/**
+ * 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.activemq.plugin.jmx;
+
+import java.util.Date;
+import org.apache.activemq.plugin.RuntimeConfigurationBroker;
+import org.springframework.core.io.Resource;
+
+public class RuntimeConfigurationView implements RuntimeConfigurationViewMBean {
+    private final RuntimeConfigurationBroker runtimeConfigurationBroker;
+
+    public RuntimeConfigurationView(RuntimeConfigurationBroker runtimeConfigurationBroker) {
+        this.runtimeConfigurationBroker = runtimeConfigurationBroker;
+    }
+
+    @Override
+    public String getUrl() {
+        Resource value = runtimeConfigurationBroker.getConfigToMonitor();
+        return value != null ? value.toString() : "null" ;
+    }
+
+    @Override
+    public String getModified() {
+        long lastModified =  runtimeConfigurationBroker.getLastModified();
+        if (lastModified > 0) {
+            return new Date(lastModified).toString();
+        }
+        return "unknown";
+    }
+
+    @Override
+    public String getCheckPeriod() {
+        return String.valueOf(runtimeConfigurationBroker.getCheckPeriod());
+    }
+
+    @Override
+    public String updateNow() {
+        return runtimeConfigurationBroker.updateNow();
+    }
+}

Propchange: activemq/trunk/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/jmx/RuntimeConfigurationView.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: activemq/trunk/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/jmx/RuntimeConfigurationView.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: activemq/trunk/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/jmx/RuntimeConfigurationViewMBean.java
URL: http://svn.apache.org/viewvc/activemq/trunk/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/jmx/RuntimeConfigurationViewMBean.java?rev=1516650&view=auto
==============================================================================
--- activemq/trunk/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/jmx/RuntimeConfigurationViewMBean.java (added)
+++ activemq/trunk/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/jmx/RuntimeConfigurationViewMBean.java Thu Aug 22 22:47:21 2013
@@ -0,0 +1,35 @@
+/**
+ * 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.activemq.plugin.jmx;
+
+import org.apache.activemq.broker.jmx.MBeanInfo;
+
+public interface RuntimeConfigurationViewMBean {
+
+    @MBeanInfo("Monitored configuration url.")
+    String getUrl();
+
+    @MBeanInfo("Current last modified.")
+    String getModified();
+
+    @MBeanInfo("check period.")
+    String getCheckPeriod();
+
+    @MBeanInfo("force a reread of the configuration url.")
+    String updateNow();
+
+}

Propchange: activemq/trunk/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/jmx/RuntimeConfigurationViewMBean.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: activemq/trunk/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/jmx/RuntimeConfigurationViewMBean.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/MBeanTest.java
URL: http://svn.apache.org/viewvc/activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/MBeanTest.java?rev=1516650&view=auto
==============================================================================
--- activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/MBeanTest.java (added)
+++ activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/MBeanTest.java Thu Aug 22 22:47:21 2013
@@ -0,0 +1,123 @@
+/**
+ * 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.activemq;
+
+import java.util.HashMap;
+import javax.management.ObjectName;
+import org.apache.activemq.plugin.RuntimeConfigurationBroker;
+import org.apache.activemq.plugin.jmx.RuntimeConfigurationView;
+import org.apache.activemq.plugin.jmx.RuntimeConfigurationViewMBean;
+import org.apache.activemq.util.IntrospectionSupport;
+import org.junit.Test;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+public class MBeanTest extends RuntimeConfigTestSupport {
+
+    @Test
+    public void testUpdateNow() throws Exception {
+        final String brokerConfig =  "mBeanTest-manual-broker";
+        applyNewConfig(brokerConfig, "emptyManualUpdateConfig");
+        startBroker(brokerConfig);
+        assertTrue("broker alive", brokerService.isStarted());
+        assertEquals("no network connectors", 0, brokerService.getNetworkConnectors().size());
+
+        applyNewConfig(brokerConfig, "networkConnectorTest-one-nc", SLEEP);
+
+        assertEquals("no network connectors", 0, brokerService.getNetworkConnectors().size());
+
+        // apply via jmx
+        ObjectName objectName =
+                new ObjectName(brokerService.getBrokerObjectName().toString() +
+                        RuntimeConfigurationBroker.objectNamePropsAppendage);
+        RuntimeConfigurationViewMBean runtimeConfigurationView =
+                (RuntimeConfigurationViewMBean) brokerService.getManagementContext().newProxyInstance(objectName,
+                        RuntimeConfigurationViewMBean.class, false);
+
+        HashMap<String, String> props = new HashMap<String, String>();
+        IntrospectionSupport.getProperties(runtimeConfigurationView, props, null);
+        LOG.info("mbean attributes before: " + props);
+
+        String result = runtimeConfigurationView.updateNow();
+
+        LOG.info("Result from update: " + result);
+
+        assertTrue("got sensible result", result.contains("started"));
+
+        assertEquals("one new network connectors", 1, brokerService.getNetworkConnectors().size());
+
+        HashMap<String, String> propsAfter = new HashMap<String, String>();
+        IntrospectionSupport.getProperties(runtimeConfigurationView, propsAfter, null);
+
+        LOG.info("mbean attributes after: " + propsAfter);
+        String propOfInterest = "modified";
+        assertNotEquals("modified is different", props.get(propOfInterest), propsAfter.get(propOfInterest));
+    }
+
+    @Test
+    public void testUpdateFailedMod() throws Exception {
+        final String brokerConfig =  "mBeanTest-manual-broker";
+        applyNewConfig(brokerConfig, "emptyManualUpdateConfig");
+        startBroker(brokerConfig);
+        assertTrue("broker alive", brokerService.isStarted());
+        assertEquals("no network connectors", 0, brokerService.getNetworkConnectors().size());
+
+        applyNewConfig(brokerConfig, "parseErrorConfig", SLEEP);
+
+        // apply via jmx
+        ObjectName objectName =
+                new ObjectName(brokerService.getBrokerObjectName().toString() +
+                        RuntimeConfigurationBroker.objectNamePropsAppendage);
+        RuntimeConfigurationViewMBean runtimeConfigurationView =
+                (RuntimeConfigurationViewMBean) brokerService.getManagementContext().newProxyInstance(objectName,
+                        RuntimeConfigurationViewMBean.class, false);
+
+        HashMap<String, String> props = new HashMap<String, String>();
+        IntrospectionSupport.getProperties(runtimeConfigurationView, props, null);
+        LOG.info("mbean attributes before: " + props);
+
+        String result = runtimeConfigurationView.updateNow();
+        LOG.info("Result from failed update: " + result);
+
+        assertTrue("got sensible result", result.contains("dudElement"));
+
+        HashMap<String, String> propsAfter = new HashMap<String, String>();
+        IntrospectionSupport.getProperties(runtimeConfigurationView, propsAfter, null);
+
+        LOG.info("mbean attributes after: " + propsAfter);
+        String propOfInterest = "modified";
+        assertEquals("modified is same", props.get(propOfInterest), propsAfter.get(propOfInterest));
+
+        // apply good change now
+        applyNewConfig(brokerConfig, "networkConnectorTest-one-nc", SLEEP);
+
+        result = runtimeConfigurationView.updateNow();
+
+        LOG.info("Result from update: " + result);
+        assertTrue("got sensible result", result.contains("started"));
+        assertEquals("one new network connectors", 1, brokerService.getNetworkConnectors().size());
+
+        propsAfter = new HashMap<String, String>();
+        IntrospectionSupport.getProperties(runtimeConfigurationView, propsAfter, null);
+
+        assertNotEquals("modified is different", props.get(propOfInterest), propsAfter.get(propOfInterest));
+
+    }
+}

Propchange: activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/MBeanTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/MBeanTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/NetworkConnectorTest.java
URL: http://svn.apache.org/viewvc/activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/NetworkConnectorTest.java?rev=1516650&r1=1516649&r2=1516650&view=diff
==============================================================================
--- activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/NetworkConnectorTest.java (original)
+++ activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/NetworkConnectorTest.java Thu Aug 22 22:47:21 2013
@@ -16,49 +16,21 @@
  */
 package org.apache.activemq;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.util.concurrent.TimeUnit;
-import org.apache.activemq.broker.BrokerFactory;
-import org.apache.activemq.broker.BrokerService;
 import org.apache.activemq.network.NetworkConnector;
-import org.apache.activemq.spring.Utils;
 import org.apache.activemq.util.Wait;
-import org.junit.After;
-import org.junit.Ignore;
+import org.junit.Before;
 import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.core.io.Resource;
-
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
-public class NetworkConnectorTest {
-
-    public static final Logger LOG = LoggerFactory.getLogger(NetworkConnectorTest.class);
-    public static final int SLEEP = 4; // seconds
-    public static final String EMPTY_UPDATABLE_CONFIG = "emptyUpdatableConfig1000" ;
+public class NetworkConnectorTest extends RuntimeConfigTestSupport {
     String configurationSeed = "networkConnectorTest";
-    BrokerService brokerService;
-
-    public void startBroker(String configFileName) throws Exception {
-        brokerService = new BrokerService();
-        brokerService = BrokerFactory.createBroker("xbean:org/apache/activemq/" + configFileName + ".xml");
-        brokerService.start();
-        brokerService.waitUntilStarted();
-    }
-
-    @After
-    public void stopBroker() throws Exception {
-        brokerService.stop();
-    }
 
     @Test
     public void testNew() throws Exception {
+
         final String brokerConfig = configurationSeed + "-no-nc-broker";
         applyNewConfig(brokerConfig, EMPTY_UPDATABLE_CONFIG);
         startBroker(brokerConfig);
@@ -67,7 +39,12 @@ public class NetworkConnectorTest {
 
         applyNewConfig(brokerConfig, configurationSeed + "-one-nc", SLEEP);
 
-        assertEquals("new network connectors", 1, brokerService.getNetworkConnectors().size());
+        assertTrue("new network connectors", Wait.waitFor(new Wait.Condition() {
+            @Override
+            public boolean isSatisified() throws Exception {
+                return 1 == brokerService.getNetworkConnectors().size();
+            }
+        }));
 
         // apply again - ensure no change
         NetworkConnector networkConnector = brokerService.getNetworkConnectors().get(0);
@@ -124,22 +101,4 @@ public class NetworkConnectorTest {
         NetworkConnector remainingNetworkConnector = brokerService.getNetworkConnectors().get(0);
         assertEquals("name match", "one", remainingNetworkConnector.getName());
     }
-
-    private void applyNewConfig(String configName, String newConfigName) throws Exception {
-        applyNewConfig(configName, newConfigName, 0l);
-    }
-
-    private void applyNewConfig(String configName, String newConfigName, long sleep) throws Exception {
-        Resource resource = Utils.resourceFromString("org/apache/activemq");
-        FileOutputStream current = new FileOutputStream(new File(resource.getFile(), configName + ".xml"));
-        FileInputStream modifications = new FileInputStream(new File(resource.getFile(), newConfigName + ".xml"));
-        modifications.getChannel().transferTo(0, Long.MAX_VALUE, current.getChannel());
-        current.flush();
-        LOG.info("Updated: " + current.getChannel());
-
-        if (sleep > 0) {
-            // wait for mods to kick in
-            TimeUnit.SECONDS.sleep(sleep);
-        }
-    }
 }

Added: activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/RuntimeConfigTestSupport.java
URL: http://svn.apache.org/viewvc/activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/RuntimeConfigTestSupport.java?rev=1516650&view=auto
==============================================================================
--- activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/RuntimeConfigTestSupport.java (added)
+++ activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/RuntimeConfigTestSupport.java Thu Aug 22 22:47:21 2013
@@ -0,0 +1,71 @@
+/**
+ * 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.activemq;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.concurrent.TimeUnit;
+import org.apache.activemq.broker.BrokerFactory;
+import org.apache.activemq.broker.BrokerService;
+import org.apache.activemq.spring.Utils;
+import org.junit.After;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.io.Resource;
+
+public class RuntimeConfigTestSupport {
+    public static final Logger LOG = LoggerFactory.getLogger(RuntimeConfigTestSupport.class);
+
+    public static final int SLEEP = 4; // seconds
+    public static final String EMPTY_UPDATABLE_CONFIG = "emptyUpdatableConfig1000" ;
+    BrokerService brokerService;
+
+    public void startBroker(String configFileName) throws Exception {
+        brokerService = createBroker(configFileName);
+        brokerService.start();
+        brokerService.waitUntilStarted();
+    }
+
+    public BrokerService createBroker(String configFileName) throws Exception {
+        brokerService = new BrokerService();
+        return BrokerFactory.createBroker("xbean:org/apache/activemq/" + configFileName + ".xml");
+    }
+
+    protected void applyNewConfig(String configName, String newConfigName) throws Exception {
+        applyNewConfig(configName, newConfigName, 0l);
+    }
+
+    protected void applyNewConfig(String configName, String newConfigName, long sleep) throws Exception {
+        Resource resource = Utils.resourceFromString("org/apache/activemq");
+        FileOutputStream current = new FileOutputStream(new File(resource.getFile(), configName + ".xml"));
+        FileInputStream modifications = new FileInputStream(new File(resource.getFile(), newConfigName + ".xml"));
+        modifications.getChannel().transferTo(0, Long.MAX_VALUE, current.getChannel());
+        current.flush();
+        LOG.info("Updated: " + current.getChannel());
+
+        if (sleep > 0) {
+            // wait for mods to kick in
+            TimeUnit.SECONDS.sleep(sleep);
+        }
+    }
+
+    @After
+    public void stopBroker() throws Exception {
+        brokerService.stop();
+    }
+}

Propchange: activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/RuntimeConfigTestSupport.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/RuntimeConfigTestSupport.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/VirtualDestTest.java
URL: http://svn.apache.org/viewvc/activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/VirtualDestTest.java?rev=1516650&r1=1516649&r2=1516650&view=diff
==============================================================================
--- activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/VirtualDestTest.java (original)
+++ activemq/trunk/activemq-runtime-config/src/test/java/org/apache/activemq/VirtualDestTest.java Thu Aug 22 22:47:21 2013
@@ -16,54 +16,27 @@
  */
 package org.apache.activemq;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.util.concurrent.TimeUnit;
-import javax.jms.*;
 import javax.jms.Message;
-import org.apache.activemq.broker.BrokerFactory;
-import org.apache.activemq.broker.BrokerService;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import javax.jms.TextMessage;
 import org.apache.activemq.broker.region.DestinationInterceptor;
 import org.apache.activemq.broker.region.virtual.VirtualDestinationInterceptor;
-import org.apache.activemq.spring.Utils;
 import org.apache.activemq.util.Wait;
-import org.junit.After;
 import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.core.io.Resource;
 
 
 import static org.junit.Assert.*;
 
-public class VirtualDestTest {
+public class VirtualDestTest extends RuntimeConfigTestSupport {
 
-    public static final Logger LOG = LoggerFactory.getLogger(VirtualDestTest.class);
-    public static final int SLEEP = 4; // seconds
     String configurationSeed = "virtualDestTest";
-    BrokerService brokerService;
-
-    public void startBroker(String configFileName) throws Exception {
-        brokerService = createBroker(configFileName);
-        brokerService.start();
-        brokerService.waitUntilStarted();
-    }
-
-    public BrokerService createBroker(String configFileName) throws Exception {
-        brokerService = new BrokerService();
-        return BrokerFactory.createBroker("xbean:org/apache/activemq/" + configFileName + ".xml");
-    }
-
-    @After
-    public void stopBroker() throws Exception {
-        brokerService.stop();
-    }
 
     @Test
     public void testNew() throws Exception {
-        final String brokerConfig = configurationSeed + "-no-vd-broker";
-        applyNewConfig(brokerConfig, NetworkConnectorTest.EMPTY_UPDATABLE_CONFIG);
+        final String brokerConfig = configurationSeed + "-new-no-vd-broker";
+        applyNewConfig(brokerConfig, RuntimeConfigTestSupport.EMPTY_UPDATABLE_CONFIG);
         startBroker(brokerConfig);
         assertTrue("broker alive", brokerService.isStarted());
 
@@ -98,8 +71,8 @@ public class VirtualDestTest {
 
     @Test
     public void testNewNoDefaultVirtualTopicSupport() throws Exception {
-        final String brokerConfig = configurationSeed + "-no-vd-broker";
-        applyNewConfig(brokerConfig, NetworkConnectorTest.EMPTY_UPDATABLE_CONFIG);
+        final String brokerConfig = configurationSeed + "-no-vd-vt-broker";
+        applyNewConfig(brokerConfig, RuntimeConfigTestSupport.EMPTY_UPDATABLE_CONFIG);
         brokerService = createBroker(brokerConfig);
         brokerService.setUseVirtualTopics(false);
         brokerService.start();
@@ -128,8 +101,8 @@ public class VirtualDestTest {
 
     @Test
     public void testNewWithMirrorQueueSupport() throws Exception {
-        final String brokerConfig = configurationSeed + "-no-vd-broker";
-        applyNewConfig(brokerConfig, NetworkConnectorTest.EMPTY_UPDATABLE_CONFIG);
+        final String brokerConfig = configurationSeed + "-no-vd-mq-broker";
+        applyNewConfig(brokerConfig, RuntimeConfigTestSupport.EMPTY_UPDATABLE_CONFIG);
         brokerService = createBroker(brokerConfig);
         brokerService.setUseMirroredQueues(true);
         brokerService.start();
@@ -158,7 +131,7 @@ public class VirtualDestTest {
 
     @Test
     public void testRemove() throws Exception {
-        final String brokerConfig = configurationSeed + "-one-vd-broker";
+        final String brokerConfig = configurationSeed + "-one-vd-rm-broker";
         applyNewConfig(brokerConfig, configurationSeed + "-one-vd");
         startBroker(brokerConfig);
         assertTrue("broker alive", brokerService.isStarted());
@@ -173,7 +146,7 @@ public class VirtualDestTest {
 
         exerciseVirtualTopic("A.Default");
 
-        applyNewConfig(brokerConfig, NetworkConnectorTest.EMPTY_UPDATABLE_CONFIG, SLEEP);
+        applyNewConfig(brokerConfig, RuntimeConfigTestSupport.EMPTY_UPDATABLE_CONFIG, SLEEP);
 
         // update will happen on addDestination
         forceAddDestination("AnyDest");
@@ -197,7 +170,7 @@ public class VirtualDestTest {
 
     @Test
     public void testMod() throws Exception {
-        final String brokerConfig = configurationSeed + "-one-vd-broker";
+        final String brokerConfig = configurationSeed + "-one-vd-mod-broker";
         applyNewConfig(brokerConfig, configurationSeed + "-one-vd");
         startBroker(brokerConfig);
         assertTrue("broker alive", brokerService.isStarted());
@@ -214,7 +187,7 @@ public class VirtualDestTest {
 
     @Test
     public void testModWithMirroredQueue() throws Exception {
-        final String brokerConfig = configurationSeed + "-one-vd-broker";
+        final String brokerConfig = configurationSeed + "-one-vd-mq-mod-broker";
         applyNewConfig(brokerConfig, configurationSeed + "-one-vd");
         brokerService = createBroker(brokerConfig);
         brokerService.setUseMirroredQueues(true);
@@ -257,21 +230,4 @@ public class VirtualDestTest {
         connection.close();
     }
 
-    private void applyNewConfig(String configName, String newConfigName) throws Exception {
-        applyNewConfig(configName, newConfigName, 0l);
-    }
-
-    private void applyNewConfig(String configName, String newConfigName, long sleep) throws Exception {
-        Resource resource = Utils.resourceFromString("org/apache/activemq");
-        FileOutputStream current = new FileOutputStream(new File(resource.getFile(), configName + ".xml"));
-        FileInputStream modifications = new FileInputStream(new File(resource.getFile(), newConfigName + ".xml"));
-        modifications.getChannel().transferTo(0, Long.MAX_VALUE, current.getChannel());
-        current.flush();
-        LOG.info("Updated: " + current.getChannel());
-
-        if (sleep > 0) {
-            // wait for mods to kick in
-            TimeUnit.SECONDS.sleep(sleep);
-        }
-    }
 }

Added: activemq/trunk/activemq-runtime-config/src/test/resources/org/apache/activemq/emptyManualUpdateConfig.xml
URL: http://svn.apache.org/viewvc/activemq/trunk/activemq-runtime-config/src/test/resources/org/apache/activemq/emptyManualUpdateConfig.xml?rev=1516650&view=auto
==============================================================================
--- activemq/trunk/activemq-runtime-config/src/test/resources/org/apache/activemq/emptyManualUpdateConfig.xml (added)
+++ activemq/trunk/activemq-runtime-config/src/test/resources/org/apache/activemq/emptyManualUpdateConfig.xml Thu Aug 22 22:47:21 2013
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<beans
+  xmlns="http://www.springframework.org/schema/beans"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
+  http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
+
+  <broker xmlns="http://activemq.apache.org/schema/core" start="false" persistent="false" >
+    <plugins>
+      <runtimeConfigurationPlugin />
+    </plugins>
+  </broker>
+</beans>

Propchange: activemq/trunk/activemq-runtime-config/src/test/resources/org/apache/activemq/emptyManualUpdateConfig.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: activemq/trunk/activemq-runtime-config/src/test/resources/org/apache/activemq/emptyManualUpdateConfig.xml
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Propchange: activemq/trunk/activemq-runtime-config/src/test/resources/org/apache/activemq/emptyManualUpdateConfig.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: activemq/trunk/activemq-runtime-config/src/test/resources/org/apache/activemq/parseErrorConfig.xml
URL: http://svn.apache.org/viewvc/activemq/trunk/activemq-runtime-config/src/test/resources/org/apache/activemq/parseErrorConfig.xml?rev=1516650&view=auto
==============================================================================
--- activemq/trunk/activemq-runtime-config/src/test/resources/org/apache/activemq/parseErrorConfig.xml (added)
+++ activemq/trunk/activemq-runtime-config/src/test/resources/org/apache/activemq/parseErrorConfig.xml Thu Aug 22 22:47:21 2013
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<beans
+  xmlns="http://www.springframework.org/schema/beans"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
+  http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
+
+  <broker xmlns="http://activemq.apache.org/schema/core" start="false" persistent="false" >
+    <plugins>
+      <runtimeConfigurationPlugin />
+    </plugins>
+    <dudElement fromWrongNameSpace="true" />;
+  </broker>
+</beans>

Propchange: activemq/trunk/activemq-runtime-config/src/test/resources/org/apache/activemq/parseErrorConfig.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: activemq/trunk/activemq-runtime-config/src/test/resources/org/apache/activemq/parseErrorConfig.xml
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Propchange: activemq/trunk/activemq-runtime-config/src/test/resources/org/apache/activemq/parseErrorConfig.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml