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 2014/07/29 21:32:17 UTC

[22/31] git commit: code review - excellent comments @aledsage

code review - excellent comments @aledsage


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/8f2a6941
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/8f2a6941
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/8f2a6941

Branch: refs/heads/master
Commit: 8f2a6941bc538280a22ed2094f8c078ced5cc7f2
Parents: 40ce411
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Jul 29 10:39:07 2014 -0400
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Jul 29 14:39:27 2014 -0400

----------------------------------------------------------------------
 .../brooklyn/entity/group/DynamicCluster.java   | 18 -------
 .../entity/group/DynamicClusterImpl.java        | 33 +++++++-----
 .../event/basic/DependentConfiguration.java     |  3 ++
 .../util/task/BasicExecutionManager.java        | 54 ++++++++++----------
 .../main/java/brooklyn/util/task/BasicTask.java |  9 ++--
 .../java/brooklyn/util/task/TaskBuilder.java    |  6 +--
 .../location/jclouds/JcloudsLocation.java       |  2 +-
 .../brooklyn/location/jclouds/JcloudsUtil.java  |  2 +
 .../entity/webapp/DynamicWebAppClusterImpl.java | 53 +++++++++----------
 .../util/concurrent/CallableFromRunnable.java   | 54 ++++++++++++++++++++
 .../util/exceptions/ReferenceWithError.java     | 33 +++++++-----
 .../brooklyn/util/javalang/Reflections.java     |  1 +
 .../brooklyn/util/javalang/RunnableAdapter.java | 44 ----------------
 .../main/java/brooklyn/util/net/Networking.java |  8 +--
 .../java/brooklyn/util/repeat/Repeater.java     |  8 +--
 .../java/brooklyn/util/GroovyJavaMethods.groovy |  4 +-
 16 files changed, 173 insertions(+), 159 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8f2a6941/core/src/main/java/brooklyn/entity/group/DynamicCluster.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/group/DynamicCluster.java b/core/src/main/java/brooklyn/entity/group/DynamicCluster.java
index 6fec83e..c44f302 100644
--- a/core/src/main/java/brooklyn/entity/group/DynamicCluster.java
+++ b/core/src/main/java/brooklyn/entity/group/DynamicCluster.java
@@ -45,13 +45,11 @@ import brooklyn.event.basic.BasicAttributeSensor;
 import brooklyn.event.basic.BasicNotificationSensor;
 import brooklyn.event.basic.Sensors;
 import brooklyn.location.Location;
-import brooklyn.util.exceptions.ReferenceWithError;
 import brooklyn.util.flags.SetFromFlag;
 import brooklyn.util.time.Duration;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Function;
-import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Multimap;
 import com.google.common.reflect.TypeToken;
@@ -178,22 +176,6 @@ public interface DynamicCluster extends AbstractGroup, Cluster, MemberReplaceabl
     @Effector(description="Changes the size of the cluster.")
     Collection<Entity> resizeByDelta(@EffectorParam(name="delta", description="The change in number of nodes") int delta);
 
-    /**
-     * Adds a node to the cluster in a single {@link Location}
-     *
-     * @deprecated since 0.7.0 tricky having this on the interface as implementation details
-     * may change; for instance we are (22 Jul) changing the return type to be a ReferenceWithError 
-     */
-    ReferenceWithError<Optional<Entity>> addInSingleLocation(Location loc, Map<?,?> extraFlags);
-
-    /**
-     * Adds a node to the cluster in each {@link Location}
-     * 
-     * @deprecated since 0.7.0 tricky having this on the interface as implementation details
-     * may change; for instance we are (22 Jul) changing the return type to be a ReferenceWithError 
-     */
-    ReferenceWithError<Collection<Entity>> addInEachLocation(Iterable<Location> locs, Map<?,?> extraFlags);
-
     void setRemovalStrategy(Function<Collection<Entity>, Entity> val);
 
     void setZonePlacementStrategy(NodePlacementStrategy val);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8f2a6941/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java b/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
index 271d9e5..b6224a4 100644
--- a/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
+++ b/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
@@ -263,7 +263,8 @@ public class DynamicClusterImpl extends AbstractGroupImpl implements DynamicClus
                 resize(initialSize);
             } catch (Exception e) {
                 Exceptions.propagateIfFatal(e);
-                // ignore problems here; we extract them below
+                // apart from logging, ignore problems here; we extract them below
+                LOG.debug("Error resizing "+this+" to size "+initialSize+" (collecting and handling): "+e, e);
             }
 
             Iterable<Task<?>> failed = Tasks.failed(Tasks.children(Tasks.current()));
