You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2016/02/01 18:50:21 UTC

[05/50] [abbrv] brooklyn-server git commit: Adds Entity.sensors() to group the sensor methods

Adds Entity.sensors() to group the sensor methods

- The attribute/sensor methods are all in Entity.sensors().
- Deprecates the previous things in Entity.* and EntityLocal.*,
  except for getAttribute(AttributeSensor) which is left as a convenience.
- In EntityInternal.sensors(), it returns SensorSupportInternal
  which has more methods on it.

There are three big motivations for this:
- Consistency with entity.config()
- Simplification of the Entity class (which has way too many methods)
  by grouping them.
- Exposing the methods of EntityLocal on Entity, so we can 
  deprecate EntityLocal (this commit deals with just the attribute/sensor
  methods of EntityLocal)

Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/4f3be274
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/4f3be274
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/4f3be274

Branch: refs/heads/0.8.0-incubating
Commit: 4f3be2744ec579bfcc4f11d7acaa7ae1406891fe
Parents: ae48054
Author: Aled Sage <al...@gmail.com>
Authored: Thu Aug 20 21:59:57 2015 +0100
Committer: Hadrian Zbarcea <ha...@apache.org>
Committed: Sun Aug 23 18:40:59 2015 -0400

----------------------------------------------------------------------
 .../org/apache/brooklyn/api/entity/Entity.java  |  62 ++++-
 .../apache/brooklyn/api/entity/EntityLocal.java |  33 +--
 .../brooklyn/core/entity/AbstractEntity.java    | 278 ++++++++++++-------
 .../brooklyn/core/entity/EntityInternal.java    |  34 ++-
 4 files changed, 273 insertions(+), 134 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/4f3be274/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java b/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
index e109a45..0e25abb 100644
--- a/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
+++ b/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
@@ -27,16 +27,22 @@ import org.apache.brooklyn.api.effector.Effector;
 import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.api.objs.BrooklynObject;
+import org.apache.brooklyn.api.objs.Configurable.ConfigurationSupport;
 import org.apache.brooklyn.api.policy.Policy;
 import org.apache.brooklyn.api.policy.PolicySpec;
 import org.apache.brooklyn.api.sensor.AttributeSensor;
 import org.apache.brooklyn.api.sensor.Enricher;
 import org.apache.brooklyn.api.sensor.EnricherSpec;
 import org.apache.brooklyn.api.sensor.Feed;
+import org.apache.brooklyn.api.sensor.Sensor;
+import org.apache.brooklyn.api.sensor.SensorEvent;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.config.ConfigKey.HasConfigKey;
 import org.apache.brooklyn.util.guava.Maybe;
 
+import com.google.common.annotations.Beta;
+import com.google.common.base.Function;
+
 /**
  * The basic interface for a Brooklyn entity.
  * <p>
@@ -185,15 +191,13 @@ public interface Entity extends BrooklynObject {
     Collection<Location> getLocations();
 
     /**
-     * Gets the value of the given attribute on this entity, or null if has not been set.
-     *
-     * Attributes can be things like workrate and status information, as well as
-     * configuration (e.g. url/jmxHost/jmxPort), etc.
+     * Convenience for calling {@link SensorSupport#get(AttributeSensor)},
+     * via code like {@code sensors().get(key)}.
      */
     <T> T getAttribute(AttributeSensor<T> sensor);
 
     /**
-     * Convenience for calling {@link ConfigurationSupport#getConfig(ConfigKey)},
+     * Convenience for calling {@link ConfigurationSupport#get(ConfigKey)},
      * via code like {@code config().get(key)}.
      */
     <T> T getConfig(ConfigKey<T> key);
