http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/daf40919/software/base/src/test/java/org/apache/brooklyn/feed/jmx/JmxFeedTest.java
----------------------------------------------------------------------
diff --git 
a/software/base/src/test/java/org/apache/brooklyn/feed/jmx/JmxFeedTest.java 
b/software/base/src/test/java/org/apache/brooklyn/feed/jmx/JmxFeedTest.java
new file mode 100644
index 0000000..3975e68
--- /dev/null
+++ b/software/base/src/test/java/org/apache/brooklyn/feed/jmx/JmxFeedTest.java
@@ -0,0 +1,422 @@
+/*
+ * 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.brooklyn.feed.jmx;
+
+import static org.apache.brooklyn.test.TestUtils.executeUntilSucceeds;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.StandardEmitterMBean;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.api.sensor.SensorEvent;
+import org.apache.brooklyn.api.sensor.SensorEventListener;
+import org.apache.brooklyn.core.entity.AbstractEntity;
+import org.apache.brooklyn.core.entity.Attributes;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.feed.ConfigToAttributes;
+import org.apache.brooklyn.core.location.PortRanges;
+import org.apache.brooklyn.core.location.SimulatedLocation;
+import org.apache.brooklyn.core.sensor.BasicAttributeSensor;
+import org.apache.brooklyn.core.sensor.BasicNotificationSensor;
+import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.core.test.entity.TestApplication;
+import org.apache.brooklyn.core.test.entity.TestApplicationImpl;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.core.test.entity.TestEntityImpl;
+import org.apache.brooklyn.entity.java.JmxSupport;
+import org.apache.brooklyn.entity.java.UsesJmx;
+import org.apache.brooklyn.entity.java.UsesJmx.JmxAgentModes;
+import 
org.apache.brooklyn.entity.software.base.test.jmx.GeneralisedDynamicMBean;
+import org.apache.brooklyn.entity.software.base.test.jmx.JmxService;
+import org.apache.brooklyn.feed.jmx.JmxAttributePollConfig;
+import org.apache.brooklyn.feed.jmx.JmxFeed;
+import org.apache.brooklyn.feed.jmx.JmxHelper;
+import org.apache.brooklyn.feed.jmx.JmxNotificationFilters;
+import org.apache.brooklyn.feed.jmx.JmxNotificationSubscriptionConfig;
+import org.apache.brooklyn.feed.jmx.JmxOperationPollConfig;
+import org.apache.brooklyn.feed.jmx.JmxValueFunctions;
+import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.test.TestUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.testng.collections.Lists;
+import 
org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Test the operation of the {@link JmxFeed} class.
+ * <p>
+ * Also confirm some of the JMX setup done by {@link JmxSupport} and {@link 
JmxHelper},
+ * based on ports in {@link UsesJmx}.
+ * <p>
+ * TODO tests of other JMX_AGENT_MODE are done in ActiveMqIntegrationTest; 
+ * would be nice to promote some to live here
+ */
+public class JmxFeedTest {
+    
+    // FIXME Move out the JmxHelper tests into the JmxHelperTest class
+    
+    // FIXME Also test that setting poll period takes effect
+    
+    private static final Logger log = 
LoggerFactory.getLogger(JmxFeedTest.class);
+
+    private static final int TIMEOUT_MS = 5000;
+    private static final int SHORT_WAIT_MS = 250;
+    
+    private JmxService jmxService;
+    private TestApplication app;
+    private TestEntity entity;
+    private JmxFeed feed;
+    private JmxHelper jmxHelper;
+    
+    private AttributeSensor<Integer> intAttribute = 
Sensors.newIntegerSensor("brooklyn.test.intAttribute", "Brooklyn testing int 
attribute");
+    private AttributeSensor<String> stringAttribute = 
Sensors.newStringSensor("brooklyn.test.stringAttribute", "Brooklyn testing 
string attribute");
+    private BasicAttributeSensor<Map> mapAttribute = new 
BasicAttributeSensor<Map>(Map.class, "brooklyn.test.mapAttribute", "Brooklyn 
testing map attribute");
+    private String objectName = "Brooklyn:type=MyTestMBean,name=myname";
+    private ObjectName jmxObjectName;
+    private String attributeName = "myattrib";
+    private String opName = "myop";
+    
+    public static class TestEntityWithJmx extends TestEntityImpl {
+        @Override public void init() {
+            setAttribute(Attributes.HOSTNAME, "localhost");
+            setAttribute(UsesJmx.JMX_PORT, 
+                    
LocalhostMachineProvisioningLocation.obtainPort(PortRanges.fromString("40123+")));
+            // only supports no-agent, at the moment
+            setConfig(UsesJmx.JMX_AGENT_MODE, JmxAgentModes.NONE);
+            setAttribute(UsesJmx.RMI_REGISTRY_PORT, -1);  // -1 means to use 
the JMX_PORT only
+            ConfigToAttributes.apply(this, UsesJmx.JMX_CONTEXT);
+        }
+    }
+    
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() throws Exception {
+        jmxObjectName = new ObjectName(objectName);
+        
+        // Create an entity and configure it with the above JMX service
+        app = TestApplication.Factory.newManagedInstanceForTests();
+        entity = 
app.createAndManageChild(EntitySpec.create(TestEntity.class).impl(TestEntityWithJmx.class));
+        app.start(ImmutableList.of(new SimulatedLocation()));
+
+        jmxHelper = new JmxHelper(entity);
+        
+        jmxService = new JmxService(entity);
+    }
+    
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() throws Exception {
+        if (feed != null) feed.stop();
+        if (jmxHelper != null) jmxHelper.disconnect();
+        if (jmxService != null) jmxService.shutdown();
+        if (app != null) Entities.destroyAll(app.getManagementContext());
+        feed = null;
+    }
+
+    @Test
+    public void testJmxAttributePollerReturnsMBeanAttribute() throws Exception 
{
+        GeneralisedDynamicMBean mbean = 
jmxService.registerMBean(ImmutableMap.of(attributeName, 42), objectName);
+
+        feed = JmxFeed.builder()
+                .entity(entity)
+                .pollAttribute(new 
JmxAttributePollConfig<Integer>(intAttribute)
+                        .objectName(objectName)
+                        .period(50)
+                        .attributeName(attributeName))
+                .build();
+        
+        // Starts with value defined when registering...
+        assertSensorEventually(intAttribute, 42, TIMEOUT_MS);
+
+        // Change the value and check it updates
+        mbean.updateAttributeValue(attributeName, 64);
+        assertSensorEventually(intAttribute, 64, TIMEOUT_MS);
+    }
+
+    @Test
+    public void testJmxAttributeOfTypeTabularDataProviderConvertedToMap() 
throws Exception {
+        // Create the CompositeType and TabularData
+        CompositeType compositeType = new CompositeType(
+                "typeName",
+                "description",
+                new String[] {"myint", "mystring", "mybool"},    // item names
+                new String[] {"myint", "mystring", "mybool"},    // item 
descriptions, can't be null or empty string
+                new OpenType<?>[] {SimpleType.INTEGER, SimpleType.STRING, 
SimpleType.BOOLEAN}
+        );
+        TabularType tt = new TabularType(
+                "typeName",
+                "description",
+                compositeType,
+                new String[] {"myint"}
+        );
+        TabularDataSupport tds = new TabularDataSupport(tt);
+        tds.put(new CompositeDataSupport(
+                compositeType,
+                new String[] {"mybool", "myint", "mystring"},
+                new Object[] {true, 1234, "on"}
+        ));
+
+        // Create MBean
+        GeneralisedDynamicMBean mbean = 
jmxService.registerMBean(ImmutableMap.of(attributeName, tds), objectName);
+
+        feed = JmxFeed.builder()
+                .entity(entity)
+                .pollAttribute(new JmxAttributePollConfig<Map>(mapAttribute)
+                        .objectName(objectName)
+                        .attributeName(attributeName)
+                        
.onSuccess((Function)JmxValueFunctions.tabularDataToMap()))
+                .build();
+
+        // Starts with value defined when registering...
+        assertSensorEventually(
+                mapAttribute, 
+                ImmutableMap.of("myint", 1234, "mystring", "on", "mybool", 
Boolean.TRUE), 
+                TIMEOUT_MS);
+    }
+
+    @Test
+    public void testJmxOperationPolledForSensor() throws Exception {
+        // This is awful syntax...
+        final int opReturnVal = 123;
+        final AtomicInteger invocationCount = new AtomicInteger();
+        MBeanOperationInfo opInfo = new MBeanOperationInfo(opName, "my descr", 
new MBeanParameterInfo[0], Integer.class.getName(), MBeanOperationInfo.ACTION);
+        GeneralisedDynamicMBean mbean = jmxService.registerMBean(
+                Collections.emptyMap(), 
+                ImmutableMap.of(opInfo, new Function<Object[], Integer>() {
+                        public Integer apply(Object[] args) {
+                            invocationCount.incrementAndGet(); return 
opReturnVal;
+                        }}),
+                objectName);
+
+        feed = JmxFeed.builder()
+                .entity(entity)
+                .pollOperation(new 
JmxOperationPollConfig<Integer>(intAttribute)
+                        .objectName(objectName)
+                        .operationName(opName))
+                .build();
+        
+        TestUtils.executeUntilSucceeds(ImmutableMap.of("timeout", TIMEOUT_MS), 
new Runnable() {
+            public void run() {
+                assertTrue(invocationCount.get() > 0, 
"invocationCount="+invocationCount);
+                assertEquals(entity.getAttribute(intAttribute), 
(Integer)opReturnVal);
+            }});
+    }
+
+    @Test
+    public void testJmxOperationWithArgPolledForSensor() throws Exception {
+        // This is awful syntax...
+        MBeanParameterInfo paramInfo = new MBeanParameterInfo("param1", 
String.class.getName(), "my param1");
+        MBeanParameterInfo[] paramInfos = new MBeanParameterInfo[] {paramInfo};
+        MBeanOperationInfo opInfo = new MBeanOperationInfo(opName, "my descr", 
paramInfos, String.class.getName(), MBeanOperationInfo.ACTION);
+        GeneralisedDynamicMBean mbean = jmxService.registerMBean(
+                Collections.emptyMap(), 
+                ImmutableMap.of(opInfo, new Function<Object[], String>() {
+                        public String apply(Object[] args) {
+                            return args[0]+"suffix";
+                        }}),
+                objectName);
+        
+        feed = JmxFeed.builder()
+                .entity(entity)
+                .pollOperation(new 
JmxOperationPollConfig<String>(stringAttribute)
+                        .objectName(objectName)
+                        .operationName(opName)
+                        .operationParams(ImmutableList.of("myprefix")))
+                .build();
+        
+        assertSensorEventually(stringAttribute, "myprefix"+"suffix", 
TIMEOUT_MS);
+    }
+
+    @Test
+    public void testJmxNotificationSubscriptionForSensor() throws Exception {
+        final String one = "notification.one", two = "notification.two";
+        final StandardEmitterMBean mbean = 
jmxService.registerMBean(ImmutableList.of(one, two), objectName);
+        final AtomicInteger sequence = new AtomicInteger(0);
+
+        feed = JmxFeed.builder()
+                .entity(entity)
+                .subscribeToNotification(new 
JmxNotificationSubscriptionConfig<Integer>(intAttribute)
+                        .objectName(objectName)
+                        
.notificationFilter(JmxNotificationFilters.matchesType(one)))
+                .build();        
+
+        // Notification updates the sensor
+        // Note that subscription is done async, so can't just send 
notification immediately during test.
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), new 
Runnable() {
+            public void run() {
+                sendNotification(mbean, one, sequence.getAndIncrement(), 123);
+                assertEquals(entity.getAttribute(intAttribute), (Integer)123);
+            }});
+        
+        // But other notification types are ignored
+        sendNotification(mbean, two, sequence.getAndIncrement(), -1);
+            
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), new 
Runnable() {
+            public void run() {
+                assertEquals(entity.getAttribute(intAttribute), (Integer)123);
+            }});
+    }
+    
+    @Test
+    public void testJmxNotificationSubscriptionForSensorParsingNotification() 
throws Exception {
+        final String one = "notification.one", two = "notification.two";
+        final StandardEmitterMBean mbean = 
jmxService.registerMBean(ImmutableList.of(one, two), objectName);
+        final AtomicInteger sequence = new AtomicInteger(0);
+        
+        feed = JmxFeed.builder()
+                .entity(entity)
+                .subscribeToNotification(new 
JmxNotificationSubscriptionConfig<Integer>(intAttribute)
+                        .objectName(objectName)
+                        
.notificationFilter(JmxNotificationFilters.matchesType(one))
+                        .onNotification(new Function<Notification, Integer>() {
+                            public Integer apply(Notification notif) {
+                                return (Integer) notif.getUserData();
+                            }
+                        }))
+                .build();
+        
+        
+        // Notification updates the sensor
+        // Note that subscription is done async, so can't just send 
notification immediately during test.
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), new 
Runnable() {
+            public void run() {
+                sendNotification(mbean, one, sequence.getAndIncrement(), 123);
+                assertEquals(entity.getAttribute(intAttribute), (Integer)123);
+            }});
+    }
+
+    @Test
+    public void testJmxNotificationMultipleSubscriptionUsingListener() throws 
Exception {
+        final String one = "notification.one";
+        final String two = "notification.two";
+        final StandardEmitterMBean mbean = 
jmxService.registerMBean(ImmutableList.of(one, two), objectName);
+        final AtomicInteger sequence = new AtomicInteger(0);
+
+        feed = JmxFeed.builder()
+                .entity(entity)
+                .subscribeToNotification(new 
JmxNotificationSubscriptionConfig<Integer>(intAttribute)
+                        .objectName(objectName)
+                        
.notificationFilter(JmxNotificationFilters.matchesTypes(one, two)))
+                .build();
+        
+        // Notification updates the sensor
+        // Note that subscription is done async, so can't just send 
notification immediately during test.
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), new 
Runnable() {
+            public void run() {
+                sendNotification(mbean, one, sequence.getAndIncrement(), 123);
+                assertEquals(entity.getAttribute(intAttribute), (Integer)123);
+            }});
+
+        // And wildcard means other notifications also received
+        sendNotification(mbean, two, sequence.getAndIncrement(), 456);
+        assertSensorEventually(intAttribute, 456, TIMEOUT_MS);
+    }
+
+    // Test reproduces functionality used in Monterey, for Venue entity being 
told of requestActor
+    @Test
+    public void 
testSubscribeToJmxNotificationAndEmitCorrespondingNotificationSensor() throws 
Exception {
+        TestApplication app2 = new TestApplicationImpl();
+        final EntityWithEmitter entity = new EntityWithEmitter(app2);
+        Entities.startManagement(app2);
+        try {
+            app2.start(ImmutableList.of(new SimulatedLocation()));
+            
+            final List<SensorEvent<String>> received = Lists.newArrayList();
+            app2.subscribe(null, EntityWithEmitter.MY_NOTIF, new 
SensorEventListener<String>() {
+                public void onEvent(SensorEvent<String> event) {
+                    received.add(event);
+                }});
+    
+            final StandardEmitterMBean mbean = 
jmxService.registerMBean(ImmutableList.of("one"), objectName);
+            final AtomicInteger sequence = new AtomicInteger(0);
+            
+            jmxHelper.connect(TIMEOUT_MS);
+            jmxHelper.addNotificationListener(jmxObjectName, new 
NotificationListener() {
+                    public void handleNotification(Notification notif, Object 
callback) {
+                        if (notif.getType().equals("one")) {
+                            entity.emit(EntityWithEmitter.MY_NOTIF, (String) 
notif.getUserData());
+                        }
+                    }});
+            
+
+            Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), 
new Runnable() {
+                public void run() {
+                    sendNotification(mbean, "one", sequence.getAndIncrement(), 
"abc");
+                    assertTrue(received.size() > 0, "received size should be 
bigger than 0");
+                    assertEquals(received.get(0).getValue(), "abc");
+                }});
+        } finally {
+            Entities.destroyAll(app2.getManagementContext());
+        }
+    }
+    
+    public static class EntityWithEmitter extends AbstractEntity {
+        public static final BasicNotificationSensor<String> MY_NOTIF = new 
BasicNotificationSensor<String>(String.class, "test.myNotif", "My notif");
+        
+        public EntityWithEmitter(Entity owner) {
+            super(owner);
+        }
+        public EntityWithEmitter(Map flags) {
+            super(flags);
+        }
+        public EntityWithEmitter(Map flags, Entity owner) {
+            super(flags, owner);
+        }
+    }
+    
+    private Notification sendNotification(StandardEmitterMBean mbean, String 
type, long seq, Object userData) {
+        Notification notif = new Notification(type, mbean, seq);
+        notif.setUserData(userData);
+        mbean.sendNotification(notif);
+        return notif;
+    }
+    
+    private <T> void assertSensorEventually(final AttributeSensor<T> sensor, 
final T expectedVal, long timeout) {
+        executeUntilSucceeds(ImmutableMap.of("timeout", timeout), new 
Callable<Void>() {
+            public Void call() {
+                assertEquals(entity.getAttribute(sensor), expectedVal);
+                return null;
+            }});
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/daf40919/software/base/src/test/java/org/apache/brooklyn/feed/jmx/JmxHelperTest.java
----------------------------------------------------------------------
diff --git 
a/software/base/src/test/java/org/apache/brooklyn/feed/jmx/JmxHelperTest.java 
b/software/base/src/test/java/org/apache/brooklyn/feed/jmx/JmxHelperTest.java
new file mode 100644
index 0000000..3470166
--- /dev/null
+++ 
b/software/base/src/test/java/org/apache/brooklyn/feed/jmx/JmxHelperTest.java
@@ -0,0 +1,311 @@
+/*
+ * 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.brooklyn.feed.jmx;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.fail;
+
+import java.io.IOException;
+import java.util.List;
+
+import javax.management.DynamicMBean;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.StandardEmitterMBean;
+
+import 
org.apache.brooklyn.entity.software.base.test.jmx.GeneralisedDynamicMBean;
+import org.apache.brooklyn.entity.software.base.test.jmx.JmxService;
+import org.apache.brooklyn.feed.jmx.JmxHelper;
+import org.apache.brooklyn.test.TestUtils;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.jclouds.util.Throwables2;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.testng.collections.Lists;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class JmxHelperTest {
+
+    private static final Logger log = 
LoggerFactory.getLogger(JmxHelperTest.class);
+    
+    private static final String LOCALHOST_NAME = "localhost";
+    
+    private static final int TIMEOUT_MS = 5000;
+    private static final int SHORT_WAIT_MS = 250;
+
+    private JmxService jmxService;
+    private JmxHelper jmxHelper;
+    
+    private String objectName = "Brooklyn:type=MyTestMBean,name=myname";
+    private String objectNameWithWildcard = 
"Brooklyn:type=MyTestMBean,name=mynam*";
+    private ObjectName jmxObjectName;
+    private ObjectName jmxObjectNameWithWildcard;
+    private String attributeName = "myattrib";
+    private String opName = "myop";
+    
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() throws Exception {
+        jmxObjectName = new ObjectName(objectName);
+        jmxObjectNameWithWildcard = new ObjectName(objectNameWithWildcard);
+        jmxService = newJmxServiceRetrying(LOCALHOST_NAME, 5);
+        jmxHelper = new JmxHelper(jmxService.getUrl());
+        jmxHelper.setMinTimeBetweenReconnectAttempts(0);
+        jmxHelper.connect(TIMEOUT_MS);
+    }
+    
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() throws Exception {
+        if (jmxHelper != null) jmxHelper.disconnect();
+        if (jmxService != null) jmxService.shutdown();
+        jmxHelper = null;
+        jmxService = null;
+    }
+
+    @Test
+    public void testGetAttribute() throws Exception {
+        GeneralisedDynamicMBean mbean = 
jmxService.registerMBean(MutableMap.of("myattr", "myval"), objectName);
+        assertEquals(jmxHelper.getAttribute(jmxObjectName, "myattr"), "myval");
+    }
+
+    @Test
+    public void testGetAttributeUsingObjectNameWildcard() throws Exception {
+        GeneralisedDynamicMBean mbean = 
jmxService.registerMBean(MutableMap.of("myattr", "myval"), objectName);
+        assertEquals(jmxHelper.getAttribute(jmxObjectNameWithWildcard, 
"myattr"), "myval");
+    }
+
+    @Test
+    public void testSetAttribute() throws Exception {
+        DynamicMBean mbean = jmxService.registerMBean(MutableMap.of("myattr", 
"myval"), objectName);
+
+        jmxHelper.setAttribute(jmxObjectName, "myattr", "abc");
+        Object actual = jmxHelper.getAttribute(jmxObjectName, "myattr");
+        assertEquals(actual, "abc");
+    }
+
+    @Test
+    public void testSetAttributeUsingObjectNameWildcard() throws Exception {
+        DynamicMBean mbean = jmxService.registerMBean(MutableMap.of("myattr", 
"myval"), objectName);
+
+        jmxHelper.setAttribute(jmxObjectNameWithWildcard, "myattr", "abc");
+        Object actual = jmxHelper.getAttribute(jmxObjectName, "myattr");
+        assertEquals(actual, "abc");
+    }
+
+    @Test
+    public void testInvokeOperationWithNoArgs() throws Exception {
+        final String opReturnVal = "my result";
+        MBeanOperationInfo opInfo = new MBeanOperationInfo(opName, "my descr", 
new MBeanParameterInfo[0], String.class.getName(), MBeanOperationInfo.ACTION);
+        Function<Object[], String> opImpl = new Function<Object[], String>() {
+            @Override public String apply(Object[] args) {
+                assertEquals(args.length, 0, "args="+args);
+                return opReturnVal;
+            }
+        };
+        GeneralisedDynamicMBean mbean = 
jmxService.registerMBean(ImmutableMap.of(), ImmutableMap.of(opInfo, opImpl), 
objectName);
+        
+        assertEquals(jmxHelper.operation(objectName, opName), opReturnVal);
+    }
+
+    @Test
+    public void testInvokeOperationUsingObjectNameWildcard() throws Exception {
+        final String opReturnVal = "my result";
+        MBeanOperationInfo opInfo = new MBeanOperationInfo(opName, "my descr", 
new MBeanParameterInfo[0], String.class.getName(), MBeanOperationInfo.ACTION);
+        Function<Object[], String> opImpl = new Function<Object[], String>() {
+            @Override public String apply(Object[] args) {
+                assertEquals(args.length, 0, "args="+args);
+                return opReturnVal;
+            }
+        };
+        GeneralisedDynamicMBean mbean = 
jmxService.registerMBean(ImmutableMap.of(), ImmutableMap.of(opInfo, opImpl), 
objectName);
+        
+        assertEquals(jmxHelper.operation(objectNameWithWildcard, opName), 
opReturnVal);
+    }
+
+    @Test
+    public void testInvokeOperationWithArgs() throws Exception {
+        final String opReturnPrefix = "my result prefix/";
+        String opParam1 = "my param 1";
+        MBeanOperationInfo opInfo = new MBeanOperationInfo(
+                opName, 
+                "my descr", 
+                new MBeanParameterInfo[] {new MBeanParameterInfo("myParam1", 
String.class.getName(), "my param1 descr")}, 
+                String.class.getName(), 
+                MBeanOperationInfo.ACTION);
+        Function<Object[],String> opImpl = new Function<Object[],String>() {
+            public String apply(Object[] input) {
+                return opReturnPrefix+input[0];
+            }
+        };
+        GeneralisedDynamicMBean mbean = 
jmxService.registerMBean(ImmutableMap.of(), ImmutableMap.of(opInfo, opImpl), 
objectName);
+        
+        assertEquals(jmxHelper.operation(objectName, opName, opParam1), 
opReturnPrefix+opParam1);
+    }
+
+    @Test
+    public void testReconnectsOnJmxServerTemporaryFailure() throws Exception {
+        int port = jmxService.getJmxPort();
+        GeneralisedDynamicMBean mbean = 
jmxService.registerMBean(MutableMap.of("myattr", "myval"), objectName);
+        assertEquals(jmxHelper.getAttribute(jmxObjectName, "myattr"), "myval");
+        
+        // Simulate temporary network-failure
+        jmxService.shutdown();
+
+        // Ensure that we have a failed query while the "network is down"      
   
+        try {
+            jmxHelper.getAttribute(jmxObjectName, attributeName);
+            fail();
+        } catch (Exception e) {
+            if (Throwables2.getFirstThrowableOfType(e, IOException.class) == 
null) {
+                throw e;
+            }
+        }
+
+        // Simulate the network restarting
+        jmxService = new JmxService(LOCALHOST_NAME, port);
+        
+        GeneralisedDynamicMBean mbean2 = 
jmxService.registerMBean(MutableMap.of("myattr", "myval2"), objectName);
+        assertEquals(jmxHelper.getAttribute(jmxObjectName, "myattr"), 
"myval2");
+    }
+    
+    @Test(expectedExceptions = {IllegalStateException.class})
+    public void testJmxCheckInstanceExistsEventuallyThrowsIfNotFound() throws 
Exception {
+        jmxHelper.assertMBeanExistsEventually(new 
ObjectName("Brooklyn:type=DoesNotExist,name=doesNotExist"), 1L);
+    }
+
+    @Test
+    public void testJmxObjectCheckExistsEventuallyReturnsIfFoundImmediately() 
throws Exception {
+        GeneralisedDynamicMBean mbean = jmxService.registerMBean(objectName);
+        jmxHelper.assertMBeanExistsEventually(jmxObjectName, 1L);
+    }
+
+    @Test
+    public void 
testJmxObjectCheckExistsEventuallyTakingLongReturnsIfFoundImmediately() throws 
Exception {
+        GeneralisedDynamicMBean mbean = jmxService.registerMBean(objectName);
+        jmxHelper.assertMBeanExistsEventually(jmxObjectName, 1L);
+    }
+
+    @Test
+    public void 
testJmxObjectCheckExistsEventuallyReturnsIfCreatedDuringPolling() throws 
Exception {
+        Thread t = new Thread(new Runnable() {
+                public void run() {
+                    try {
+                        Thread.sleep(SHORT_WAIT_MS);
+                        GeneralisedDynamicMBean mbean = 
jmxService.registerMBean(objectName);
+                    } catch (InterruptedException e) {
+                        return; // graceful return
+                    } catch (Exception e) {
+                        throw Exceptions.propagate(e);
+                    }
+                }});
+        try {
+            t.start();
+            
+            jmxHelper.assertMBeanExistsEventually(jmxObjectName, TIMEOUT_MS);
+        } finally {
+            t.interrupt();
+            t.join(TIMEOUT_MS);
+            assertFalse(t.isAlive());
+        }        
+    }
+
+    @Test
+    public void testSubscribeToJmxNotificationsDirectlyWithJmxHelper() throws 
Exception {
+        StandardEmitterMBean mbean = 
jmxService.registerMBean(ImmutableList.of("one"), objectName);
+        int sequence = 0;
+        final List<Notification> received = Lists.newArrayList();
+
+        jmxHelper.addNotificationListener(jmxObjectName, new 
NotificationListener() {
+            public void handleNotification(Notification notif, Object 
callback) {
+                received.add(notif);
+            }});
+                    
+
+        final Notification notif = sendNotification(mbean, "one", sequence++, 
"abc");
+
+        TestUtils.executeUntilSucceeds(ImmutableMap.of("timeout", TIMEOUT_MS), 
new Runnable() {
+            public void run() {
+                assertEquals(received.size(), 1);
+                assertNotificationsEqual(received.get(0), notif);
+            }});
+    }
+
+    // Visual-inspection test that LOG.warn happens only once; TODO setup a 
listener to the logging output
+    @Test
+    public void testMBeanNotFoundLoggedOnlyOncePerUrl() throws Exception {
+        ObjectName wrongObjectName = new 
ObjectName("DoesNotExist:type=DoesNotExist");
+
+        // Expect just one log message about:
+        //     JMX object DoesNotExist:type=DoesNotExist not found at 
service:jmx:rmi://localhost:1099/jndi/rmi://localhost:9001/jmxrmi"
+        for (int i = 0; i < 10; i++) {
+            jmxHelper.findMBean(wrongObjectName);
+        }
+
+        jmxService.shutdown();
+        jmxHelper.disconnect();
+        
+        jmxService = newJmxServiceRetrying(LOCALHOST_NAME, 5);
+        jmxHelper = new JmxHelper(jmxService.getUrl());
+        jmxHelper.connect();
+        
+        // Expect just one log message about:
+        //     JMX object DoesNotExist:type=DoesNotExist not found at 
service:jmx:rmi://localhost:1099/jndi/rmi://localhost:9001/jmxrmi"
+        for (int i = 0; i < 10; i++) {
+            jmxHelper.findMBean(wrongObjectName);
+        }
+    }
+
+    private JmxService newJmxServiceRetrying(String host, int retries) throws 
Exception {
+        Exception lastexception = null;
+        for (int i = 0; i < retries; i++) {
+            try {
+                return new JmxService(host, (int)(11000+(500*Math.random())));
+            } catch (Exception e) {
+                log.debug("Unable to create JMX service during test - 
"+retries+" retries remaining");
+                lastexception = e;
+            }
+        }
+        throw lastexception;
+    }
+
+    private Notification sendNotification(StandardEmitterMBean mbean, String 
type, long seq, Object userData) {
+        Notification notif = new Notification(type, mbean, seq);
+        notif.setUserData(userData);
+        mbean.sendNotification(notif);
+        return notif;
+    }
+    
+    private void assertNotificationsEqual(Notification n1, Notification n2) {
+        assertEquals(n1.getType(), n2.getType());
+        assertEquals(n1.getSequenceNumber(), n2.getSequenceNumber());
+        assertEquals(n1.getUserData(), n2.getUserData());
+        assertEquals(n1.getTimeStamp(), n2.getTimeStamp());
+        assertEquals(n1.getMessage(), n2.getMessage());
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/daf40919/software/base/src/test/java/org/apache/brooklyn/feed/jmx/RebindJmxFeedTest.java
----------------------------------------------------------------------
diff --git 
a/software/base/src/test/java/org/apache/brooklyn/feed/jmx/RebindJmxFeedTest.java
 
b/software/base/src/test/java/org/apache/brooklyn/feed/jmx/RebindJmxFeedTest.java
new file mode 100644
index 0000000..f521932
--- /dev/null
+++ 
b/software/base/src/test/java/org/apache/brooklyn/feed/jmx/RebindJmxFeedTest.java
@@ -0,0 +1,148 @@
+/*
+ * 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.brooklyn.feed.jmx;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.Collection;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.api.sensor.Feed;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.entity.Attributes;
+import org.apache.brooklyn.core.feed.ConfigToAttributes;
+import org.apache.brooklyn.core.location.PortRanges;
+import org.apache.brooklyn.core.mgmt.rebind.RebindTestFixtureWithApp;
+import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.core.test.entity.TestEntityImpl;
+import org.apache.brooklyn.entity.java.UsesJmx;
+import org.apache.brooklyn.entity.java.UsesJmx.JmxAgentModes;
+import 
org.apache.brooklyn.entity.software.base.test.jmx.GeneralisedDynamicMBean;
+import org.apache.brooklyn.entity.software.base.test.jmx.JmxService;
+import org.apache.brooklyn.feed.jmx.JmxAttributePollConfig;
+import org.apache.brooklyn.feed.jmx.JmxFeed;
+import org.apache.brooklyn.feed.jmx.JmxHelper;
+import org.apache.brooklyn.test.EntityTestUtils;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import 
org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
+public class RebindJmxFeedTest extends RebindTestFixtureWithApp {
+
+    private static final Logger log = 
LoggerFactory.getLogger(RebindJmxFeedTest.class);
+
+    private static final String LOCALHOST_NAME = "localhost";
+
+    static final AttributeSensor<String> SENSOR_STRING = 
Sensors.newStringSensor("aString", "");
+    static final AttributeSensor<Integer> SENSOR_INT = 
Sensors.newIntegerSensor( "aLong", "");
+
+    static final String JMX_ATTRIBUTE_NAME = "myattr";
+    static final String OBJECT_NAME = "Brooklyn:type=MyTestMBean,name=myname";
+    
+    private JmxService jmxService;
+    
+    @BeforeMethod(alwaysRun=true)
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        
+        // Create an entity and configure it with the above JMX service
+        //jmxService = newJmxServiceRetrying(LOCALHOST_NAME, 5);
+    }
+    
+    @AfterMethod(alwaysRun=true)
+    @Override
+    public void tearDown() throws Exception {
+        if (jmxService != null) jmxService.shutdown();
+        super.tearDown();
+    }
+
+    @Test
+    public void testJmxFeedIsPersisted() throws Exception {
+        runJmxFeedIsPersisted(false);
+    }
+
+    @Test
+    public void testJmxFeedIsPersistedWithPreCreatedJmxHelper() throws 
Exception {
+        runJmxFeedIsPersisted(true);
+    }
+
+    protected void runJmxFeedIsPersisted(boolean preCreateJmxHelper) throws 
Exception {
+        TestEntity origEntity = 
origApp.createAndManageChild(EntitySpec.create(TestEntity.class).impl(MyEntityWithJmxFeedImpl.class)
+                .configure(MyEntityWithJmxFeedImpl.PRE_CREATE_JMX_HELPER, 
preCreateJmxHelper));
+        origApp.start(ImmutableList.<Location>of());
+        
+        jmxService = new JmxService(origEntity);
+        GeneralisedDynamicMBean mbean = 
jmxService.registerMBean(MutableMap.of(JMX_ATTRIBUTE_NAME, "myval"), 
OBJECT_NAME);
+        
+        EntityTestUtils.assertAttributeEqualsEventually(origEntity, 
SENSOR_STRING, "myval");
+        assertEquals(origEntity.feeds().getFeeds().size(), 1);
+
+        newApp = rebind();
+        TestEntity newEntity = (TestEntity) 
Iterables.getOnlyElement(newApp.getChildren());
+        
+        Collection<Feed> newFeeds = newEntity.feeds().getFeeds();
+        assertEquals(newFeeds.size(), 1);
+        
+        // Expect the feed to still be polling
+        newEntity.setAttribute(SENSOR_STRING, null);
+        EntityTestUtils.assertAttributeEqualsEventually(newEntity, 
SENSOR_STRING, "myval");
+    }
+
+    public static class MyEntityWithJmxFeedImpl extends TestEntityImpl {
+        public static final ConfigKey<Boolean> PRE_CREATE_JMX_HELPER = 
ConfigKeys.newBooleanConfigKey("test.rebindjmx.preCreateJmxHelper", "", false);
+        
+        @Override
+        public void start(Collection<? extends Location> locs) {
+            // TODO Auto-generated method stub
+            super.start(locs);
+            
+            setAttribute(Attributes.HOSTNAME, "localhost");
+            setAttribute(UsesJmx.JMX_PORT, 
+                    
LocalhostMachineProvisioningLocation.obtainPort(PortRanges.fromString("40123+")));
+            // only supports no-agent, at the moment
+            setConfig(UsesJmx.JMX_AGENT_MODE, JmxAgentModes.NONE);
+            setAttribute(UsesJmx.RMI_REGISTRY_PORT, -1);  // -1 means to use 
the JMX_PORT only
+            ConfigToAttributes.apply(this, UsesJmx.JMX_CONTEXT);
+            
+            JmxFeed.Builder feedBuilder = JmxFeed.builder()
+                    .entity(this)
+                    .pollAttribute(new 
JmxAttributePollConfig<String>(SENSOR_STRING)
+                            .objectName(OBJECT_NAME)
+                            .period(50)
+                            .attributeName(JMX_ATTRIBUTE_NAME));
+            if (getConfig(PRE_CREATE_JMX_HELPER)) {
+                JmxHelper jmxHelper = new JmxHelper(this);
+                feedBuilder.helper(jmxHelper);
+            }
+            addFeed(feedBuilder.build());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/daf40919/software/base/src/test/java/org/apache/brooklyn/sensor/feed/jmx/JmxFeedTest.java
----------------------------------------------------------------------
diff --git 
a/software/base/src/test/java/org/apache/brooklyn/sensor/feed/jmx/JmxFeedTest.java
 
b/software/base/src/test/java/org/apache/brooklyn/sensor/feed/jmx/JmxFeedTest.java
deleted file mode 100644
index 8f722b2..0000000
--- 
a/software/base/src/test/java/org/apache/brooklyn/sensor/feed/jmx/JmxFeedTest.java
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- * 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.brooklyn.sensor.feed.jmx;
-
-import static org.apache.brooklyn.test.TestUtils.executeUntilSucceeds;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import javax.management.MBeanOperationInfo;
-import javax.management.MBeanParameterInfo;
-import javax.management.Notification;
-import javax.management.NotificationListener;
-import javax.management.ObjectName;
-import javax.management.StandardEmitterMBean;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-import javax.management.openmbean.TabularDataSupport;
-import javax.management.openmbean.TabularType;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.api.sensor.AttributeSensor;
-import org.apache.brooklyn.api.sensor.SensorEvent;
-import org.apache.brooklyn.api.sensor.SensorEventListener;
-import org.apache.brooklyn.core.entity.AbstractEntity;
-import org.apache.brooklyn.core.entity.Attributes;
-import org.apache.brooklyn.core.entity.Entities;
-import org.apache.brooklyn.core.location.PortRanges;
-import org.apache.brooklyn.core.location.SimulatedLocation;
-import org.apache.brooklyn.core.sensor.BasicAttributeSensor;
-import org.apache.brooklyn.core.sensor.BasicNotificationSensor;
-import org.apache.brooklyn.core.sensor.Sensors;
-import org.apache.brooklyn.core.test.entity.TestApplication;
-import org.apache.brooklyn.core.test.entity.TestApplicationImpl;
-import org.apache.brooklyn.core.test.entity.TestEntity;
-import org.apache.brooklyn.core.test.entity.TestEntityImpl;
-import org.apache.brooklyn.entity.java.JmxSupport;
-import org.apache.brooklyn.entity.java.UsesJmx;
-import org.apache.brooklyn.entity.java.UsesJmx.JmxAgentModes;
-import 
org.apache.brooklyn.entity.software.base.test.jmx.GeneralisedDynamicMBean;
-import org.apache.brooklyn.entity.software.base.test.jmx.JmxService;
-import org.apache.brooklyn.sensor.feed.ConfigToAttributes;
-import org.apache.brooklyn.sensor.feed.jmx.JmxAttributePollConfig;
-import org.apache.brooklyn.sensor.feed.jmx.JmxFeed;
-import org.apache.brooklyn.sensor.feed.jmx.JmxHelper;
-import org.apache.brooklyn.sensor.feed.jmx.JmxNotificationFilters;
-import org.apache.brooklyn.sensor.feed.jmx.JmxNotificationSubscriptionConfig;
-import org.apache.brooklyn.sensor.feed.jmx.JmxOperationPollConfig;
-import org.apache.brooklyn.sensor.feed.jmx.JmxValueFunctions;
-import org.apache.brooklyn.test.Asserts;
-import org.apache.brooklyn.test.TestUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-import org.testng.collections.Lists;
-import 
org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
-
-import com.google.common.base.Function;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-
-/**
- * Test the operation of the {@link JmxFeed} class.
- * <p>
- * Also confirm some of the JMX setup done by {@link JmxSupport} and {@link 
JmxHelper},
- * based on ports in {@link UsesJmx}.
- * <p>
- * TODO tests of other JMX_AGENT_MODE are done in ActiveMqIntegrationTest; 
- * would be nice to promote some to live here
- */
-public class JmxFeedTest {
-    
-    // FIXME Move out the JmxHelper tests into the JmxHelperTest class
-    
-    // FIXME Also test that setting poll period takes effect
-    
-    private static final Logger log = 
LoggerFactory.getLogger(JmxFeedTest.class);
-
-    private static final int TIMEOUT_MS = 5000;
-    private static final int SHORT_WAIT_MS = 250;
-    
-    private JmxService jmxService;
-    private TestApplication app;
-    private TestEntity entity;
-    private JmxFeed feed;
-    private JmxHelper jmxHelper;
-    
-    private AttributeSensor<Integer> intAttribute = 
Sensors.newIntegerSensor("brooklyn.test.intAttribute", "Brooklyn testing int 
attribute");
-    private AttributeSensor<String> stringAttribute = 
Sensors.newStringSensor("brooklyn.test.stringAttribute", "Brooklyn testing 
string attribute");
-    private BasicAttributeSensor<Map> mapAttribute = new 
BasicAttributeSensor<Map>(Map.class, "brooklyn.test.mapAttribute", "Brooklyn 
testing map attribute");
-    private String objectName = "Brooklyn:type=MyTestMBean,name=myname";
-    private ObjectName jmxObjectName;
-    private String attributeName = "myattrib";
-    private String opName = "myop";
-    
-    public static class TestEntityWithJmx extends TestEntityImpl {
-        @Override public void init() {
-            setAttribute(Attributes.HOSTNAME, "localhost");
-            setAttribute(UsesJmx.JMX_PORT, 
-                    
LocalhostMachineProvisioningLocation.obtainPort(PortRanges.fromString("40123+")));
-            // only supports no-agent, at the moment
-            setConfig(UsesJmx.JMX_AGENT_MODE, JmxAgentModes.NONE);
-            setAttribute(UsesJmx.RMI_REGISTRY_PORT, -1);  // -1 means to use 
the JMX_PORT only
-            ConfigToAttributes.apply(this, UsesJmx.JMX_CONTEXT);
-        }
-    }
-    
-    @BeforeMethod(alwaysRun=true)
-    public void setUp() throws Exception {
-        jmxObjectName = new ObjectName(objectName);
-        
-        // Create an entity and configure it with the above JMX service
-        app = TestApplication.Factory.newManagedInstanceForTests();
-        entity = 
app.createAndManageChild(EntitySpec.create(TestEntity.class).impl(TestEntityWithJmx.class));
-        app.start(ImmutableList.of(new SimulatedLocation()));
-
-        jmxHelper = new JmxHelper(entity);
-        
-        jmxService = new JmxService(entity);
-    }
-    
-    @AfterMethod(alwaysRun=true)
-    public void tearDown() throws Exception {
-        if (feed != null) feed.stop();
-        if (jmxHelper != null) jmxHelper.disconnect();
-        if (jmxService != null) jmxService.shutdown();
-        if (app != null) Entities.destroyAll(app.getManagementContext());
-        feed = null;
-    }
-
-    @Test
-    public void testJmxAttributePollerReturnsMBeanAttribute() throws Exception 
{
-        GeneralisedDynamicMBean mbean = 
jmxService.registerMBean(ImmutableMap.of(attributeName, 42), objectName);
-
-        feed = JmxFeed.builder()
-                .entity(entity)
-                .pollAttribute(new 
JmxAttributePollConfig<Integer>(intAttribute)
-                        .objectName(objectName)
-                        .period(50)
-                        .attributeName(attributeName))
-                .build();
-        
-        // Starts with value defined when registering...
-        assertSensorEventually(intAttribute, 42, TIMEOUT_MS);
-
-        // Change the value and check it updates
-        mbean.updateAttributeValue(attributeName, 64);
-        assertSensorEventually(intAttribute, 64, TIMEOUT_MS);
-    }
-
-    @Test
-    public void testJmxAttributeOfTypeTabularDataProviderConvertedToMap() 
throws Exception {
-        // Create the CompositeType and TabularData
-        CompositeType compositeType = new CompositeType(
-                "typeName",
-                "description",
-                new String[] {"myint", "mystring", "mybool"},    // item names
-                new String[] {"myint", "mystring", "mybool"},    // item 
descriptions, can't be null or empty string
-                new OpenType<?>[] {SimpleType.INTEGER, SimpleType.STRING, 
SimpleType.BOOLEAN}
-        );
-        TabularType tt = new TabularType(
-                "typeName",
-                "description",
-                compositeType,
-                new String[] {"myint"}
-        );
-        TabularDataSupport tds = new TabularDataSupport(tt);
-        tds.put(new CompositeDataSupport(
-                compositeType,
-                new String[] {"mybool", "myint", "mystring"},
-                new Object[] {true, 1234, "on"}
-        ));
-
-        // Create MBean
-        GeneralisedDynamicMBean mbean = 
jmxService.registerMBean(ImmutableMap.of(attributeName, tds), objectName);
-
-        feed = JmxFeed.builder()
-                .entity(entity)
-                .pollAttribute(new JmxAttributePollConfig<Map>(mapAttribute)
-                        .objectName(objectName)
-                        .attributeName(attributeName)
-                        
.onSuccess((Function)JmxValueFunctions.tabularDataToMap()))
-                .build();
-
-        // Starts with value defined when registering...
-        assertSensorEventually(
-                mapAttribute, 
-                ImmutableMap.of("myint", 1234, "mystring", "on", "mybool", 
Boolean.TRUE), 
-                TIMEOUT_MS);
-    }
-
-    @Test
-    public void testJmxOperationPolledForSensor() throws Exception {
-        // This is awful syntax...
-        final int opReturnVal = 123;
-        final AtomicInteger invocationCount = new AtomicInteger();
-        MBeanOperationInfo opInfo = new MBeanOperationInfo(opName, "my descr", 
new MBeanParameterInfo[0], Integer.class.getName(), MBeanOperationInfo.ACTION);
-        GeneralisedDynamicMBean mbean = jmxService.registerMBean(
-                Collections.emptyMap(), 
-                ImmutableMap.of(opInfo, new Function<Object[], Integer>() {
-                        public Integer apply(Object[] args) {
-                            invocationCount.incrementAndGet(); return 
opReturnVal;
-                        }}),
-                objectName);
-
-        feed = JmxFeed.builder()
-                .entity(entity)
-                .pollOperation(new 
JmxOperationPollConfig<Integer>(intAttribute)
-                        .objectName(objectName)
-                        .operationName(opName))
-                .build();
-        
-        TestUtils.executeUntilSucceeds(ImmutableMap.of("timeout", TIMEOUT_MS), 
new Runnable() {
-            public void run() {
-                assertTrue(invocationCount.get() > 0, 
"invocationCount="+invocationCount);
-                assertEquals(entity.getAttribute(intAttribute), 
(Integer)opReturnVal);
-            }});
-    }
-
-    @Test
-    public void testJmxOperationWithArgPolledForSensor() throws Exception {
-        // This is awful syntax...
-        MBeanParameterInfo paramInfo = new MBeanParameterInfo("param1", 
String.class.getName(), "my param1");
-        MBeanParameterInfo[] paramInfos = new MBeanParameterInfo[] {paramInfo};
-        MBeanOperationInfo opInfo = new MBeanOperationInfo(opName, "my descr", 
paramInfos, String.class.getName(), MBeanOperationInfo.ACTION);
-        GeneralisedDynamicMBean mbean = jmxService.registerMBean(
-                Collections.emptyMap(), 
-                ImmutableMap.of(opInfo, new Function<Object[], String>() {
-                        public String apply(Object[] args) {
-                            return args[0]+"suffix";
-                        }}),
-                objectName);
-        
-        feed = JmxFeed.builder()
-                .entity(entity)
-                .pollOperation(new 
JmxOperationPollConfig<String>(stringAttribute)
-                        .objectName(objectName)
-                        .operationName(opName)
-                        .operationParams(ImmutableList.of("myprefix")))
-                .build();
-        
-        assertSensorEventually(stringAttribute, "myprefix"+"suffix", 
TIMEOUT_MS);
-    }
-
-    @Test
-    public void testJmxNotificationSubscriptionForSensor() throws Exception {
-        final String one = "notification.one", two = "notification.two";
-        final StandardEmitterMBean mbean = 
jmxService.registerMBean(ImmutableList.of(one, two), objectName);
-        final AtomicInteger sequence = new AtomicInteger(0);
-
-        feed = JmxFeed.builder()
-                .entity(entity)
-                .subscribeToNotification(new 
JmxNotificationSubscriptionConfig<Integer>(intAttribute)
-                        .objectName(objectName)
-                        
.notificationFilter(JmxNotificationFilters.matchesType(one)))
-                .build();        
-
-        // Notification updates the sensor
-        // Note that subscription is done async, so can't just send 
notification immediately during test.
-        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), new 
Runnable() {
-            public void run() {
-                sendNotification(mbean, one, sequence.getAndIncrement(), 123);
-                assertEquals(entity.getAttribute(intAttribute), (Integer)123);
-            }});
-        
-        // But other notification types are ignored
-        sendNotification(mbean, two, sequence.getAndIncrement(), -1);
-            
-        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), new 
Runnable() {
-            public void run() {
-                assertEquals(entity.getAttribute(intAttribute), (Integer)123);
-            }});
-    }
-    
-    @Test
-    public void testJmxNotificationSubscriptionForSensorParsingNotification() 
throws Exception {
-        final String one = "notification.one", two = "notification.two";
-        final StandardEmitterMBean mbean = 
jmxService.registerMBean(ImmutableList.of(one, two), objectName);
-        final AtomicInteger sequence = new AtomicInteger(0);
-        
-        feed = JmxFeed.builder()
-                .entity(entity)
-                .subscribeToNotification(new 
JmxNotificationSubscriptionConfig<Integer>(intAttribute)
-                        .objectName(objectName)
-                        
.notificationFilter(JmxNotificationFilters.matchesType(one))
-                        .onNotification(new Function<Notification, Integer>() {
-                            public Integer apply(Notification notif) {
-                                return (Integer) notif.getUserData();
-                            }
-                        }))
-                .build();
-        
-        
-        // Notification updates the sensor
-        // Note that subscription is done async, so can't just send 
notification immediately during test.
-        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), new 
Runnable() {
-            public void run() {
-                sendNotification(mbean, one, sequence.getAndIncrement(), 123);
-                assertEquals(entity.getAttribute(intAttribute), (Integer)123);
-            }});
-    }
-
-    @Test
-    public void testJmxNotificationMultipleSubscriptionUsingListener() throws 
Exception {
-        final String one = "notification.one";
-        final String two = "notification.two";
-        final StandardEmitterMBean mbean = 
jmxService.registerMBean(ImmutableList.of(one, two), objectName);
-        final AtomicInteger sequence = new AtomicInteger(0);
-
-        feed = JmxFeed.builder()
-                .entity(entity)
-                .subscribeToNotification(new 
JmxNotificationSubscriptionConfig<Integer>(intAttribute)
-                        .objectName(objectName)
-                        
.notificationFilter(JmxNotificationFilters.matchesTypes(one, two)))
-                .build();
-        
-        // Notification updates the sensor
-        // Note that subscription is done async, so can't just send 
notification immediately during test.
-        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), new 
Runnable() {
-            public void run() {
-                sendNotification(mbean, one, sequence.getAndIncrement(), 123);
-                assertEquals(entity.getAttribute(intAttribute), (Integer)123);
-            }});
-
-        // And wildcard means other notifications also received
-        sendNotification(mbean, two, sequence.getAndIncrement(), 456);
-        assertSensorEventually(intAttribute, 456, TIMEOUT_MS);
-    }
-
-    // Test reproduces functionality used in Monterey, for Venue entity being 
told of requestActor
-    @Test
-    public void 
testSubscribeToJmxNotificationAndEmitCorrespondingNotificationSensor() throws 
Exception {
-        TestApplication app2 = new TestApplicationImpl();
-        final EntityWithEmitter entity = new EntityWithEmitter(app2);
-        Entities.startManagement(app2);
-        try {
-            app2.start(ImmutableList.of(new SimulatedLocation()));
-            
-            final List<SensorEvent<String>> received = Lists.newArrayList();
-            app2.subscribe(null, EntityWithEmitter.MY_NOTIF, new 
SensorEventListener<String>() {
-                public void onEvent(SensorEvent<String> event) {
-                    received.add(event);
-                }});
-    
-            final StandardEmitterMBean mbean = 
jmxService.registerMBean(ImmutableList.of("one"), objectName);
-            final AtomicInteger sequence = new AtomicInteger(0);
-            
-            jmxHelper.connect(TIMEOUT_MS);
-            jmxHelper.addNotificationListener(jmxObjectName, new 
NotificationListener() {
-                    public void handleNotification(Notification notif, Object 
callback) {
-                        if (notif.getType().equals("one")) {
-                            entity.emit(EntityWithEmitter.MY_NOTIF, (String) 
notif.getUserData());
-                        }
-                    }});
-            
-
-            Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), 
new Runnable() {
-                public void run() {
-                    sendNotification(mbean, "one", sequence.getAndIncrement(), 
"abc");
-                    assertTrue(received.size() > 0, "received size should be 
bigger than 0");
-                    assertEquals(received.get(0).getValue(), "abc");
-                }});
-        } finally {
-            Entities.destroyAll(app2.getManagementContext());
-        }
-    }
-    
-    public static class EntityWithEmitter extends AbstractEntity {
-        public static final BasicNotificationSensor<String> MY_NOTIF = new 
BasicNotificationSensor<String>(String.class, "test.myNotif", "My notif");
-        
-        public EntityWithEmitter(Entity owner) {
-            super(owner);
-        }
-        public EntityWithEmitter(Map flags) {
-            super(flags);
-        }
-        public EntityWithEmitter(Map flags, Entity owner) {
-            super(flags, owner);
-        }
-    }
-    
-    private Notification sendNotification(StandardEmitterMBean mbean, String 
type, long seq, Object userData) {
-        Notification notif = new Notification(type, mbean, seq);
-        notif.setUserData(userData);
-        mbean.sendNotification(notif);
-        return notif;
-    }
-    
-    private <T> void assertSensorEventually(final AttributeSensor<T> sensor, 
final T expectedVal, long timeout) {
-        executeUntilSucceeds(ImmutableMap.of("timeout", timeout), new 
Callable<Void>() {
-            public Void call() {
-                assertEquals(entity.getAttribute(sensor), expectedVal);
-                return null;
-            }});
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/daf40919/software/base/src/test/java/org/apache/brooklyn/sensor/feed/jmx/JmxHelperTest.java
----------------------------------------------------------------------
diff --git 
a/software/base/src/test/java/org/apache/brooklyn/sensor/feed/jmx/JmxHelperTest.java
 
b/software/base/src/test/java/org/apache/brooklyn/sensor/feed/jmx/JmxHelperTest.java
deleted file mode 100644
index 058947c..0000000
--- 
a/software/base/src/test/java/org/apache/brooklyn/sensor/feed/jmx/JmxHelperTest.java
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * 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.brooklyn.sensor.feed.jmx;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.fail;
-
-import java.io.IOException;
-import java.util.List;
-
-import javax.management.DynamicMBean;
-import javax.management.MBeanOperationInfo;
-import javax.management.MBeanParameterInfo;
-import javax.management.Notification;
-import javax.management.NotificationListener;
-import javax.management.ObjectName;
-import javax.management.StandardEmitterMBean;
-
-import 
org.apache.brooklyn.entity.software.base.test.jmx.GeneralisedDynamicMBean;
-import org.apache.brooklyn.entity.software.base.test.jmx.JmxService;
-import org.apache.brooklyn.sensor.feed.jmx.JmxHelper;
-import org.apache.brooklyn.test.TestUtils;
-import org.apache.brooklyn.util.collections.MutableMap;
-import org.apache.brooklyn.util.exceptions.Exceptions;
-import org.jclouds.util.Throwables2;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-import org.testng.collections.Lists;
-
-import com.google.common.base.Function;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-
-public class JmxHelperTest {
-
-    private static final Logger log = 
LoggerFactory.getLogger(JmxHelperTest.class);
-    
-    private static final String LOCALHOST_NAME = "localhost";
-    
-    private static final int TIMEOUT_MS = 5000;
-    private static final int SHORT_WAIT_MS = 250;
-
-    private JmxService jmxService;
-    private JmxHelper jmxHelper;
-    
-    private String objectName = "Brooklyn:type=MyTestMBean,name=myname";
-    private String objectNameWithWildcard = 
"Brooklyn:type=MyTestMBean,name=mynam*";
-    private ObjectName jmxObjectName;
-    private ObjectName jmxObjectNameWithWildcard;
-    private String attributeName = "myattrib";
-    private String opName = "myop";
-    
-    @BeforeMethod(alwaysRun=true)
-    public void setUp() throws Exception {
-        jmxObjectName = new ObjectName(objectName);
-        jmxObjectNameWithWildcard = new ObjectName(objectNameWithWildcard);
-        jmxService = newJmxServiceRetrying(LOCALHOST_NAME, 5);
-        jmxHelper = new JmxHelper(jmxService.getUrl());
-        jmxHelper.setMinTimeBetweenReconnectAttempts(0);
-        jmxHelper.connect(TIMEOUT_MS);
-    }
-    
-    @AfterMethod(alwaysRun=true)
-    public void tearDown() throws Exception {
-        if (jmxHelper != null) jmxHelper.disconnect();
-        if (jmxService != null) jmxService.shutdown();
-        jmxHelper = null;
-        jmxService = null;
-    }
-
-    @Test
-    public void testGetAttribute() throws Exception {
-        GeneralisedDynamicMBean mbean = 
jmxService.registerMBean(MutableMap.of("myattr", "myval"), objectName);
-        assertEquals(jmxHelper.getAttribute(jmxObjectName, "myattr"), "myval");
-    }
-
-    @Test
-    public void testGetAttributeUsingObjectNameWildcard() throws Exception {
-        GeneralisedDynamicMBean mbean = 
jmxService.registerMBean(MutableMap.of("myattr", "myval"), objectName);
-        assertEquals(jmxHelper.getAttribute(jmxObjectNameWithWildcard, 
"myattr"), "myval");
-    }
-
-    @Test
-    public void testSetAttribute() throws Exception {
-        DynamicMBean mbean = jmxService.registerMBean(MutableMap.of("myattr", 
"myval"), objectName);
-
-        jmxHelper.setAttribute(jmxObjectName, "myattr", "abc");
-        Object actual = jmxHelper.getAttribute(jmxObjectName, "myattr");
-        assertEquals(actual, "abc");
-    }
-
-    @Test
-    public void testSetAttributeUsingObjectNameWildcard() throws Exception {
-        DynamicMBean mbean = jmxService.registerMBean(MutableMap.of("myattr", 
"myval"), objectName);
-
-        jmxHelper.setAttribute(jmxObjectNameWithWildcard, "myattr", "abc");
-        Object actual = jmxHelper.getAttribute(jmxObjectName, "myattr");
-        assertEquals(actual, "abc");
-    }
-
-    @Test
-    public void testInvokeOperationWithNoArgs() throws Exception {
-        final String opReturnVal = "my result";
-        MBeanOperationInfo opInfo = new MBeanOperationInfo(opName, "my descr", 
new MBeanParameterInfo[0], String.class.getName(), MBeanOperationInfo.ACTION);
-        Function<Object[], String> opImpl = new Function<Object[], String>() {
-            @Override public String apply(Object[] args) {
-                assertEquals(args.length, 0, "args="+args);
-                return opReturnVal;
-            }
-        };
-        GeneralisedDynamicMBean mbean = 
jmxService.registerMBean(ImmutableMap.of(), ImmutableMap.of(opInfo, opImpl), 
objectName);
-        
-        assertEquals(jmxHelper.operation(objectName, opName), opReturnVal);
-    }
-
-    @Test
-    public void testInvokeOperationUsingObjectNameWildcard() throws Exception {
-        final String opReturnVal = "my result";
-        MBeanOperationInfo opInfo = new MBeanOperationInfo(opName, "my descr", 
new MBeanParameterInfo[0], String.class.getName(), MBeanOperationInfo.ACTION);
-        Function<Object[], String> opImpl = new Function<Object[], String>() {
-            @Override public String apply(Object[] args) {
-                assertEquals(args.length, 0, "args="+args);
-                return opReturnVal;
-            }
-        };
-        GeneralisedDynamicMBean mbean = 
jmxService.registerMBean(ImmutableMap.of(), ImmutableMap.of(opInfo, opImpl), 
objectName);
-        
-        assertEquals(jmxHelper.operation(objectNameWithWildcard, opName), 
opReturnVal);
-    }
-
-    @Test
-    public void testInvokeOperationWithArgs() throws Exception {
-        final String opReturnPrefix = "my result prefix/";
-        String opParam1 = "my param 1";
-        MBeanOperationInfo opInfo = new MBeanOperationInfo(
-                opName, 
-                "my descr", 
-                new MBeanParameterInfo[] {new MBeanParameterInfo("myParam1", 
String.class.getName(), "my param1 descr")}, 
-                String.class.getName(), 
-                MBeanOperationInfo.ACTION);
-        Function<Object[],String> opImpl = new Function<Object[],String>() {
-            public String apply(Object[] input) {
-                return opReturnPrefix+input[0];
-            }
-        };
-        GeneralisedDynamicMBean mbean = 
jmxService.registerMBean(ImmutableMap.of(), ImmutableMap.of(opInfo, opImpl), 
objectName);
-        
-        assertEquals(jmxHelper.operation(objectName, opName, opParam1), 
opReturnPrefix+opParam1);
-    }
-
-    @Test
-    public void testReconnectsOnJmxServerTemporaryFailure() throws Exception {
-        int port = jmxService.getJmxPort();
-        GeneralisedDynamicMBean mbean = 
jmxService.registerMBean(MutableMap.of("myattr", "myval"), objectName);
-        assertEquals(jmxHelper.getAttribute(jmxObjectName, "myattr"), "myval");
-        
-        // Simulate temporary network-failure
-        jmxService.shutdown();
-
-        // Ensure that we have a failed query while the "network is down"      
   
-        try {
-            jmxHelper.getAttribute(jmxObjectName, attributeName);
-            fail();
-        } catch (Exception e) {
-            if (Throwables2.getFirstThrowableOfType(e, IOException.class) == 
null) {
-                throw e;
-            }
-        }
-
-        // Simulate the network restarting
-        jmxService = new JmxService(LOCALHOST_NAME, port);
-        
-        GeneralisedDynamicMBean mbean2 = 
jmxService.registerMBean(MutableMap.of("myattr", "myval2"), objectName);
-        assertEquals(jmxHelper.getAttribute(jmxObjectName, "myattr"), 
"myval2");
-    }
-    
-    @Test(expectedExceptions = {IllegalStateException.class})
-    public void testJmxCheckInstanceExistsEventuallyThrowsIfNotFound() throws 
Exception {
-        jmxHelper.assertMBeanExistsEventually(new 
ObjectName("Brooklyn:type=DoesNotExist,name=doesNotExist"), 1L);
-    }
-
-    @Test
-    public void testJmxObjectCheckExistsEventuallyReturnsIfFoundImmediately() 
throws Exception {
-        GeneralisedDynamicMBean mbean = jmxService.registerMBean(objectName);
-        jmxHelper.assertMBeanExistsEventually(jmxObjectName, 1L);
-    }
-
-    @Test
-    public void 
testJmxObjectCheckExistsEventuallyTakingLongReturnsIfFoundImmediately() throws 
Exception {
-        GeneralisedDynamicMBean mbean = jmxService.registerMBean(objectName);
-        jmxHelper.assertMBeanExistsEventually(jmxObjectName, 1L);
-    }
-
-    @Test
-    public void 
testJmxObjectCheckExistsEventuallyReturnsIfCreatedDuringPolling() throws 
Exception {
-        Thread t = new Thread(new Runnable() {
-                public void run() {
-                    try {
-                        Thread.sleep(SHORT_WAIT_MS);
-                        GeneralisedDynamicMBean mbean = 
jmxService.registerMBean(objectName);
-                    } catch (InterruptedException e) {
-                        return; // graceful return
-                    } catch (Exception e) {
-                        throw Exceptions.propagate(e);
-                    }
-                }});
-        try {
-            t.start();
-            
-            jmxHelper.assertMBeanExistsEventually(jmxObjectName, TIMEOUT_MS);
-        } finally {
-            t.interrupt();
-            t.join(TIMEOUT_MS);
-            assertFalse(t.isAlive());
-        }        
-    }
-
-    @Test
-    public void testSubscribeToJmxNotificationsDirectlyWithJmxHelper() throws 
Exception {
-        StandardEmitterMBean mbean = 
jmxService.registerMBean(ImmutableList.of("one"), objectName);
-        int sequence = 0;
-        final List<Notification> received = Lists.newArrayList();
-
-        jmxHelper.addNotificationListener(jmxObjectName, new 
NotificationListener() {
-            public void handleNotification(Notification notif, Object 
callback) {
-                received.add(notif);
-            }});
-                    
-
-        final Notification notif = sendNotification(mbean, "one", sequence++, 
"abc");
-
-        TestUtils.executeUntilSucceeds(ImmutableMap.of("timeout", TIMEOUT_MS), 
new Runnable() {
-            public void run() {
-                assertEquals(received.size(), 1);
-                assertNotificationsEqual(received.get(0), notif);
-            }});
-    }
-
-    // Visual-inspection test that LOG.warn happens only once; TODO setup a 
listener to the logging output
-    @Test
-    public void testMBeanNotFoundLoggedOnlyOncePerUrl() throws Exception {
-        ObjectName wrongObjectName = new 
ObjectName("DoesNotExist:type=DoesNotExist");
-
-        // Expect just one log message about:
-        //     JMX object DoesNotExist:type=DoesNotExist not found at 
service:jmx:rmi://localhost:1099/jndi/rmi://localhost:9001/jmxrmi"
-        for (int i = 0; i < 10; i++) {
-            jmxHelper.findMBean(wrongObjectName);
-        }
-
-        jmxService.shutdown();
-        jmxHelper.disconnect();
-        
-        jmxService = newJmxServiceRetrying(LOCALHOST_NAME, 5);
-        jmxHelper = new JmxHelper(jmxService.getUrl());
-        jmxHelper.connect();
-        
-        // Expect just one log message about:
-        //     JMX object DoesNotExist:type=DoesNotExist not found at 
service:jmx:rmi://localhost:1099/jndi/rmi://localhost:9001/jmxrmi"
-        for (int i = 0; i < 10; i++) {
-            jmxHelper.findMBean(wrongObjectName);
-        }
-    }
-
-    private JmxService newJmxServiceRetrying(String host, int retries) throws 
Exception {
-        Exception lastexception = null;
-        for (int i = 0; i < retries; i++) {
-            try {
-                return new JmxService(host, (int)(11000+(500*Math.random())));
-            } catch (Exception e) {
-                log.debug("Unable to create JMX service during test - 
"+retries+" retries remaining");
-                lastexception = e;
-            }
-        }
-        throw lastexception;
-    }
-
-    private Notification sendNotification(StandardEmitterMBean mbean, String 
type, long seq, Object userData) {
-        Notification notif = new Notification(type, mbean, seq);
-        notif.setUserData(userData);
-        mbean.sendNotification(notif);
-        return notif;
-    }
-    
-    private void assertNotificationsEqual(Notification n1, Notification n2) {
-        assertEquals(n1.getType(), n2.getType());
-        assertEquals(n1.getSequenceNumber(), n2.getSequenceNumber());
-        assertEquals(n1.getUserData(), n2.getUserData());
-        assertEquals(n1.getTimeStamp(), n2.getTimeStamp());
-        assertEquals(n1.getMessage(), n2.getMessage());
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/daf40919/software/base/src/test/java/org/apache/brooklyn/sensor/feed/jmx/RebindJmxFeedTest.java
----------------------------------------------------------------------
diff --git 
a/software/base/src/test/java/org/apache/brooklyn/sensor/feed/jmx/RebindJmxFeedTest.java
 
b/software/base/src/test/java/org/apache/brooklyn/sensor/feed/jmx/RebindJmxFeedTest.java
deleted file mode 100644
index 9ed0031..0000000
--- 
a/software/base/src/test/java/org/apache/brooklyn/sensor/feed/jmx/RebindJmxFeedTest.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * 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.brooklyn.sensor.feed.jmx;
-
-import static org.testng.Assert.assertEquals;
-
-import java.util.Collection;
-
-import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.sensor.AttributeSensor;
-import org.apache.brooklyn.api.sensor.Feed;
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.core.entity.Attributes;
-import org.apache.brooklyn.core.location.PortRanges;
-import org.apache.brooklyn.core.mgmt.rebind.RebindTestFixtureWithApp;
-import org.apache.brooklyn.core.sensor.Sensors;
-import org.apache.brooklyn.core.test.entity.TestEntity;
-import org.apache.brooklyn.core.test.entity.TestEntityImpl;
-import org.apache.brooklyn.entity.java.UsesJmx;
-import org.apache.brooklyn.entity.java.UsesJmx.JmxAgentModes;
-import 
org.apache.brooklyn.entity.software.base.test.jmx.GeneralisedDynamicMBean;
-import org.apache.brooklyn.entity.software.base.test.jmx.JmxService;
-import org.apache.brooklyn.sensor.feed.ConfigToAttributes;
-import org.apache.brooklyn.sensor.feed.jmx.JmxAttributePollConfig;
-import org.apache.brooklyn.sensor.feed.jmx.JmxFeed;
-import org.apache.brooklyn.sensor.feed.jmx.JmxHelper;
-import org.apache.brooklyn.test.EntityTestUtils;
-import org.apache.brooklyn.util.collections.MutableMap;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-import 
org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-
-public class RebindJmxFeedTest extends RebindTestFixtureWithApp {
-
-    private static final Logger log = 
LoggerFactory.getLogger(RebindJmxFeedTest.class);
-
-    private static final String LOCALHOST_NAME = "localhost";
-
-    static final AttributeSensor<String> SENSOR_STRING = 
Sensors.newStringSensor("aString", "");
-    static final AttributeSensor<Integer> SENSOR_INT = 
Sensors.newIntegerSensor( "aLong", "");
-
-    static final String JMX_ATTRIBUTE_NAME = "myattr";
-    static final String OBJECT_NAME = "Brooklyn:type=MyTestMBean,name=myname";
-    
-    private JmxService jmxService;
-    
-    @BeforeMethod(alwaysRun=true)
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        
-        // Create an entity and configure it with the above JMX service
-        //jmxService = newJmxServiceRetrying(LOCALHOST_NAME, 5);
-    }
-    
-    @AfterMethod(alwaysRun=true)
-    @Override
-    public void tearDown() throws Exception {
-        if (jmxService != null) jmxService.shutdown();
-        super.tearDown();
-    }
-
-    @Test
-    public void testJmxFeedIsPersisted() throws Exception {
-        runJmxFeedIsPersisted(false);
-    }
-
-    @Test
-    public void testJmxFeedIsPersistedWithPreCreatedJmxHelper() throws 
Exception {
-        runJmxFeedIsPersisted(true);
-    }
-
-    protected void runJmxFeedIsPersisted(boolean preCreateJmxHelper) throws 
Exception {
-        TestEntity origEntity = 
origApp.createAndManageChild(EntitySpec.create(TestEntity.class).impl(MyEntityWithJmxFeedImpl.class)
-                .configure(MyEntityWithJmxFeedImpl.PRE_CREATE_JMX_HELPER, 
preCreateJmxHelper));
-        origApp.start(ImmutableList.<Location>of());
-        
-        jmxService = new JmxService(origEntity);
-        GeneralisedDynamicMBean mbean = 
jmxService.registerMBean(MutableMap.of(JMX_ATTRIBUTE_NAME, "myval"), 
OBJECT_NAME);
-        
-        EntityTestUtils.assertAttributeEqualsEventually(origEntity, 
SENSOR_STRING, "myval");
-        assertEquals(origEntity.feeds().getFeeds().size(), 1);
-
-        newApp = rebind();
-        TestEntity newEntity = (TestEntity) 
Iterables.getOnlyElement(newApp.getChildren());
-        
-        Collection<Feed> newFeeds = newEntity.feeds().getFeeds();
-        assertEquals(newFeeds.size(), 1);
-        
-        // Expect the feed to still be polling
-        newEntity.setAttribute(SENSOR_STRING, null);
-        EntityTestUtils.assertAttributeEqualsEventually(newEntity, 
SENSOR_STRING, "myval");
-    }
-
-    public static class MyEntityWithJmxFeedImpl extends TestEntityImpl {
-        public static final ConfigKey<Boolean> PRE_CREATE_JMX_HELPER = 
ConfigKeys.newBooleanConfigKey("test.rebindjmx.preCreateJmxHelper", "", false);
-        
-        @Override
-        public void start(Collection<? extends Location> locs) {
-            // TODO Auto-generated method stub
-            super.start(locs);
-            
-            setAttribute(Attributes.HOSTNAME, "localhost");
-            setAttribute(UsesJmx.JMX_PORT, 
-                    
LocalhostMachineProvisioningLocation.obtainPort(PortRanges.fromString("40123+")));
-            // only supports no-agent, at the moment
-            setConfig(UsesJmx.JMX_AGENT_MODE, JmxAgentModes.NONE);
-            setAttribute(UsesJmx.RMI_REGISTRY_PORT, -1);  // -1 means to use 
the JMX_PORT only
-            ConfigToAttributes.apply(this, UsesJmx.JMX_CONTEXT);
-            
-            JmxFeed.Builder feedBuilder = JmxFeed.builder()
-                    .entity(this)
-                    .pollAttribute(new 
JmxAttributePollConfig<String>(SENSOR_STRING)
-                            .objectName(OBJECT_NAME)
-                            .period(50)
-                            .attributeName(JMX_ATTRIBUTE_NAME));
-            if (getConfig(PRE_CREATE_JMX_HELPER)) {
-                JmxHelper jmxHelper = new JmxHelper(this);
-                feedBuilder.helper(jmxHelper);
-            }
-            addFeed(feedBuilder.build());
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/daf40919/software/database/src/main/java/org/apache/brooklyn/entity/database/crate/CrateNodeImpl.java
----------------------------------------------------------------------
diff --git 
a/software/database/src/main/java/org/apache/brooklyn/entity/database/crate/CrateNodeImpl.java
 
b/software/database/src/main/java/org/apache/brooklyn/entity/database/crate/CrateNodeImpl.java
index 8b544c4..f78ddba 100644
--- 
a/software/database/src/main/java/org/apache/brooklyn/entity/database/crate/CrateNodeImpl.java
+++ 
b/software/database/src/main/java/org/apache/brooklyn/entity/database/crate/CrateNodeImpl.java
@@ -22,11 +22,11 @@ import org.apache.brooklyn.core.config.render.RendererHints;
 import org.apache.brooklyn.core.entity.Attributes;
 import org.apache.brooklyn.entity.java.JavaAppUtils;
 import org.apache.brooklyn.entity.software.base.SoftwareProcessImpl;
+import org.apache.brooklyn.feed.http.HttpFeed;
+import org.apache.brooklyn.feed.http.HttpPollConfig;
+import org.apache.brooklyn.feed.http.HttpValueFunctions;
+import org.apache.brooklyn.feed.jmx.JmxFeed;
 import org.apache.brooklyn.sensor.enricher.Enrichers;
-import org.apache.brooklyn.sensor.feed.http.HttpFeed;
-import org.apache.brooklyn.sensor.feed.http.HttpPollConfig;
-import org.apache.brooklyn.sensor.feed.http.HttpValueFunctions;
-import org.apache.brooklyn.sensor.feed.jmx.JmxFeed;
 import org.apache.brooklyn.util.guava.Functionals;
 
 public class CrateNodeImpl extends SoftwareProcessImpl implements CrateNode{

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/daf40919/software/database/src/main/java/org/apache/brooklyn/entity/database/mariadb/MariaDbNodeImpl.java
----------------------------------------------------------------------
diff --git 
a/software/database/src/main/java/org/apache/brooklyn/entity/database/mariadb/MariaDbNodeImpl.java
 
b/software/database/src/main/java/org/apache/brooklyn/entity/database/mariadb/MariaDbNodeImpl.java
index 3d8c982..c23c616 100644
--- 
a/software/database/src/main/java/org/apache/brooklyn/entity/database/mariadb/MariaDbNodeImpl.java
+++ 
b/software/database/src/main/java/org/apache/brooklyn/entity/database/mariadb/MariaDbNodeImpl.java
@@ -23,10 +23,10 @@ import org.slf4j.LoggerFactory;
 import org.apache.brooklyn.core.effector.EffectorBody;
 import org.apache.brooklyn.core.location.Locations;
 import org.apache.brooklyn.entity.software.base.SoftwareProcessImpl;
+import org.apache.brooklyn.feed.ssh.SshFeed;
+import org.apache.brooklyn.feed.ssh.SshPollConfig;
+import org.apache.brooklyn.feed.ssh.SshPollValue;
 import org.apache.brooklyn.location.ssh.SshMachineLocation;
-import org.apache.brooklyn.sensor.feed.ssh.SshFeed;
-import org.apache.brooklyn.sensor.feed.ssh.SshPollConfig;
-import org.apache.brooklyn.sensor.feed.ssh.SshPollValue;
 import org.apache.brooklyn.util.core.config.ConfigBag;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.text.Identifiers;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/daf40919/software/database/src/main/java/org/apache/brooklyn/entity/database/mysql/MySqlClusterImpl.java
----------------------------------------------------------------------
diff --git 
a/software/database/src/main/java/org/apache/brooklyn/entity/database/mysql/MySqlClusterImpl.java
 
b/software/database/src/main/java/org/apache/brooklyn/entity/database/mysql/MySqlClusterImpl.java
index e106728..d6527ca 100644
--- 
a/software/database/src/main/java/org/apache/brooklyn/entity/database/mysql/MySqlClusterImpl.java
+++ 
b/software/database/src/main/java/org/apache/brooklyn/entity/database/mysql/MySqlClusterImpl.java
@@ -39,9 +39,9 @@ import 
org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic.ServiceNotUpL
 import org.apache.brooklyn.core.sensor.DependentConfiguration;
 import org.apache.brooklyn.core.sensor.Sensors;
 import org.apache.brooklyn.entity.group.DynamicClusterImpl;
+import org.apache.brooklyn.feed.function.FunctionFeed;
+import org.apache.brooklyn.feed.function.FunctionPollConfig;
 import org.apache.brooklyn.sensor.enricher.Enrichers;
-import org.apache.brooklyn.sensor.feed.function.FunctionFeed;
-import org.apache.brooklyn.sensor.feed.function.FunctionPollConfig;
 import org.apache.brooklyn.util.collections.CollectionFunctionals;
 import org.apache.brooklyn.util.core.task.DynamicTasks;
 import org.apache.brooklyn.util.core.task.TaskBuilder;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/daf40919/software/database/src/main/java/org/apache/brooklyn/entity/database/mysql/MySqlNodeImpl.java
----------------------------------------------------------------------
diff --git 
a/software/database/src/main/java/org/apache/brooklyn/entity/database/mysql/MySqlNodeImpl.java
 
b/software/database/src/main/java/org/apache/brooklyn/entity/database/mysql/MySqlNodeImpl.java
index 71c73c6..5346fcb 100644
--- 
a/software/database/src/main/java/org/apache/brooklyn/entity/database/mysql/MySqlNodeImpl.java
+++ 
b/software/database/src/main/java/org/apache/brooklyn/entity/database/mysql/MySqlNodeImpl.java
@@ -24,12 +24,12 @@ import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.core.effector.EffectorBody;
 import org.apache.brooklyn.core.location.Locations;
 import org.apache.brooklyn.entity.software.base.SoftwareProcessImpl;
+import org.apache.brooklyn.feed.ssh.SshFeed;
+import org.apache.brooklyn.feed.ssh.SshPollConfig;
+import org.apache.brooklyn.feed.ssh.SshPollValue;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.brooklyn.location.ssh.SshMachineLocation;
-import org.apache.brooklyn.sensor.feed.ssh.SshFeed;
-import org.apache.brooklyn.sensor.feed.ssh.SshPollConfig;
-import org.apache.brooklyn.sensor.feed.ssh.SshPollValue;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.config.ConfigBag;
 import org.apache.brooklyn.util.guava.Maybe;


Reply via email to