@@ -487,7 +488,7 @@ public class DynamicClusterImpl extends AbstractGroupImpl implements DynamicClus
         synchronized (mutex) {
             ReferenceWithError<Optional<Entity>> added = addInSingleLocation(memberLoc, extraFlags);
 
-            if (!added.getIgnoringError().isPresent()) {
+            if (!added.getMaskingError().isPresent()) {
                 String msg = String.format("In %s, failed to grow, to replace %s; not removing", this, member);
                 if (added.hasError())
                     throw new IllegalStateException(msg, added.getError());
@@ -501,7 +502,7 @@ public class DynamicClusterImpl extends AbstractGroupImpl implements DynamicClus
                 throw new StopFailedRuntimeException("replaceMember failed to stop and remove old member "+member.getId(), e);
             }
 
-            return added.getOrThrowError().get();
+            return added.getThrowingError().get();
         }
     }
 
@@ -584,7 +585,7 @@ public class DynamicClusterImpl extends AbstractGroupImpl implements DynamicClus
         }
 
         // create and start the entities
-        return addInEachLocation(chosenLocations, ImmutableMap.of()).getOrThrowError();
+        return addInEachLocation(chosenLocations, ImmutableMap.of()).getThrowingError();
     }
 
     /** <strong>Note</strong> for sub-clases; this method can be called while synchronized on {@link #mutex}. */
@@ -615,16 +616,22 @@ public class DynamicClusterImpl extends AbstractGroupImpl implements DynamicClus
         }
     }
 
-    @Override
-    public ReferenceWithError<Optional<Entity>> addInSingleLocation(Location location, Map<?,?> flags) {
+    protected ReferenceWithError<Optional<Entity>> addInSingleLocation(Location location, Map<?,?> flags) {
         ReferenceWithError<Collection<Entity>> added = addInEachLocation(ImmutableList.of(location), flags);
-        return ReferenceWithError.newInstanceWithInformativeError(
-            Iterables.isEmpty(added.getIgnoringError()) ? Optional.<Entity>absent() : Optional.of(Iterables.getOnlyElement(added.getIgnoringError())),
-                added.getError());
+        
+        Optional<Entity> result = Iterables.isEmpty(added.getMaskingError()) ? Optional.<Entity>absent() : Optional.of(Iterables.getOnlyElement(added.get()));
+        if (!added.hasError()) {
+            return ReferenceWithError.newInstanceWithoutError( result );
+        } else {
+            if (added.masksErrorIfPresent()) {
+                return ReferenceWithError.newInstanceMaskingError( result, added.getError() );
+            } else {
+                return ReferenceWithError.newInstanceThrowingError( result, added.getError() );
+            }
+        }
     }
 
-    @Override
-    public ReferenceWithError<Collection<Entity>> addInEachLocation(Iterable<Location> locations, Map<?,?> flags) {
+    protected ReferenceWithError<Collection<Entity>> addInEachLocation(Iterable<Location> locations, Map<?,?> flags) {
         List<Entity> addedEntities = Lists.newArrayList();
         Map<Entity, Location> addedEntityLocations = Maps.newLinkedHashMap();
         Map<Entity, Task<?>> tasks = Maps.newLinkedHashMap();
@@ -669,10 +676,10 @@ public class DynamicClusterImpl extends AbstractGroupImpl implements DynamicClus
             } else {
                 cleanupFailedNodes(errors.keySet());
             }
-            return ReferenceWithError.newInstanceWithInformativeError(result, Exceptions.create(errors.values()));
+            return ReferenceWithError.newInstanceMaskingError(result, Exceptions.create(errors.values()));
         }
 
-        return ReferenceWithError.newInstanceWithNoError(result);
+        return ReferenceWithError.newInstanceWithoutError(result);
     }
 
     protected void quarantineFailedNodes(Collection<Entity> failedEntities) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8f2a6941/core/src/main/java/brooklyn/event/basic/DependentConfiguration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/basic/DependentConfiguration.java b/core/src/main/java/brooklyn/event/basic/DependentConfiguration.java
index d569aea..8630214 100644
--- a/core/src/main/java/brooklyn/event/basic/DependentConfiguration.java
+++ b/core/src/main/java/brooklyn/event/basic/DependentConfiguration.java
@@ -151,6 +151,9 @@ public class DependentConfiguration {
         return waitInTaskForAttributeReady(source, sensor, ready, ImmutableList.<AttributeAndSensorCondition<?>>of());
     }
     
