From e60cf77a04b3d3df897aba95e9fcae482f93bb58 Mon Sep 17 00:00:00 2001 From: Janne Valkealahti Date: Wed, 4 May 2016 19:48:05 +0100 Subject: [PATCH] TimerTrigger with delay fires immediately - Fix use of correct delay. - Move CountTrigger to support package as it's a generic class. - Fixes #220 --- .../{state => support}/CountTrigger.java | 17 ++++++++++++++++- .../statemachine/trigger/TimerTrigger.java | 5 +++-- .../statemachine/trigger/TimerTriggerTests.java | 12 ++++++++++-- 3 files changed, 29 insertions(+), 5 deletions(-) rename spring-statemachine-core/src/main/java/org/springframework/statemachine/{state => support}/CountTrigger.java (87%) diff --git a/spring-statemachine-core/src/main/java/org/springframework/statemachine/state/CountTrigger.java b/spring-statemachine-core/src/main/java/org/springframework/statemachine/support/CountTrigger.java similarity index 87% rename from spring-statemachine-core/src/main/java/org/springframework/statemachine/state/CountTrigger.java rename to spring-statemachine-core/src/main/java/org/springframework/statemachine/support/CountTrigger.java index dd3e8b97..491901fc 100644 --- a/spring-statemachine-core/src/main/java/org/springframework/statemachine/state/CountTrigger.java +++ b/spring-statemachine-core/src/main/java/org/springframework/statemachine/support/CountTrigger.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.statemachine.state; +package org.springframework.statemachine.support; import java.util.Date; import java.util.concurrent.TimeUnit; @@ -60,11 +60,26 @@ public class CountTrigger implements Trigger { * @param timeUnit the time unit */ public CountTrigger(int count, long period, TimeUnit timeUnit) { + this(count, period, 0, timeUnit); + } + + /** + * Create a trigger with the given count, period and time unit. The time unit will + * apply not only to the period but also to any 'initialDelay' value, if + * configured on this Trigger later via {@link #setInitialDelay(long)}. + * + * @param count the count + * @param period the period + * @param timeUnit the time unit + * @param initialDelay the initial delay + */ + public CountTrigger(int count, long period, long initialDelay, TimeUnit timeUnit) { Assert.isTrue(period >= 0, "period must not be negative"); Assert.isTrue(count >= 0, "count must not be negative"); this.timeUnit = (timeUnit != null ? timeUnit : TimeUnit.MILLISECONDS); this.period = this.timeUnit.toMillis(period); this.count = count; + setInitialDelay(initialDelay); } /** diff --git a/spring-statemachine-core/src/main/java/org/springframework/statemachine/trigger/TimerTrigger.java b/spring-statemachine-core/src/main/java/org/springframework/statemachine/trigger/TimerTrigger.java index 9deefd99..37b53eac 100644 --- a/spring-statemachine-core/src/main/java/org/springframework/statemachine/trigger/TimerTrigger.java +++ b/spring-statemachine-core/src/main/java/org/springframework/statemachine/trigger/TimerTrigger.java @@ -18,7 +18,7 @@ package org.springframework.statemachine.trigger; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import org.springframework.statemachine.state.CountTrigger; +import org.springframework.statemachine.support.CountTrigger; import org.springframework.statemachine.support.LifecycleObjectSupport; /** @@ -101,13 +101,14 @@ public class TimerTrigger extends LifecycleObjectSupport implements Trigge } private void schedule() { + long initialDelay = count > 0 ? period : 0; scheduled = getTaskScheduler().schedule(new Runnable() { @Override public void run() { notifyTriggered(); } - }, new CountTrigger(count, period, TimeUnit.MILLISECONDS)); + }, new CountTrigger(count, period, initialDelay, TimeUnit.MILLISECONDS)); } private void notifyTriggered() { diff --git a/spring-statemachine-core/src/test/java/org/springframework/statemachine/trigger/TimerTriggerTests.java b/spring-statemachine-core/src/test/java/org/springframework/statemachine/trigger/TimerTriggerTests.java index 2e91e31a..69b00497 100644 --- a/spring-statemachine-core/src/test/java/org/springframework/statemachine/trigger/TimerTriggerTests.java +++ b/spring-statemachine-core/src/test/java/org/springframework/statemachine/trigger/TimerTriggerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2015-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext; @@ -125,10 +126,12 @@ public class TimerTriggerTests extends AbstractStateMachineTests { private class TestTriggerListener implements TriggerListener { + AtomicInteger count = new AtomicInteger(); CountDownLatch latch = new CountDownLatch(1); @Override public void triggered() { + count.incrementAndGet(); latch.countDown(); } } @@ -167,6 +170,11 @@ public class TimerTriggerTests extends AbstractStateMachineTests { assertThat(listener.stateChangedCount, is(1)); assertThat(machine.getState().getIds(), containsInAnyOrder(TestStates.S2)); + assertThat(tlistener.latch.await(1, TimeUnit.SECONDS), is(false)); + assertThat(tlistener.count.get(), is(0)); + assertThat(tlistener.latch.await(4, TimeUnit.SECONDS), is(true)); + assertThat(tlistener.count.get(), is(1)); + assertThat(action.latch.await(2, TimeUnit.SECONDS), is(true)); action.reset(1); assertThat(action.latch.await(2, TimeUnit.SECONDS), is(false)); @@ -287,7 +295,7 @@ public class TimerTriggerTests extends AbstractStateMachineTests { .withInternal() .source(TestStates.S2) .action(testTimerAction()) - .timerOnce(1000); + .timerOnce(3000); } @Bean