@@ -262,4 +266,52 @@ public interface Entity extends BrooklynObject {
      * Adds the given feed to this entity. Also calls feed.setEntity if available.
      */
     <T extends Feed> T addFeed(T feed);
+    
+    SensorSupport sensors();
+
+    @Beta
+    public interface SensorSupport {
+
+        /**
+         * Gets the value of the given attribute on this entity, or null if has not been set.
+         *
+         * Attributes can be things like workrate and status information, as well as
+         * configuration (e.g. url/jmxHost/jmxPort), etc.
+         */
+        <T> T get(AttributeSensor<T> key);
+
+        /**
+         * Sets the {@link AttributeSensor} data for the given attribute to the specified value.
+         * 
+         * This can be used to "enrich" the entity, such as adding aggregated information, 
+         * rolling averages, etc.
+         * 
+         * @return the old value for the attribute (possibly {@code null})
+         */
+        <T> T set(AttributeSensor<T> attribute, T val);
+
+        /**
+         * Atomically modifies the {@link AttributeSensor}, ensuring that only one modification is done
+         * at a time.
+         * 
+         * If the modifier returns {@link Maybe#absent()} then the attribute will be
+         * left unmodified, and the existing value will be returned.
+         * 
+         * For details of the synchronization model used to achieve this, refer to the underlying 
+         * attribute store (e.g. AttributeMap).
+         * 
+         * @return the old value for the attribute (possibly {@code null})
+         * @since 0.7.0-M2
+         */
+        @Beta
+        <T> T modify(AttributeSensor<T> attribute, Function<? super T, Maybe<T>> modifier);
+
+        /**
+         * Emits a {@link SensorEvent} event on behalf of this entity (as though produced by this entity).
+         * <p>
+         * Note that for attribute sensors it is nearly always recommended to use setAttribute, 
+         * as this method will not update local values.
+         */
+        <T> void emit(Sensor<T> sensor, T value);
+    }
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/4f3be274/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java b/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java
index c831dfd..5533949 100644
--- a/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java
+++ b/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java
@@ -26,7 +26,6 @@ import org.apache.brooklyn.api.mgmt.SubscriptionManager;
 import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.api.sensor.AttributeSensor;
 import org.apache.brooklyn.api.sensor.Sensor;
-import org.apache.brooklyn.api.sensor.SensorEvent;
 import org.apache.brooklyn.api.sensor.SensorEventListener;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.config.ConfigKey.HasConfigKey;
@@ -81,32 +80,22 @@ public interface EntityLocal extends Entity {
     <T> T setConfig(HasConfigKey<T> key, Task<T> val);
 
     /**
-     * Sets the {@link AttributeSensor} data for the given attribute to the specified value.
-     * 
-     * This can be used to "enrich" the entity, such as adding aggregated information, 
-     * rolling averages, etc.
-     * 
-     * @return the old value for the attribute (possibly {@code null})
+     * @deprecated since 0.8.0; use {@link SensorSupport#set(AttributeSensor, Object)} via code like {@code sensors().set(attribute, val)}.
      */
     <T> T setAttribute(AttributeSensor<T> attribute, T val);
 
     /**
-     * Atomically modifies the {@link AttributeSensor}, ensuring that only one modification is done
-     * at a time.
-     * 
-     * If the modifier returns {@link Maybe#absent()} then the attribute will be
-     * left unmodified, and the existing value will be returned.
-     * 
-     * For details of the synchronization model used to achieve this, refer to the underlying 
-     * attribute store (e.g. AttributeMap).
-     * 
-     * @return the old value for the attribute (possibly {@code null})
-     * @since 0.7.0-M2
+     * @deprecated since 0.8.0; use {@link SensorSupport#modify(AttributeSensor, Function)} via code like {@code sensors().modify(attribute, modifier)}.
      */
     @Beta
     <T> T modifyAttribute(AttributeSensor<T> attribute, Function<? super T, Maybe<T>> modifier);
 
     /**
+     * @deprecated since 0.8.0; use {@link SensorSupport#emit(Sensor, Object)} via code like {@code sensors().emit(sensor, val)}.
+     */
+    <T> void emit(Sensor<T> sensor, T value);
+    
+    /**
      * @deprecated in 0.5; use {@link #getConfig(ConfigKey)}
      */
     <T> T getConfig(ConfigKey<T> key, T defaultValue);
@@ -117,14 +106,6 @@ public interface EntityLocal extends Entity {
     <T> T getConfig(HasConfigKey<T> key, T defaultValue);
 
     /**
-     * Emits a {@link SensorEvent} event on behalf of this entity (as though produced by this entity).
-     * <p>
-     * Note that for attribute sensors it is nearly always recommended to use setAttribute, 
-     * as this method will not update local values.
-     */
-    <T> void emit(Sensor<T> sensor, T value);
-    
-    /**
      * Allow us to subscribe to data from a {@link Sensor} on another entity.
      * 
      * @return a subscription id which can be used to unsubscribe

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/4f3be274/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
index fb8f2d0..5dc110d 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
@@ -218,6 +218,8 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
 
     private final BasicConfigurationSupport config = new BasicConfigurationSupport();
 
+    private final BasicSensorSupport sensors = new BasicSensorSupport();
+
     /**
      * The config values of this entity. Updating this map should be done
      * via getConfig/setConfig.
@@ -843,10 +845,15 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
 
     @Override
     public <T> T getAttribute(AttributeSensor<T> attribute) {
-        return attributesInternal.getValue(attribute);
+        return sensors().get(attribute);
     }
 
+    /**
+     * @deprecated since 0.8.0; use {@link SensorSupport#get(AttributeSensor)}, 
+     *             which may require constructing a temporary sensor using {@link Sensors#newSensor(Class, String)}.
+     */
     @SuppressWarnings("unchecked")
+    @Deprecated
     public <T> T getAttributeByNameParts(List<String> nameParts) {
         return (T) attributesInternal.getValue(nameParts);
     }
@@ -854,88 +861,28 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     static Set<String> WARNED_READ_ONLY_ATTRIBUTES = Collections.synchronizedSet(MutableSet.<String>of());
     
     @Override
+    @Deprecated
     public <T> T setAttribute(AttributeSensor<T> attribute, T val) {
-        if (LOG.isTraceEnabled())
-            LOG.trace(""+this+" setAttribute "+attribute+" "+val);
-        
-        if (Boolean.TRUE.equals(getManagementSupport().isReadOnlyRaw())) {
-            T oldVal = getAttribute(attribute);
-            if (Equals.approximately(val, oldVal)) {
-                // ignore, probably an enricher resetting values or something on init
-            } else {
-                String message = this+" setting "+attribute+" = "+val+" (was "+oldVal+") in read only mode; will have very little effect"; 
-                if (!getManagementSupport().isDeployed()) {
-                    if (getManagementSupport().wasDeployed()) message += " (no longer deployed)"; 
-                    else message += " (not yet deployed)";
-                }
-                if (WARNED_READ_ONLY_ATTRIBUTES.add(attribute.getName())) {
-                    LOG.warn(message + " (future messages for this sensor logged at trace)");
-                } else if (LOG.isTraceEnabled()) {
-                    LOG.trace(message);
-                }
-            }
-        }
-        T result = attributesInternal.update(attribute, val);
-        if (result == null) {
-            // could be this is a new sensor
-            entityType.addSensorIfAbsent(attribute);
-        }
-        
-        getManagementSupport().getEntityChangeListener().onAttributeChanged(attribute);
-        return result;
+        return sensors().set(attribute, val);
     }
 
     @Override
+    @Deprecated
     public <T> T setAttributeWithoutPublishing(AttributeSensor<T> attribute, T val) {
-        if (LOG.isTraceEnabled())
-            LOG.trace(""+this+" setAttributeWithoutPublishing "+attribute+" "+val);
-        
-        T result = attributesInternal.updateWithoutPublishing(attribute, val);
-        if (result == null) {
-            // could be this is a new sensor
-            entityType.addSensorIfAbsentWithoutPublishing(attribute);
-        }
-        
-        getManagementSupport().getEntityChangeListener().onAttributeChanged(attribute);
-        return result;
+        return sensors().setWithoutPublishing(attribute, val);
     }
 
     @Beta
     @Override
+    @Deprecated
     public <T> T modifyAttribute(AttributeSensor<T> attribute, Function<? super T, Maybe<T>> modifier) {
-        if (LOG.isTraceEnabled())
-            LOG.trace(""+this+" modifyAttribute "+attribute+" "+modifier);
-        
-        if (Boolean.TRUE.equals(getManagementSupport().isReadOnlyRaw())) {
-            String message = this+" modifying "+attribute+" = "+modifier+" in read only mode; will have very little effect"; 
-            if (!getManagementSupport().isDeployed()) {
-                if (getManagementSupport().wasDeployed()) message += " (no longer deployed)"; 
-                else message += " (not yet deployed)";
-            }
-            if (WARNED_READ_ONLY_ATTRIBUTES.add(attribute.getName())) {
-                LOG.warn(message + " (future messages for this sensor logged at trace)");
-            } else if (LOG.isTraceEnabled()) {
-                LOG.trace(message);
-            }
-        }
-        T result = attributesInternal.modify(attribute, modifier);
-        if (result == null) {
-            // could be this is a new sensor
-            entityType.addSensorIfAbsent(attribute);
-        }
-        
-        // TODO Conditionally set onAttributeChanged, only if was modified
-        getManagementSupport().getEntityChangeListener().onAttributeChanged(attribute);
-        return result;
+        return sensors().modify(attribute, modifier);
     }
 
     @Override
+    @Deprecated
     public void removeAttribute(AttributeSensor<?> attribute) {
-        if (LOG.isTraceEnabled())
-            LOG.trace(""+this+" removeAttribute "+attribute);
-        
-        attributesInternal.remove(attribute);
-        entityType.removeSensor(attribute);
+        sensors().remove(attribute);
     }
 
     /** sets the value of the given attribute sensor from the config key value herein
@@ -952,22 +899,10 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     }
 
     @Override
+    @Deprecated
+    @SuppressWarnings("rawtypes")
     public Map<AttributeSensor, Object> getAllAttributes() {
-        Map<AttributeSensor, Object> result = Maps.newLinkedHashMap();
-        Map<String, Object> attribs = attributesInternal.asMap();
-        for (Map.Entry<String,Object> entry : attribs.entrySet()) {
-            AttributeSensor<?> attribKey = (AttributeSensor<?>) entityType.getSensor(entry.getKey());
-            if (attribKey == null) {
-                // Most likely a race: e.g. persister thread calling getAllAttributes; writer thread
-                // has written attribute value and is in process of calling entityType.addSensorIfAbsent(attribute)
-                // Just use a synthetic AttributeSensor, rather than ignoring value.
-                // TODO If it's not a race, then don't log.warn every time!
-                LOG.warn("When retrieving all attributes of {}, no AttributeSensor for attribute {} (creating synthetic)", this, entry.getKey());
-                attribKey = Sensors.newSensor(Object.class, entry.getKey());
-            }
-            result.put(attribKey, entry.getValue());
-        }
-        return result;
+        return Collections.<AttributeSensor, Object>unmodifiableMap(sensors().getAll());
     }
 
     
@@ -982,6 +917,157 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
         return config;
     }
 
+    @Override 
+    @Beta
+    // the concrete type rather than an interface is returned because Groovy subclasses
+    // complain (incorrectly) if we return SensorsSupport
+    // TODO revert to SensorsSupportInternal when groovy subclasses work without this (eg new groovy version)
+    public BasicSensorSupport sensors() {
+        return sensors;
+    }
+
+    /**
+     * Direct use of this class is strongly discouraged. It will become private in a future release,
+     * once {@link #sensors()} is reverted to return {@link SensorsSupport} instead of
+     * {@link BasicSensorSupport}.
+     */
+    @Beta
+    // TODO revert to private when config() is reverted to return SensorSupportInternal
+    public class BasicSensorSupport implements SensorSupportInternal {
+
+        @Override
+        public <T> T get(AttributeSensor<T> attribute) {
+            return attributesInternal.getValue(attribute);
+        }
+
+        @Override
+        public <T> T set(AttributeSensor<T> attribute, T val) {
+            if (LOG.isTraceEnabled())
+                LOG.trace(""+AbstractEntity.this+" setAttribute "+attribute+" "+val);
+            
+            if (Boolean.TRUE.equals(getManagementSupport().isReadOnlyRaw())) {
+                T oldVal = getAttribute(attribute);
+                if (Equals.approximately(val, oldVal)) {
+                    // ignore, probably an enricher resetting values or something on init
+                } else {
+                    String message = AbstractEntity.this+" setting "+attribute+" = "+val+" (was "+oldVal+") in read only mode; will have very little effect"; 
+                    if (!getManagementSupport().isDeployed()) {
+                        if (getManagementSupport().wasDeployed()) message += " (no longer deployed)"; 
+                        else message += " (not yet deployed)";
+                    }
+                    if (WARNED_READ_ONLY_ATTRIBUTES.add(attribute.getName())) {
+                        LOG.warn(message + " (future messages for this sensor logged at trace)");
+                    } else if (LOG.isTraceEnabled()) {
+                        LOG.trace(message);
+                    }
+                }
+            }
+            T result = attributesInternal.update(attribute, val);
+            if (result == null) {
+                // could be this is a new sensor
+                entityType.addSensorIfAbsent(attribute);
+            }
+            
+            getManagementSupport().getEntityChangeListener().onAttributeChanged(attribute);
+            return result;
+        }
+
+        @Override
+        public <T> T setWithoutPublishing(AttributeSensor<T> attribute, T val) {
+            if (LOG.isTraceEnabled())
+                LOG.trace(""+AbstractEntity.this+" setAttributeWithoutPublishing "+attribute+" "+val);
+            
+            T result = attributesInternal.updateWithoutPublishing(attribute, val);
+            if (result == null) {
+                // could be this is a new sensor
+                entityType.addSensorIfAbsentWithoutPublishing(attribute);
+            }
+            
+            getManagementSupport().getEntityChangeListener().onAttributeChanged(attribute);
+            return result;
+        }
+
+        @Beta
+        @Override
+        public <T> T modify(AttributeSensor<T> attribute, Function<? super T, Maybe<T>> modifier) {
+            if (LOG.isTraceEnabled())
+                LOG.trace(""+AbstractEntity.this+" modifyAttribute "+attribute+" "+modifier);
+            
+            if (Boolean.TRUE.equals(getManagementSupport().isReadOnlyRaw())) {
+                String message = AbstractEntity.this+" modifying "+attribute+" = "+modifier+" in read only mode; will have very little effect"; 
+                if (!getManagementSupport().isDeployed()) {
+                    if (getManagementSupport().wasDeployed()) message += " (no longer deployed)"; 
+                    else message += " (not yet deployed)";
+                }
+                if (WARNED_READ_ONLY_ATTRIBUTES.add(attribute.getName())) {
+                    LOG.warn(message + " (future messages for this sensor logged at trace)");
+                } else if (LOG.isTraceEnabled()) {
+                    LOG.trace(message);
+                }
+            }
+            T result = attributesInternal.modify(attribute, modifier);
+            if (result == null) {
+                // could be this is a new sensor
+                entityType.addSensorIfAbsent(attribute);
+            }
+            
+            // TODO Conditionally set onAttributeChanged, only if was modified
+            getManagementSupport().getEntityChangeListener().onAttributeChanged(attribute);
+            return result;
+        }
+
+        @Override
+        public void remove(AttributeSensor<?> attribute) {
+            if (LOG.isTraceEnabled())
+                LOG.trace(""+AbstractEntity.this+" removeAttribute "+attribute);
+            
+            attributesInternal.remove(attribute);
+            entityType.removeSensor(attribute);
+        }
+
+        @Override
+        public Map<AttributeSensor<?>, Object> getAll() {
+            Map<AttributeSensor<?>, Object> result = Maps.newLinkedHashMap();
+            Map<String, Object> attribs = attributesInternal.asMap();
+            for (Map.Entry<String,Object> entry : attribs.entrySet()) {
+                AttributeSensor<?> attribKey = (AttributeSensor<?>) entityType.getSensor(entry.getKey());
+                if (attribKey == null) {
+                    // Most likely a race: e.g. persister thread calling getAllAttributes; writer thread
+                    // has written attribute value and is in process of calling entityType.addSensorIfAbsent(attribute)
+                    // Just use a synthetic AttributeSensor, rather than ignoring value.
+                    // TODO If it's not a race, then don't log.warn every time!
+                    LOG.warn("When retrieving all attributes of {}, no AttributeSensor for attribute {} (creating synthetic)", AbstractEntity.this, entry.getKey());
+                    attribKey = Sensors.newSensor(Object.class, entry.getKey());
+                }
+                result.put(attribKey, entry.getValue());
+            }
+            return result;
+        }
+        
+        @Override
+        public <T> void emit(Sensor<T> sensor, T val) {
+            if (sensor instanceof AttributeSensor) {
+                LOG.warn("Strongly discouraged use of emit with attribute sensor "+sensor+" "+val+"; use setAttribute instead!",
+                    new Throwable("location of discouraged attribute "+sensor+" emit"));
+            }
+            if (val instanceof SensorEvent) {
+                LOG.warn("Strongly discouraged use of emit with sensor event as value "+sensor+" "+val+"; value should be unpacked!",
+                    new Throwable("location of discouraged event "+sensor+" emit"));
+            }
+            BrooklynLogging.log(LOG, BrooklynLogging.levelDebugOrTraceIfReadOnly(AbstractEntity.this),
+                "Emitting sensor notification {} value {} on {}", sensor.getName(), val, AbstractEntity.this);
+            emitInternal(sensor, val);
+        }
+        
+        public <T> void emitInternal(Sensor<T> sensor, T val) {
+            if (getManagementSupport().isNoLongerManaged())
+                throw new IllegalStateException("Entity "+AbstractEntity.this+" is no longer managed, when trying to publish "+sensor+" "+val);
+
+            SubscriptionContext subsContext = getSubscriptionContext();
+            if (subsContext != null) subsContext.publish(sensor.newEvent(getProxyIfAvailable(), val));
+        }
+    }
+    
     /**
      * Direct use of this class is strongly discouraged. It will become private in a future release,
      * once {@link #config()} is reverted to return {@link ConfigurationSupportInternal} instead of
@@ -1087,7 +1173,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
                 // i (Alex) think the way to be stricter about this (if that becomes needed) 
                 // would be to introduce a 'mutable' field on config keys
                 LOG.debug("configuration being made to {} after deployment: {} = {}; change may not be visible in other contexts", 
-                        new Object[] { this, key, val });
+                        new Object[] { AbstractEntity.this, key, val });
             }
             T result = (T) configsInternal.setConfig(key, val);
             
@@ -1601,26 +1687,16 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     // -------- SENSORS --------------------
 
     @Override
+    @Deprecated
     public <T> void emit(Sensor<T> sensor, T val) {
-        if (sensor instanceof AttributeSensor) {
-            LOG.warn("Strongly discouraged use of emit with attribute sensor "+sensor+" "+val+"; use setAttribute instead!",
-                new Throwable("location of discouraged attribute "+sensor+" emit"));
-        }
-        if (val instanceof SensorEvent) {
-            LOG.warn("Strongly discouraged use of emit with sensor event as value "+sensor+" "+val+"; value should be unpacked!",
-                new Throwable("location of discouraged event "+sensor+" emit"));
-        }
-        BrooklynLogging.log(LOG, BrooklynLogging.levelDebugOrTraceIfReadOnly(this),
-            "Emitting sensor notification {} value {} on {}", sensor.getName(), val, this);
-        emitInternal(sensor, val);
+        sensors().emit(sensor, val);
     }
     
+    /**
+     * Warning: for internal purposes only; this method may be deleted without notice in future releases.
+     */
     public <T> void emitInternal(Sensor<T> sensor, T val) {
-        if (getManagementSupport().isNoLongerManaged())
-            throw new IllegalStateException("Entity "+this+" is no longer managed, when trying to publish "+sensor+" "+val);
-
-        SubscriptionContext subsContext = getSubscriptionContext();
-        if (subsContext != null) subsContext.publish(sensor.newEvent(getProxyIfAvailable(), val));
+        sensors().emitInternal(sensor, val);
     }
 
     // -------- EFFECTORS --------------

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/4f3be274/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java b/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
index 0147170..3811ce8 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
@@ -22,7 +22,9 @@ import java.util.Collection;
 import java.util.Map;
 
 import org.apache.brooklyn.api.effector.Effector;
+import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntityLocal;
+import org.apache.brooklyn.api.entity.Entity.SensorSupport;
 import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.mgmt.ExecutionContext;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
@@ -30,13 +32,17 @@ import org.apache.brooklyn.api.mgmt.SubscriptionContext;
 import org.apache.brooklyn.api.mgmt.rebind.RebindSupport;
 import org.apache.brooklyn.api.mgmt.rebind.Rebindable;
 import org.apache.brooklyn.api.mgmt.rebind.mementos.EntityMemento;
+import org.apache.brooklyn.api.objs.Configurable;
 import org.apache.brooklyn.api.sensor.AttributeSensor;
 import org.apache.brooklyn.api.sensor.Feed;
 import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.config.ConfigKey.HasConfigKey;
 import org.apache.brooklyn.core.entity.internal.EntityConfigMap;
 import org.apache.brooklyn.core.mgmt.internal.EntityManagementSupport;
 import org.apache.brooklyn.core.objs.BrooklynObjectInternal;
+import org.apache.brooklyn.core.objs.BrooklynObjectInternal.ConfigurationSupportInternal;
 import org.apache.brooklyn.util.core.config.ConfigBag;
+import org.apache.brooklyn.util.guava.Maybe;
 
 import com.google.common.annotations.Beta;
 
@@ -54,8 +60,7 @@ public interface EntityInternal extends BrooklynObjectInternal, EntityLocal, Reb
     void clearLocations();
 
     /**
-     * 
-     * Like {@link EntityLocal#setAttribute(AttributeSensor, Object)}, except does not publish an attribute-change event.
+     * @deprecated since 0.8.0; use {@link SensorSupportInternal#setWithoutPublishing(AttributeSensor, Object)} via code like {@code sensors().setWithoutPublishing(attribute, val)}.
      */
     <T> T setAttributeWithoutPublishing(AttributeSensor<T> sensor, T val);
 
@@ -93,9 +98,15 @@ public interface EntityInternal extends BrooklynObjectInternal, EntityLocal, Reb
     @Deprecated
     ConfigBag getLocalConfigBag();
 
+    /**
+     * @deprecated since 0.8.0; use {@link SensorSupportInternal#getAll()} via code like {@code sensors().getAll()}.
+     */
     @Beta
     Map<AttributeSensor, Object> getAllAttributes();
 
+    /**
+     * @deprecated since 0.8.0; use {@link SensorSupportInternal#remove(AttributeSensor)} via code like {@code sensors().remove(attribute)}.
+     */
     @Beta
     void removeAttribute(AttributeSensor<?> attribute);
 
@@ -177,6 +188,25 @@ public interface EntityInternal extends BrooklynObjectInternal, EntityLocal, Reb
      */
     void requestPersist();
     
+    SensorSupportInternal sensors();
+
+    @Beta
+    public interface SensorSupportInternal extends Entity.SensorSupport {
+        /**
+         * 
+         * Like {@link EntityLocal#setAttribute(AttributeSensor, Object)}, except does not publish an attribute-change event.
+         */
+        <T> T setWithoutPublishing(AttributeSensor<T> sensor, T val);
+        
+        @Beta
+        Map<AttributeSensor<?>, Object> getAll();
+
+        @Beta
+        void remove(AttributeSensor<?> attribute);
+
+
+    }
+
     public interface FeedSupport {
         Collection<Feed> getFeeds();