+    // TODO would be nice to have an easy semantics for whenServiceUp (cf DynamicWebAppClusterImpl.whenServiceUp)
+    // and TODO would be nice to have it stop when source is unmanaged (with ability to define post-processing)
+    // probably using the builder for both of these...
     public static <T> T waitInTaskForAttributeReady(final Entity source, final AttributeSensor<T> sensor, Predicate<? super T> ready, List<AttributeAndSensorCondition<?>> abortConditions) {
         T value = source.getAttribute(sensor);
         final List<Exception> abortion = Lists.newCopyOnWriteArrayList();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8f2a6941/core/src/main/java/brooklyn/util/task/BasicExecutionManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/BasicExecutionManager.java b/core/src/main/java/brooklyn/util/task/BasicExecutionManager.java
index 18858ee..da8c456 100644
--- a/core/src/main/java/brooklyn/util/task/BasicExecutionManager.java
+++ b/core/src/main/java/brooklyn/util/task/BasicExecutionManager.java
@@ -288,33 +288,33 @@ public class BasicExecutionManager implements ExecutionManager {
     }
 
     public <T> Task<T> scheduleWith(Task<T> task) { return scheduleWith(Collections.emptyMap(), task); }
-	public <T> Task<T> scheduleWith(Map<?,?> flags, Task<T> task) {
-		synchronized (task) {
-			if (((TaskInternal<?>)task).getResult()!=null) return task;
-			return submitNewTask(flags, task);
-		}
-	}
+    public <T> Task<T> scheduleWith(Map<?,?> flags, Task<T> task) {
+        synchronized (task) {
+            if (((TaskInternal<?>)task).getResult()!=null) return task;
+            return submitNewTask(flags, task);
+        }
+    }
 
-	@SuppressWarnings("unchecked")
+    @SuppressWarnings("unchecked")
     protected Task<?> submitNewScheduledTask(final Map<?,?> flags, final ScheduledTask task) {
-		task.submitTimeUtc = System.currentTimeMillis();
-		tasksById.put(task.getId(), task);
-		if (!task.isDone()) {
-			task.result = delayedRunner.schedule(new ScheduledTaskCallable(task, flags),
-			    task.delay.toNanoseconds(), TimeUnit.NANOSECONDS);
-		} else {
-			task.endTimeUtc = System.currentTimeMillis();
-		}
-		return task;
-	}
-	
-	protected class ScheduledTaskCallable implements Callable<Object> {
-	    public ScheduledTask task;
-	    public Map<?,?> flags;
-	    
-	    public ScheduledTaskCallable(ScheduledTask task, Map<?, ?> flags) {
-	        this.task = task;
-	        this.flags = flags;
+        task.submitTimeUtc = System.currentTimeMillis();
+        tasksById.put(task.getId(), task);
+        if (!task.isDone()) {
+            task.result = delayedRunner.schedule(new ScheduledTaskCallable(task, flags),
+                task.delay.toNanoseconds(), TimeUnit.NANOSECONDS);
+        } else {
+            task.endTimeUtc = System.currentTimeMillis();
+        }
+        return task;
+    }
+
+    protected class ScheduledTaskCallable implements Callable<Object> {
+        public ScheduledTask task;
+        public Map<?,?> flags;
+
+        public ScheduledTaskCallable(ScheduledTask task, Map<?, ?> flags) {
+            this.task = task;
+            this.flags = flags;
         }
 
         @SuppressWarnings({ "rawtypes", "unchecked" })
@@ -352,12 +352,12 @@ public class BasicExecutionManager implements ExecutionManager {
                 afterEnd(flags, task);
             }
         }
-        
+
         @Override
         public String toString() {
             return "ScheduledTaskCallable["+task+","+flags+"]";
         }
-	}
+    }
 
     @SuppressWarnings("unchecked")
     protected <T> Task<T> submitNewTask(final Map<?,?> flags, final Task<T> task) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8f2a6941/core/src/main/java/brooklyn/util/task/BasicTask.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/BasicTask.java b/core/src/main/java/brooklyn/util/task/BasicTask.java
