You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by sj...@apache.org on 2015/11/19 15:36:28 UTC

[1/5] incubator-brooklyn git commit: Trivial doc fix

Repository: incubator-brooklyn
Updated Branches:
  refs/heads/master d8822bd96 -> cf286fea0


Trivial doc fix


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

Branch: refs/heads/master
Commit: 0f777c5071843ca4e54ab9ca901194cf437bb093
Parents: 8f384a1
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Wed Nov 18 12:46:32 2015 +0000
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Thu Nov 19 13:58:58 2015 +0000

----------------------------------------------------------------------
 .../apache/brooklyn/rest/jsgui/BrooklynJavascriptGuiLauncher.java  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0f777c50/usage/jsgui/src/test/java/org/apache/brooklyn/rest/jsgui/BrooklynJavascriptGuiLauncher.java
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/test/java/org/apache/brooklyn/rest/jsgui/BrooklynJavascriptGuiLauncher.java b/usage/jsgui/src/test/java/org/apache/brooklyn/rest/jsgui/BrooklynJavascriptGuiLauncher.java
index 0f573c6..6c261fe 100644
--- a/usage/jsgui/src/test/java/org/apache/brooklyn/rest/jsgui/BrooklynJavascriptGuiLauncher.java
+++ b/usage/jsgui/src/test/java/org/apache/brooklyn/rest/jsgui/BrooklynJavascriptGuiLauncher.java
@@ -49,7 +49,7 @@ public class BrooklynJavascriptGuiLauncher {
     public static void main(String[] args) throws Exception {
         // NOTE: When running Brooklyn from an IDE (i.e. by launching BrooklynJavascriptGuiLauncher.main())
         // you will need to ensure that the working directory is set to the jsgui folder. For IntelliJ,
-        // set the 'Working directory' of the Run/Debug Configuration to $MODULE_DIR/../jsgui.
+        // set the 'Working directory' of the Run/Debug Configuration to $MODULE_DIR$/../jsgui.
         // For Eclipse, use the default option of ${workspace_loc:brooklyn-jsgui}.
         // If the working directory is not set correctly, Brooklyn will be unable to find the jsgui .war
         // file and the 'gui not available' message will be shown.


[4/5] incubator-brooklyn git commit: Pollers set cancelOnException=false when scheduling tasks

Posted by sj...@apache.org.
Pollers set cancelOnException=false when scheduling tasks


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

Branch: refs/heads/master
Commit: 5832a15f2a30ba81f3b5b104b17795a5520b06af
Parents: e0014b1
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Wed Nov 18 14:36:32 2015 +0000
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Thu Nov 19 14:01:54 2015 +0000

----------------------------------------------------------------------
 .../org/apache/brooklyn/core/feed/Poller.java   |   9 +-
 .../apache/brooklyn/core/feed/PollerTest.java   | 191 ++++++++++++-------
 2 files changed, 125 insertions(+), 75 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5832a15f/core/src/main/java/org/apache/brooklyn/core/feed/Poller.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/feed/Poller.java b/core/src/main/java/org/apache/brooklyn/core/feed/Poller.java
index d57f826..a9a34d9 100644
--- a/core/src/main/java/org/apache/brooklyn/core/feed/Poller.java
+++ b/core/src/main/java/org/apache/brooklyn/core/feed/Poller.java
@@ -19,6 +19,7 @@
 package org.apache.brooklyn.core.feed;
 
 import java.util.LinkedHashSet;
+import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.Callable;
 
@@ -31,6 +32,7 @@ import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.task.DynamicSequentialTask;
 import org.apache.brooklyn.util.core.task.ScheduledTask;
+import org.apache.brooklyn.util.core.task.TaskTags;
 import org.apache.brooklyn.util.core.task.Tasks;
 import org.apache.brooklyn.util.time.Duration;
 import org.slf4j.Logger;
@@ -155,8 +157,11 @@ public class Poller<V> {
                         return task;
                     }
                 };
-                ScheduledTask task = new ScheduledTask(MutableMap.of("period", pollJob.pollPeriod, "displayName", "scheduled:"+scheduleName), pollingTaskFactory);
-                tasks.add((ScheduledTask)Entities.submit(entity, task));
+                Map<String, ?> taskFlags = MutableMap.of("displayName", "scheduled:" + scheduleName);
+                ScheduledTask task = new ScheduledTask(taskFlags, pollingTaskFactory)
+                        .period(pollJob.pollPeriod)
+                        .cancelOnException(false);
+                tasks.add(Entities.submit(entity, task));
             } else {
                 if (log.isDebugEnabled()) log.debug("Activating poll (but leaving off, as period {}) for {} (using {})", new Object[] {pollJob.pollPeriod, entity, this});
             }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5832a15f/core/src/test/java/org/apache/brooklyn/core/feed/PollerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/feed/PollerTest.java b/core/src/test/java/org/apache/brooklyn/core/feed/PollerTest.java