index 8370512..5bbd9cb 100644
--- a/core/src/main/java/brooklyn/util/task/BasicTask.java
+++ b/core/src/main/java/brooklyn/util/task/BasicTask.java
@@ -144,10 +144,11 @@ public class BasicTask<T> implements TaskInternal<T> {
     @Override
     public String toString() {
         // give display name plus id, or job and tags plus id; some jobs have been extended to include nice tostrings 
-        return "Task["+(Strings.isNonEmpty(displayName) ? displayName : 
-                job + 
-                (tags!=null && !tags.isEmpty() ? ";"+tags : "")) +
-                ":"+getId()+"]";
+        return "Task["+
+            (Strings.isNonEmpty(displayName) ? 
+                displayName : 
+                (job + (tags!=null && !tags.isEmpty() ? ";"+tags : "")) ) +
+            ":"+getId()+"]";
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8f2a6941/core/src/main/java/brooklyn/util/task/TaskBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/TaskBuilder.java b/core/src/main/java/brooklyn/util/task/TaskBuilder.java
index 8b0150d..ed3e282 100644
--- a/core/src/main/java/brooklyn/util/task/TaskBuilder.java
+++ b/core/src/main/java/brooklyn/util/task/TaskBuilder.java
@@ -130,9 +130,9 @@ public class TaskBuilder<T> {
     @SuppressWarnings({ "unchecked", "rawtypes" })
     public Task<T> build() {
         MutableMap<String, Object> taskFlags = MutableMap.copyOf(flags);
-        if (name!=null) taskFlags.add("displayName", name);
-        if (description!=null) taskFlags.add("description", description);
-        if (!tags.isEmpty()) taskFlags.add("tags", tags);
+        if (name!=null) taskFlags.put("displayName", name);
+        if (description!=null) taskFlags.put("description", description);
+        if (!tags.isEmpty()) taskFlags.put("tags", tags);
         
         if (Boolean.FALSE.equals(dynamic) && children.isEmpty()) {
             if (swallowChildrenFailures!=null)

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8f2a6941/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java
index f37c3cb..0736a7d 100644
--- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java
+++ b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java
@@ -1742,7 +1742,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
             .limitTimeTo(delayMs, MILLISECONDS)
             .runKeepingError();
 
-        if (!reachable.getIgnoringError()) {
+        if (!reachable.getMaskingError()) {
             throw new IllegalStateException("SSH failed for "+
                     user+"@"+vmIp+" ("+setup.getDescription()+") after waiting "+
                     Time.makeTimeStringRounded(delayMs), reachable.getError());

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8f2a6941/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsUtil.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsUtil.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsUtil.java
index 2ac077e..9bb6027 100644
--- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsUtil.java
+++ b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsUtil.java
@@ -76,6 +76,7 @@ import brooklyn.location.jclouds.config.BrooklynStandardJcloudsGuiceModule;
 import brooklyn.util.collections.MutableList;
 import brooklyn.util.collections.MutableMap;
 import brooklyn.util.config.ConfigBag;
+import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.net.Protocol;
 import brooklyn.util.ssh.BashCommands;
 import brooklyn.util.ssh.IptablesCommands;
@@ -391,6 +392,7 @@ public class JcloudsUtil implements JcloudsLocationConfig {
         try {
             client = context.utils().sshForNode().apply(node);
         } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
             /* i've seen: java.lang.IllegalStateException: Optional.get() cannot be called on an absent value
              * from org.jclouds.crypto.ASN1Codec.createASN1Sequence(ASN1Codec.java:86), if the ssh key has a passphrase, against AWS.
              * 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8f2a6941/software/webapp/src/main/java/brooklyn/entity/webapp/DynamicWebAppClusterImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/DynamicWebAppClusterImpl.java b/software/webapp/src/main/java/brooklyn/entity/webapp/DynamicWebAppClusterImpl.java
index 7eb6e25..1b40195 100644
--- a/software/webapp/src/main/java/brooklyn/entity/webapp/DynamicWebAppClusterImpl.java
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/DynamicWebAppClusterImpl.java
@@ -30,8 +30,6 @@ import org.slf4j.LoggerFactory;
 
 import brooklyn.enricher.Enrichers;
 import brooklyn.entity.Entity;
-import brooklyn.entity.annotation.Effector;
-import brooklyn.entity.annotation.EffectorParam;
 import brooklyn.entity.basic.Attributes;
 import brooklyn.entity.basic.Entities;
 import brooklyn.entity.basic.EntityInternal;
@@ -68,7 +66,7 @@ import com.google.common.collect.Iterables;
 public class DynamicWebAppClusterImpl extends DynamicClusterImpl implements DynamicWebAppCluster {
 
     private static final Logger log = LoggerFactory.getLogger(DynamicWebAppClusterImpl.class);
-    private static final FilenameToWebContextMapper filenameToWebContextMapper = new FilenameToWebContextMapper();
+    private static final FilenameToWebContextMapper FILENAME_TO_WEB_CONTEXT_MAPPER = new FilenameToWebContextMapper();
     
     /**
      * Instantiate a new DynamicWebAppCluster.  Parameters as per {@link DynamicCluster#DynamicCluster()}
@@ -160,6 +158,7 @@ public class DynamicWebAppClusterImpl extends DynamicClusterImpl implements Dyna
     }
     
     // TODO this will probably be useful elsewhere ... but where to put it?
+    // TODO add support for this in DependentConfiguration (see TODO there)
     /** Waits for the given target to report service up, then runs the given task
      * (often an invocation on that entity), with the given name.
      * If the target goes away, this task marks itself inessential
@@ -174,7 +173,7 @@ public class DynamicWebAppClusterImpl extends DynamicClusterImpl implements Dyna
                             Tasks.markInessential();
                             throw new IllegalStateException("Target "+target+" is no longer managed");
                         }
-                        if (target.getAttribute(Attributes.SERVICE_UP)) {
+                        if (Boolean.TRUE.equals(target.getAttribute(Attributes.SERVICE_UP))) {
                             Tasks.resetBlockingDetails();
                             TaskTags.markInessential(task);
                             DynamicTasks.queue(task);
@@ -202,13 +201,10 @@ public class DynamicWebAppClusterImpl extends DynamicClusterImpl implements Dyna
     }
 
     @Override
-    @Effector(description="Deploys the given artifact, from a source URL, to a given deployment filename/context")
-    public void deploy(
-            @EffectorParam(name="url", description="URL of WAR file") String url, 
-            @EffectorParam(name="targetName", description="context path where WAR should be deployed (/ for ROOT)") String targetName) {
+    public void deploy(String url, String targetName) {
         checkNotNull(url, "url");
         checkNotNull(targetName, "targetName");
-        targetName = filenameToWebContextMapper.convertDeploymentTargetNameToContext(targetName);
+        targetName = FILENAME_TO_WEB_CONTEXT_MAPPER.convertDeploymentTargetNameToContext(targetName);
 
         // set it up so future nodes get the right wars
         addToWarsByContext(this, url, targetName);
@@ -224,19 +220,21 @@ public class DynamicWebAppClusterImpl extends DynamicClusterImpl implements Dyna
         DynamicTasks.queueIfPossible(tb.build()).orSubmitAsync(this).asTask().getUnchecked();
 
         // Update attribute
+        // TODO support for atomic sensor update (should be part of standard tooling; NB there is some work towards this, according to @aledsage)
         Set<String> deployedWars = MutableSet.copyOf(getAttribute(DEPLOYED_WARS));
         deployedWars.add(targetName);
         setAttribute(DEPLOYED_WARS, deployedWars);
     }
     
     @Override
-    @Effector(description="Undeploys the given context/artifact")
-    public void undeploy(@EffectorParam(name="targetName") String targetName) {
+    public void undeploy(String targetName) {
         checkNotNull(targetName, "targetName");
-        targetName = filenameToWebContextMapper.convertDeploymentTargetNameToContext(targetName);
+        targetName = FILENAME_TO_WEB_CONTEXT_MAPPER.convertDeploymentTargetNameToContext(targetName);
         
         // set it up so future nodes get the right wars
-        removeFromWarsByContext(this, targetName);
+        if (!removeFromWarsByContext(this, targetName)) {
+            DynamicTasks.submit(Tasks.warning("Context "+targetName+" not known at "+this+"; attempting to undeploy regardless", null), this);
+        }
         
         log.debug("Undeploying "+targetName+" across cluster "+this+"; WARs now "+getConfig(WARS_BY_CONTEXT));
 
@@ -250,12 +248,13 @@ public class DynamicWebAppClusterImpl extends DynamicClusterImpl implements Dyna
 
         // Update attribute
         Set<String> deployedWars = MutableSet.copyOf(getAttribute(DEPLOYED_WARS));
-        deployedWars.remove( filenameToWebContextMapper.convertDeploymentTargetNameToContext(targetName) );
+        deployedWars.remove( FILENAME_TO_WEB_CONTEXT_MAPPER.convertDeploymentTargetNameToContext(targetName) );
         setAttribute(DEPLOYED_WARS, deployedWars);
     }
 
     static void addToWarsByContext(Entity entity, String url, String targetName) {
-        targetName = filenameToWebContextMapper.convertDeploymentTargetNameToContext(targetName);
+        targetName = FILENAME_TO_WEB_CONTEXT_MAPPER.convertDeploymentTargetNameToContext(targetName);
+        // TODO a better way to do atomic updates, see comment above
         synchronized (entity) {
             Map<String,String> newWarsMap = MutableMap.copyOf(entity.getConfig(WARS_BY_CONTEXT));
             newWarsMap.put(targetName, url);
@@ -263,18 +262,20 @@ public class DynamicWebAppClusterImpl extends DynamicClusterImpl implements Dyna
         }
     }
 
-    static void removeFromWarsByContext(Entity entity, String targetName) {
-        targetName = filenameToWebContextMapper.convertDeploymentTargetNameToContext(targetName);
+    static boolean removeFromWarsByContext(Entity entity, String targetName) {
+        targetName = FILENAME_TO_WEB_CONTEXT_MAPPER.convertDeploymentTargetNameToContext(targetName);
+        // TODO a better way to do atomic updates, see comment above
         synchronized (entity) {
             Map<String,String> newWarsMap = MutableMap.copyOf(entity.getConfig(WARS_BY_CONTEXT));
             String url = newWarsMap.remove(targetName);
             if (url==null) {
-                DynamicTasks.submit(Tasks.warning("Context "+targetName+" not known at "+entity+"; attempting to undeploy regardless", null), entity);
+                return false;
             }
             ((EntityInternal)entity).setConfig(WARS_BY_CONTEXT, newWarsMap);
+            return true;
         }
     }
-
+    
     @Override
     public void redeployAll() {
         Map<String, String> wars = MutableMap.copyOf(getConfig(WARS_BY_CONTEXT));
@@ -282,14 +283,14 @@ public class DynamicWebAppClusterImpl extends DynamicClusterImpl implements Dyna
 
         log.debug("Redeplying all WARs across cluster "+this+": "+getConfig(WARS_BY_CONTEXT));
         
-        Iterable<CanDeployAndUndeploy> targets = Iterables.filter(getChildren(), CanDeployAndUndeploy.class);
-        TaskBuilder<Void> tb = Tasks.<Void>builder().parallel(true).name(redeployPrefix+" across cluster (size "+Iterables.size(targets)+")");
-        for (Entity target: targets) {
-            TaskBuilder<Void> redeployAllToTarget = Tasks.<Void>builder().name(redeployPrefix+" at "+target+" (after ready check)");
-            for (String targetName: wars.keySet()) {
-                redeployAllToTarget.add(Effectors.invocation(target, DEPLOY, MutableMap.of("url", wars.get(targetName), "targetName", targetName)));
+        Iterable<CanDeployAndUndeploy> targetEntities = Iterables.filter(getChildren(), CanDeployAndUndeploy.class);
+        TaskBuilder<Void> tb = Tasks.<Void>builder().parallel(true).name(redeployPrefix+" across cluster (size "+Iterables.size(targetEntities)+")");
+        for (Entity targetEntity: targetEntities) {
+            TaskBuilder<Void> redeployAllToTarget = Tasks.<Void>builder().name(redeployPrefix+" at "+targetEntity+" (after ready check)");
+            for (String warContextPath: wars.keySet()) {
+                redeployAllToTarget.add(Effectors.invocation(targetEntity, DEPLOY, MutableMap.of("url", wars.get(warContextPath), "targetName", warContextPath)));
             }
-            tb.add(whenServiceUp(target, redeployAllToTarget.build(), redeployPrefix+" at "+target+" when ready"));
+            tb.add(whenServiceUp(targetEntity, redeployAllToTarget.build(), redeployPrefix+" at "+targetEntity+" when ready"));
         }
         DynamicTasks.queueIfPossible(tb.build()).orSubmitAsync(this).asTask().getUnchecked();
     }  

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8f2a6941/utils/common/src/main/java/brooklyn/util/concurrent/CallableFromRunnable.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/concurrent/CallableFromRunnable.java b/utils/common/src/main/java/brooklyn/util/concurrent/CallableFromRunnable.java
new file mode 100644
index 0000000..2160e5f
--- /dev/null
+++ b/utils/common/src/main/java/brooklyn/util/concurrent/CallableFromRunnable.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.util.concurrent;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executors;
+
+import com.google.common.annotations.Beta;
+
+/** Wraps a Runnable as a Callable. Like {@link Executors#callable(Runnable, Object)} but including the underlying toString. */
+@Beta
+public class CallableFromRunnable<T> implements Callable<T> {
+    
+    public static <T> CallableFromRunnable<T> newInstance(Runnable task, T result) {
+        return new CallableFromRunnable<T>(task, result);
+    }
+    
+    private final Runnable task;
+    private final T result;
+    
+    protected CallableFromRunnable(Runnable task, T result) {
+        this.task = task;
+        this.result = result;
+    }
+    
+    public T call() {
+        task.run();
+        return result;
+    }
+    
+    @Override
+    public String toString() {
+        if (result!=null)
+            return "CallableFromRunnable["+task+(result!=null ? "->"+result : "")+"]";
+        else
+            return ""+task;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8f2a6941/utils/common/src/main/java/brooklyn/util/exceptions/ReferenceWithError.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/exceptions/ReferenceWithError.java b/utils/common/src/main/java/brooklyn/util/exceptions/ReferenceWithError.java
index 7de6fb5..cdb5925 100644
--- a/utils/common/src/main/java/brooklyn/util/exceptions/ReferenceWithError.java
+++ b/utils/common/src/main/java/brooklyn/util/exceptions/ReferenceWithError.java
@@ -27,58 +27,65 @@ public class ReferenceWithError<T> implements Supplier<T> {
 
     private final T object;
     private final Throwable error;
-    private final boolean throwErrorOnAccess;
+    private final boolean maskError;
 
     /** returns a reference which includes an error, and where attempts to get the content cause the error to throw */
-    public static <T> ReferenceWithError<T> newInstanceWithFatalError(T object, Throwable error) {
+    public static <T> ReferenceWithError<T> newInstanceThrowingError(T object, Throwable error) {
         return new ReferenceWithError<T>(object, error, true);
     }
     
     /** returns a reference which includes an error, but attempts to get the content do not cause the error to throw */
-    public static <T> ReferenceWithError<T> newInstanceWithInformativeError(T object, Throwable error) {
+    public static <T> ReferenceWithError<T> newInstanceMaskingError(T object, Throwable error) {
         return new ReferenceWithError<T>(object, error, false);
     }
     
     /** returns a reference which includes an error, but attempts to get the content do not cause the error to throw */
-    public static <T> ReferenceWithError<T> newInstanceWithNoError(T object) {
+    public static <T> ReferenceWithError<T> newInstanceWithoutError(T object) {
         return new ReferenceWithError<T>(object, null, false);
     }
     
     protected ReferenceWithError(@Nullable T object, @Nullable Throwable error, boolean throwErrorOnAccess) {
         this.object = object;
         this.error = error;
-        this.throwErrorOnAccess = throwErrorOnAccess;
+        this.maskError = throwErrorOnAccess;
     }
 
-    public boolean throwsErrorOnAccess() {
-        return throwErrorOnAccess;
+    /** whether this will mask any error on an attempt to {@link #get()};
+     * if false (if created with {@link #newInstanceThrowingError(Object, Throwable)}) a call to {@link #get()} will throw if there is an error;
+     * true if created with {@link #newInstanceMaskingError(Object, Throwable)} and {@link #get()} will not throw */
+    public boolean masksErrorIfPresent() {
+        return maskError;
     }
 
+    /** returns the underlying value, throwing if there is an error and {@link #throwsErrorOnAccess()} is set */
     public T get() {
-        if (throwsErrorOnAccess()) {
-            return getOrThrowError();
+        if (masksErrorIfPresent()) {
+            return getMaskingError();
         }
-        return getIgnoringError();
+        return getThrowingError();
     }
 
-    public T getIgnoringError() {
+    public T getMaskingError() {
         return object;
     }
 
-    public T getOrThrowError() {
+    public T getThrowingError() {
         checkNoError();
         return object;
     }
 
+    /** throws if there is an error (even if masked) */
     public void checkNoError() {
         if (hasError())
             Exceptions.propagate(error);
     }
-    
+
+    /** returns the error (not throwing) */
     public Throwable getError() {
         return error;
     }
     
+    /** true if there is an error (whether masked or not) */
     public boolean hasError() {
         return error!=null;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8f2a6941/utils/common/src/main/java/brooklyn/util/javalang/Reflections.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/javalang/Reflections.java b/utils/common/src/main/java/brooklyn/util/javalang/Reflections.java
index 9ea35ce..e5b78c6 100644
--- a/utils/common/src/main/java/brooklyn/util/javalang/Reflections.java
+++ b/utils/common/src/main/java/brooklyn/util/javalang/Reflections.java
@@ -209,6 +209,7 @@ public class Reflections {
     /** Invokes a suitable constructor, supporting varargs and primitives */
     public static <T> Optional<T> invokeConstructorWithArgs(ClassLoader classLoader, String className, Object...argsArray) {
         Reflections reflections = new Reflections(classLoader);
+        @SuppressWarnings("unchecked")
         Class<T> clazz = (Class<T>) reflections.loadClass(className);
         return invokeConstructorWithArgs(reflections, clazz, argsArray, false);
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8f2a6941/utils/common/src/main/java/brooklyn/util/javalang/RunnableAdapter.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/javalang/RunnableAdapter.java b/utils/common/src/main/java/brooklyn/util/javalang/RunnableAdapter.java
deleted file mode 100644
index d61e84b..0000000
--- a/utils/common/src/main/java/brooklyn/util/javalang/RunnableAdapter.java
+++ /dev/null
@@ -1,44 +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 brooklyn.util.javalang;
-
-import java.util.concurrent.Callable;
-
-public class RunnableAdapter<T> implements Callable<T> {
-    final Runnable task;
-    final T result;
-    
-    public RunnableAdapter(Runnable task, T result) {
-        this.task = task;
-        this.result = result;
-    }
-    
-    public T call() {
-        task.run();
-        return result;
-    }
-    
-    @Override
-    public String toString() {
-        if (result!=null)
-            return "RunnableAdapter["+task+(result!=null ? "->"+result : "")+"]";
-        else
-            return ""+task;
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8f2a6941/utils/common/src/main/java/brooklyn/util/net/Networking.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/net/Networking.java b/utils/common/src/main/java/brooklyn/util/net/Networking.java
index 5c7df18..8c2d4f1 100644
--- a/utils/common/src/main/java/brooklyn/util/net/Networking.java
+++ b/utils/common/src/main/java/brooklyn/util/net/Networking.java
@@ -387,19 +387,19 @@ public class Networking {
     // TODO go through nic's, looking for public, private, etc, on localhost
 
     /**
-     * intsall TLSv1, fixing:
+     * force use of TLSv1, fixing:
      * http://stackoverflow.com/questions/9828414/receiving-sslhandshakeexception-handshake-failure-despite-my-client-ignoring-al
      */
-    public static void installTlsForHttps() {
+    public static void installTlsOnlyForHttpsForcing() {
         System.setProperty("https.protocols", "TLSv1");
     }
     public static void installTlsForHttpsIfAppropriate() {
         if (System.getProperty("https.protocols")==null && System.getProperty("brooklyn.https.protocols.leave_untouched")==null) {
-            installTlsForHttps();
+            installTlsOnlyForHttpsForcing();
         }
     }
     static {
-        installTlsForHttps();
+        installTlsForHttpsIfAppropriate();
     }
     
     /** does nothing, but forces the class to be loaded and do static initialization */

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8f2a6941/utils/common/src/main/java/brooklyn/util/repeat/Repeater.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/repeat/Repeater.java b/utils/common/src/main/java/brooklyn/util/repeat/Repeater.java
index b2000fa..be0d3f2 100644
--- a/utils/common/src/main/java/brooklyn/util/repeat/Repeater.java
+++ b/utils/common/src/main/java/brooklyn/util/repeat/Repeater.java
@@ -301,7 +301,7 @@ public class Repeater {
      * @return true if the exit condition was satisfied; false if the loop terminated for any other reason.
      */
     public boolean run() {
-        return runKeepingError().getIgnoringError();
+        return runKeepingError().getMaskingError();
     }
     
     public ReferenceWithError<Boolean> runKeepingError() {
@@ -335,7 +335,7 @@ public class Repeater {
             }
             if (done) {
                 if (log.isDebugEnabled()) log.debug("{}: condition satisfied", description);
-                return ReferenceWithError.newInstanceWithNoError(true);
+                return ReferenceWithError.newInstanceWithoutError(true);
             } else {
                 if (log.isDebugEnabled()) {
                     String msg = String.format("%s: unsatisfied during iteration %s %s", description, iterations,
@@ -357,7 +357,7 @@ public class Repeater {
                 }
                 if (warnOnUnRethrownException && lastError != null)
                     log.warn("{}: error caught checking condition: {}", description, lastError.getMessage());
-                return ReferenceWithError.newInstanceWithInformativeError(false, lastError);
+                return ReferenceWithError.newInstanceMaskingError(false, lastError);
             }
 
             if (timer.isExpired()) {
@@ -367,7 +367,7 @@ public class Repeater {
                     log.error("{}: error caught checking condition: {}", description, lastError.getMessage());
                     throw Exceptions.propagate(lastError);
                 }
-                return ReferenceWithError.newInstanceWithInformativeError(false, lastError);
+                return ReferenceWithError.newInstanceMaskingError(false, lastError);
             }
 
             Time.sleep(delayThisIteration);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8f2a6941/utils/groovy/src/main/java/brooklyn/util/GroovyJavaMethods.groovy
----------------------------------------------------------------------
diff --git a/utils/groovy/src/main/java/brooklyn/util/GroovyJavaMethods.groovy b/utils/groovy/src/main/java/brooklyn/util/GroovyJavaMethods.groovy
index c34f72d..199f6a5 100644
--- a/utils/groovy/src/main/java/brooklyn/util/GroovyJavaMethods.groovy
+++ b/utils/groovy/src/main/java/brooklyn/util/GroovyJavaMethods.groovy
@@ -22,7 +22,7 @@ import static brooklyn.util.GroovyJavaMethods.truth
 
 import java.util.concurrent.Callable
 
-import brooklyn.util.javalang.RunnableAdapter
+import brooklyn.util.concurrent.CallableFromRunnable;
 
 import com.google.common.base.Function
 import com.google.common.base.Predicate
@@ -54,7 +54,7 @@ public class GroovyJavaMethods {
     }
 
     public static <T> Callable<T> callableFromRunnable(final Runnable job) {
-        return (job in Callable) ? callableFromClosure(job) : new RunnableAdapter<Object>(job, null);
+        return (job in Callable) ? callableFromClosure(job) : CallableFromRunnable.newInstance(job, null);
     }
 
     public static <T> Predicate<T> predicateFromClosure(final Closure<Boolean> job) {