index 0f2c1ce..6495f566 100644
--- a/core/src/test/java/org/apache/brooklyn/core/feed/PollerTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/feed/PollerTest.java
@@ -18,91 +18,136 @@
  */
 package org.apache.brooklyn.core.feed;
 
-import static org.testng.Assert.assertTrue;
-
+import java.util.Map;
 import java.util.concurrent.Callable;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
 
+import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.core.feed.PollHandler;
-import org.apache.brooklyn.core.feed.Poller;
+import org.apache.brooklyn.api.entity.ImplementedBy;
+import org.apache.brooklyn.api.mgmt.Task;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.entity.AbstractEntity;
+import org.apache.brooklyn.core.entity.EntityAsserts;
+import org.apache.brooklyn.core.sensor.Sensors;
 import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
-import org.apache.brooklyn.core.test.entity.TestEntity;
-import org.apache.brooklyn.test.Asserts;
-import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.feed.function.FunctionFeed;
+import org.apache.brooklyn.feed.function.FunctionPollConfig;
 import org.apache.brooklyn.util.core.task.DynamicTasks;
-import org.apache.brooklyn.util.time.Duration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
+import org.apache.brooklyn.util.core.task.Tasks;
+import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
+import com.google.common.base.Functions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
 public class PollerTest extends BrooklynAppUnitTestSupport {
 
-    private static final Logger LOG = LoggerFactory.getLogger(PollerTest.class);
-
-    private TestEntity entity;
-    private Poller<Integer> poller;
-    
-    @BeforeMethod(alwaysRun=true)
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
-        poller = new Poller<Integer>(entity, false);
+    @DataProvider(name = "specProvider")
+    public Object[][] specProvider() {
+        EntitySpec<FeedExceptionEntity> pollFailer = EntitySpec.create(FeedExceptionEntity.class)
+                .configure(FeedExceptionEntity.POLLER, new PollFailer());
+        EntitySpec<FeedExceptionEntity> taskFailer = EntitySpec.create(FeedExceptionEntity.class)
+                .configure(FeedExceptionEntity.POLLER, new TaskFailer());
+        return new Object[][]{{pollFailer}, {taskFailer}};
+    }
+
+    @Test(dataProvider = "specProvider")
+    public void testFeedContinuesWhenPollerThrows(EntitySpec<FeedExceptionEntity> spec) {
+        Map<?, ?> timeoutFlags = ImmutableMap.of("timeout", "100ms");
+        FeedExceptionEntity fee = app.createAndManageChild(spec);
+        app.start(ImmutableList.of(app.newSimulatedLocation()));
+        EntityAsserts.assertAttributeEqualsEventually(timeoutFlags, fee, FeedExceptionEntity.FLAG, true);
+
+        fee.startThrowingPollExceptions();
+        EntityAsserts.assertAttributeEqualsEventually(timeoutFlags, fee, FeedExceptionEntity.FLAG, false);
+        EntityAsserts.assertAttributeEqualsContinually(timeoutFlags, fee, FeedExceptionEntity.FLAG, false);
+
+        fee.stopThrowingPollExceptions();
+        EntityAsserts.assertAttributeEqualsEventually(timeoutFlags, fee, FeedExceptionEntity.FLAG, true);
+        EntityAsserts.assertAttributeEqualsContinually(timeoutFlags, fee, FeedExceptionEntity.FLAG, true);
     }
-    
-    @AfterMethod(alwaysRun=true)
-    @Override
-    public void tearDown() throws Exception {
-        if (poller != null) poller.stop();
-        super.tearDown();
+
+    @ImplementedBy(FeedExceptionEntityImpl.class)
+    public static interface FeedExceptionEntity extends Entity {
+        ConfigKey<ThrowingPoller> POLLER = ConfigKeys.newConfigKey(ThrowingPoller.class, "poller");
+        AttributeSensor<Boolean> FLAG = Sensors.newBooleanSensor("flag");
+
+        void startThrowingPollExceptions();
+        void stopThrowingPollExceptions();
+    }
+
+    public static class FeedExceptionEntityImpl extends AbstractEntity implements FeedExceptionEntity {
+        private ThrowingPoller poller;
+
+        @Override
+        public void init() {
+            super.init();
+            poller = config().get(POLLER);
+            FunctionFeed.builder()
+                    .entity(this)
+                    .period(1L)
+                    .poll(new FunctionPollConfig<Boolean, Boolean>(FLAG)
+                            .callable(poller)
+                            .onException(Functions.constant(false)))
+                    .build();
+        }
+
+        public void startThrowingPollExceptions() {
+            this.poller.setShouldThrow(true);
+        }
+
+        public void stopThrowingPollExceptions() {
+            this.poller.setShouldThrow(false);
+        }
     }
-    
-    @Test(groups={"Integration", "WIP"}) // because takes > 1 second
-    public void testPollingSubTaskFailsOnceKeepsGoing() throws Exception {
-        final AtomicInteger counter = new AtomicInteger();
-        poller.scheduleAtFixedRate(
-                new Callable<Integer>() {
-                    @Override public Integer call() throws Exception {
-                        int result = counter.incrementAndGet();
-                        if (result % 2 == 0) {
-                            DynamicTasks.queue("in-poll", new Runnable() {
-                                public void run() {
-                                    throw new IllegalStateException("Simulating error in sub-task for poll");
-                                }});
+
+    private static class TaskFailer extends ThrowingPoller {
+        public Boolean execute(final boolean shouldThrow) {
+            Task<Boolean> t = Tasks.<Boolean>builder()
+                    .body(new Callable<Boolean>() {
+                        @Override
+                        public Boolean call() {
+                            if (shouldThrow) {
+                                throw new IllegalArgumentException("exception in feed task");
+                            }
+                            return true;
                         }
-                        return result;
-                    }
-                },
-                new PollHandler<Integer>() {
-                    @Override public boolean checkSuccess(Integer val) {
-                        return true;
-                    }
-                    @Override public void onSuccess(Integer val) {
-                        
-                    }
-                    @Override public void onFailure(Integer val) {
-                    }
-                    @Override
-                    public void onException(Exception exception) {
-                        LOG.info("Exception in test poller", exception);
-                    }
-                    @Override public String getDescription() {
-                        return "mypollhandler";
-                    }
-                }, 
-                new Duration(10, TimeUnit.MILLISECONDS));
-        poller.start();
-        
-        Asserts.succeedsContinually(MutableMap.of("timeout", 2*1000, "period", 500), new Runnable() {
-            int oldCounter = -1;
-            @Override public void run() {
-                assertTrue(counter.get() > oldCounter);
-                oldCounter = counter.get();
+                    })
+                    .build();
+            return DynamicTasks.queueIfPossible(t).orSubmitAsync().asTask().getUnchecked();
+        }
+    }
+
+    private static class PollFailer extends ThrowingPoller {
+        public Boolean execute(final boolean shouldThrow) {
+            if (shouldThrow) {
+                throw new IllegalArgumentException("exception in poller");
+            }
+            return true;
+        }
+    }
+
+    private static abstract class ThrowingPoller implements Callable<Boolean> {
+        protected final Object throwLock = new Object[0];
+        boolean shouldThrow = false;
+
+        abstract Boolean execute(boolean shouldThrow);
+
+        @Override
+        public Boolean call() throws Exception {
+            synchronized (throwLock) {
+                return execute(shouldThrow);
             }
-        });
+        }
+
+        public void setShouldThrow(boolean shouldThrow) {
+            synchronized (throwLock) {
+                this.shouldThrow = shouldThrow;
+            }
+        }
     }
+
 }


[5/5] incubator-brooklyn git commit: This closes #1043

Posted by sj...@apache.org.
This closes #1043


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

Branch: refs/heads/master
Commit: cf286fea07c8e8df77130971c5e937a291dcbcf0
Parents: d8822bd 5832a15
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Thu Nov 19 14:36:16 2015 +0000
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Thu Nov 19 14:36:16 2015 +0000

----------------------------------------------------------------------
 .../org/apache/brooklyn/core/feed/Poller.java   |   9 +-
 .../util/core/task/BasicExecutionManager.java   |  50 +++--
 .../brooklyn/util/core/task/ScheduledTask.java  |  54 ++++--
 .../apache/brooklyn/core/feed/PollerTest.java   | 191 ++++++++++++-------
 .../util/core/task/ScheduledExecutionTest.java  |  48 ++++-
 .../webapp/assets/js/view/entity-details.js     |   2 +-
 .../jsgui/BrooklynJavascriptGuiLauncher.java    |   2 +-
 7 files changed, 250 insertions(+), 106 deletions(-)
----------------------------------------------------------------------



[3/5] incubator-brooklyn git commit: Adds cancelOnException to ScheduledTask

Posted by sj...@apache.org.
Adds cancelOnException to ScheduledTask


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

Branch: refs/heads/master
Commit: e0014b14062ce40fd0269ea5c362a707240ab324
Parents: 26773c0
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Wed Nov 18 12:47:44 2015 +0000
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Thu Nov 19 14:01:52 2015 +0000

----------------------------------------------------------------------
 .../util/core/task/BasicExecutionManager.java   | 50 +++++++++++++-----
 .../brooklyn/util/core/task/ScheduledTask.java  | 54 +++++++++++++++-----
 .../util/core/task/ScheduledExecutionTest.java  | 48 +++++++++++++++--
 3 files changed, 123 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e0014b14/core/src/main/java/org/apache/brooklyn/util/core/task/BasicExecutionManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/task/BasicExecutionManager.java b/core/src/main/java/org/apache/brooklyn/util/core/task/BasicExecutionManager.java
index 4c9858a..02277a1 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/task/BasicExecutionManager.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/task/BasicExecutionManager.java
@@ -398,7 +398,7 @@ public class BasicExecutionManager implements ExecutionManager {
                 final Callable<?> oldJob = taskScheduled.getJob();
                 final TaskInternal<?> taskScheduledF = taskScheduled;
                 taskScheduled.setJob(new Callable() { public Object call() {
-                    boolean resubmitted = false;
+                    boolean shouldResubmit = true;
                     task.recentRun = taskScheduledF;
                     try {
                         synchronized (task) {
@@ -407,25 +407,19 @@ public class BasicExecutionManager implements ExecutionManager {
                         Object result;
                         try {
                             result = oldJob.call();
+                            task.lastThrownType = null;
                         } catch (Exception e) {
-                            if (!Tasks.isInterrupted()) {
-                                log.warn("Error executing "+oldJob+" (scheduled job of "+task+" - "+task.getDescription()+"); cancelling scheduled execution", e);
-                            } else {
-                                log.debug("Interrupted executing "+oldJob+" (scheduled job of "+task+" - "+task.getDescription()+"); cancelling scheduled execution: "+e);
-                            }
+                            shouldResubmit = shouldResubmitOnException(oldJob, e);
                             throw Exceptions.propagate(e);
                         }
-                        task.runCount++;
-                        if (task.period!=null && !task.isCancelled()) {
-                            task.delay = task.period;
-                            submitSubsequentScheduledTask(flags, task);
-                            resubmitted = true;
-                        }
                         return result;
                     } finally {
                         // do in finally block in case we were interrupted
-                        if (!resubmitted)
+                        if (shouldResubmit) {
+                            resubmit();
+                        } else {
                             afterEndScheduledTaskAllIterations(flags, task);
+                        }
                     }
                 }});
                 task.nextRun = taskScheduled;
@@ -437,6 +431,36 @@ public class BasicExecutionManager implements ExecutionManager {
             }
         }
 
+        private void resubmit() {
+            task.runCount++;
+            if (task.period!=null && !task.isCancelled()) {
+                task.delay = task.period;
+                submitSubsequentScheduledTask(flags, task);
+            }
+        }
+
+        private boolean shouldResubmitOnException(Callable<?> oldJob, Exception e) {
+            String message = "Error executing " + oldJob + " (scheduled job of " + task + " - " + task.getDescription() + ")";
+            if (Tasks.isInterrupted()) {
+                log.debug(message + "; cancelling scheduled execution: " + e);
+                return false;
+            } else if (task.cancelOnException) {
+                log.warn(message + "; cancelling scheduled execution.", e);
+                return false;
+            } else {
+                message += "; resubmitting task and throwing: " + e;
+                if (!e.getClass().equals(task.lastThrownType)) {
+                    task.lastThrownType = e.getClass();
+                    message += " (logging subsequent exceptions at trace)";
+                    log.debug(message);
+                } else {
+                    message += " (repeat exception)";
+                    log.trace(message);
+                }
+                return true;
+            }
+        }
+
         @Override
         public String toString() {
             return "ScheduledTaskCallable["+task+","+flags+"]";

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e0014b14/core/src/main/java/org/apache/brooklyn/util/core/task/ScheduledTask.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/task/ScheduledTask.java b/core/src/main/java/org/apache/brooklyn/util/core/task/ScheduledTask.java
index 94327a1..c1ad4f8 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/task/ScheduledTask.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/task/ScheduledTask.java
@@ -46,17 +46,32 @@ import com.google.common.base.Throwables;
 public class ScheduledTask extends BasicTask {
     
     final Callable<Task<?>> taskFactory;
-    /** initial delay before running, set as flag in constructor; defaults to 0 */
+
+    /**
+     * Initial delay before running, set as flag in constructor; defaults to 0
+     */
     protected Duration delay;
-    /** time to wait between executions, or null if not to repeat (default), set as flag to constructor;
+
+    /**
+     * The time to wait between executions, or null if not to repeat (default), set as flag to constructor;
      * this may be modified for subsequent submissions by a running task generated by the factory 
-     * using getSubmittedByTask().setPeriod(Duration) */
+     * using {@link #getSubmittedByTask().setPeriod(Duration)}
+     */
     protected Duration period = null;
-    /** optional, set as flag in constructor; defaults to null meaning no limit */
+
+    /**
+     * Optional, set as flag in constructor; defaults to null meaning no limit.
+     */
     protected Integer maxIterations = null;
-    
+
+    /**
+     * Set false if the task should be rescheduled after throwing an exception; defaults to true.
+     */
+    protected boolean cancelOnException = true;
+
     protected int runCount=0;
     protected Task<?> recentRun, nextRun;
+    Class<? extends Exception> lastThrownType;
 
     public int getRunCount() { return runCount; }
     public ScheduledFuture<?> getNextScheduled() { return (ScheduledFuture<?>)internalFuture; }
@@ -84,12 +99,15 @@ public class ScheduledTask extends BasicTask {
         delay = Duration.of(elvis(flags.remove("delay"), 0));
         period = Duration.of(elvis(flags.remove("period"), null));
         maxIterations = elvis(flags.remove("maxIterations"), null);
+        Object cancelFlag = flags.remove("cancelOnException");
+        cancelOnException = cancelFlag == null || Boolean.TRUE.equals(cancelFlag);
     }
     
     public ScheduledTask delay(Duration d) {
         this.delay = d;
         return this;
     }
+
     public ScheduledTask delay(long val) {
         return delay(Duration.millis(val));
     }
@@ -98,6 +116,7 @@ public class ScheduledTask extends BasicTask {
         this.period = d;
         return this;
     }
+
     public ScheduledTask period(long val) {
         return period(Duration.millis(val));
     }
@@ -107,6 +126,11 @@ public class ScheduledTask extends BasicTask {
         return this;
     }
 
+    public ScheduledTask cancelOnException(boolean cancel) {
+        this.cancelOnException = cancel;
+        return this;
+    }
+
     public Callable<Task<?>> getTaskFactory() {
         return taskFactory;
     }
@@ -121,13 +145,17 @@ public class ScheduledTask extends BasicTask {
     
     protected String getActiveTaskStatusString(int verbosity) {
         StringBuilder rv = new StringBuilder("Scheduler");
-        if (runCount>0) rv.append(", iteration "+(runCount+1));
-        if (recentRun!=null) rv.append(", last run "+
-            Duration.sinceUtc(recentRun.getStartTimeUtc())+" ms ago");
+        if (runCount > 0) {
+            rv.append(", iteration ").append(runCount + 1);
+        }
+        if (recentRun != null) {
+            Duration start = Duration.sinceUtc(recentRun.getStartTimeUtc());
+            rv.append(", last run ").append(start).append(" ago");
+        }
         if (truth(getNextScheduled())) {
             Duration untilNext = Duration.millis(getNextScheduled().getDelay(TimeUnit.MILLISECONDS));
             if (untilNext.isPositive())
-                rv.append(", next in "+untilNext);
+                rv.append(", next in ").append(untilNext);
             else 
                 rv.append(", next imminent");
         }
@@ -158,7 +186,7 @@ public class ScheduledTask extends BasicTask {
         while (!isDone()) super.blockUntilEnded();
     }
 
-    /** gets the value of the most recently run task */
+    /** @return The value of the most recently run task */
     public Object get() throws InterruptedException, ExecutionException {
         blockUntilStarted();
         blockUntilFirstScheduleStarted();
@@ -175,8 +203,10 @@ public class ScheduledTask extends BasicTask {
         return result;
     }
     
-    /** internal method used to allow callers to wait for underlying tasks to finished in the case of cancellation 
-     * @param duration */ 
+    /**
+     * Internal method used to allow callers to wait for underlying tasks to finished in the case of cancellation.
+     * @param timeout maximum time to wait
+     */
     @Beta
     public boolean blockUntilNextRunFinished(Duration timeout) {
         return Tasks.blockUntilInternalTasksEnded(nextRun, timeout);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e0014b14/core/src/test/java/org/apache/brooklyn/util/core/task/ScheduledExecutionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/util/core/task/ScheduledExecutionTest.java b/core/src/test/java/org/apache/brooklyn/util/core/task/ScheduledExecutionTest.java
index 6884040..1d551e8 100644
--- a/core/src/test/java/org/apache/brooklyn/util/core/task/ScheduledExecutionTest.java
+++ b/core/src/test/java/org/apache/brooklyn/util/core/task/ScheduledExecutionTest.java
@@ -32,10 +32,6 @@ import java.util.concurrent.atomic.AtomicInteger;
 import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.test.Asserts;
 import org.apache.brooklyn.util.collections.MutableMap;
-import org.apache.brooklyn.util.core.task.BasicExecutionManager;
-import org.apache.brooklyn.util.core.task.BasicTask;
-import org.apache.brooklyn.util.core.task.ScheduledTask;
-import org.apache.brooklyn.util.core.task.Tasks;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.exceptions.RuntimeInterruptedException;
 import org.apache.brooklyn.util.javalang.JavaClassNames;
@@ -81,6 +77,50 @@ public class ScheduledExecutionTest {
         assertEquals(i.get(), 5);
     }
 
+    @Test
+    public void testScheduledTaskCancelledIfExceptionThrown() throws Exception {
+        BasicExecutionManager m = new BasicExecutionManager("mycontextid");
+        final AtomicInteger calls = new AtomicInteger(0);
+        ScheduledTask t = new ScheduledTask(MutableMap.of("period", Duration.ONE_MILLISECOND, "maxIterations", 5), new Callable<Task<?>>() {
+            public Task<?> call() throws Exception {
+                return new BasicTask<>(new Callable<Integer>() {
+                    public Integer call() {
+                        calls.incrementAndGet();
+                        throw new RuntimeException("boo");
+                    }});
+            }});
+
+        m.submit(t);
+        Runnable callsIsOne = new Runnable() {
+            @Override public void run() {
+                if (calls.get() != 1) {
+                    throw new RuntimeException("not yet");
+                }
+            }
+
+        };
+        Asserts.succeedsEventually(callsIsOne);
+        Asserts.succeedsContinually(callsIsOne);
+    }
+
+    @Test
+    public void testScheduledTaskResubmittedIfExceptionThrownAndCancelOnExceptionFalse() {
+        BasicExecutionManager m = new BasicExecutionManager("mycontextid");
+        final AtomicInteger calls = new AtomicInteger(0);
+        ScheduledTask t = new ScheduledTask(MutableMap.of("period", Duration.ONE_MILLISECOND, "maxIterations", 5, "cancelOnException", false), new Callable<Task<?>>() {
+            public Task<?> call() throws Exception {
+                return new BasicTask<>(new Callable<Integer>() {
+                    public Integer call() {
+                        calls.incrementAndGet();
+                        throw new RuntimeException("boo");
+                    }});
+            }});
+
+        m.submit(t);
+        t.blockUntilEnded();
+        assertEquals(calls.get(), 5, "Expected task to be resubmitted despite throwing an exception");
+    }
+
     /** like testScheduledTask but the loop is terminated by the task itself adjusting the period */
     @Test
     public void testScheduledTaskSelfEnding() throws Exception {


[2/5] incubator-brooklyn git commit: Closing ] in jquery selector

Posted by sj...@apache.org.
Closing ] in jquery selector


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

Branch: refs/heads/master
Commit: 26773c0d735612c3a994b292423c107801ade37d
Parents: 0f777c5
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Wed Nov 18 12:46:56 2015 +0000
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Thu Nov 19 13:58:59 2015 +0000

----------------------------------------------------------------------
 usage/jsgui/src/main/webapp/assets/js/view/entity-details.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/26773c0d/usage/jsgui/src/main/webapp/assets/js/view/entity-details.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/view/entity-details.js b/usage/jsgui/src/main/webapp/assets/js/view/entity-details.js
index 7d65458..f54c572 100644
--- a/usage/jsgui/src/main/webapp/assets/js/view/entity-details.js
+++ b/usage/jsgui/src/main/webapp/assets/js/view/entity-details.js
@@ -103,7 +103,7 @@ define([
             }
             var entityHref = this.getEntityHref();
             if (entityHref) {
-                $("a[data-toggle='tab'").each(function(i,a) {
+                $("a[data-toggle='tab']").each(function(i,a) {
                     $(a).attr('href',entityHref+"/"+$(a).attr("data-target").slice(1));
                 });
             } else {