Add ref docs for error handling
- Base docs for error handling and some tests to verify added doc samples. - Relates to #88
This commit is contained in:
@@ -310,5 +310,8 @@ in a state machine.
|
||||
This appendix provides more detailed technical documentation about
|
||||
using a Zookeeper with a Spring State Machine.
|
||||
|
||||
tbd.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
This article is not complete as it requires jepsen tests which are
|
||||
planned for next release.
|
||||
====
|
||||
|
||||
@@ -609,6 +609,52 @@ exposed directly via `StateMachine` interface.
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetZH]
|
||||
----
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
More about error handling shown in above example, see section
|
||||
<<sm-error-handling>>.
|
||||
====
|
||||
|
||||
[[sm-error-handling]]
|
||||
== State Machine Error Handling
|
||||
If state machine detects an internal error during a state transition
|
||||
logic it may throw an exception. Before this exception is processed
|
||||
internally, user is given a change to intercept.
|
||||
|
||||
Normal `StateMachineInterceptor` can be used to intercept errors and
|
||||
example of it is shown above.
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippet1]
|
||||
----
|
||||
|
||||
When errors are detected, normal event notify mechanism is executed.
|
||||
This allows to use either `StateMachineListener` or Spring Application
|
||||
context event listener, more about these read section
|
||||
<<sm-listeners>>.
|
||||
|
||||
Having said that, a simple listener would look like:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippet2]
|
||||
----
|
||||
|
||||
Generic `ApplicationListener` checking `StateMachineEvent` would look
|
||||
like.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippet3]
|
||||
----
|
||||
|
||||
It's also possible to define `ApplicationListener` directly to
|
||||
recognize only `StateMachineEvent` instances.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippet4]
|
||||
----
|
||||
|
||||
[[sm-persist]]
|
||||
== Persisting State Machine
|
||||
|
||||
@@ -56,7 +56,8 @@ public class StateMachineErrorTests extends AbstractStateMachineTests {
|
||||
context.register(Config.class, Config1.class);
|
||||
context.refresh();
|
||||
|
||||
TestApplicationEventListener listener1 = context.getBean(TestApplicationEventListener.class);
|
||||
TestApplicationEventListener1 listener1 = context.getBean(TestApplicationEventListener1.class);
|
||||
TestApplicationEventListener2 listener3 = context.getBean(TestApplicationEventListener2.class);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectStateMachine<TestStates,TestEvents> machine =
|
||||
@@ -72,6 +73,8 @@ public class StateMachineErrorTests extends AbstractStateMachineTests {
|
||||
|
||||
assertThat(listener1.latch.await(1, TimeUnit.SECONDS), is(true));
|
||||
assertThat(listener1.count, is(1));
|
||||
assertThat(listener3.latch.await(1, TimeUnit.SECONDS), is(true));
|
||||
assertThat(listener3.count, is(1));
|
||||
assertThat(listener2.latch.await(1, TimeUnit.SECONDS), is(true));
|
||||
assertThat(listener2.count, is(1));
|
||||
assertThat(machine.hasStateMachineError(), is(true));
|
||||
@@ -82,7 +85,7 @@ public class StateMachineErrorTests extends AbstractStateMachineTests {
|
||||
context.register(Config.class, Config1.class);
|
||||
context.refresh();
|
||||
|
||||
TestApplicationEventListener listener1 = context.getBean(TestApplicationEventListener.class);
|
||||
TestApplicationEventListener1 listener1 = context.getBean(TestApplicationEventListener1.class);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectStateMachine<TestStates,TestEvents> machine =
|
||||
@@ -180,8 +183,13 @@ public class StateMachineErrorTests extends AbstractStateMachineTests {
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
public TestApplicationEventListener testApplicationEventListener() {
|
||||
return new TestApplicationEventListener();
|
||||
public TestApplicationEventListener1 testApplicationEventListener1() {
|
||||
return new TestApplicationEventListener1();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TestApplicationEventListener2 testApplicationEventListener2() {
|
||||
return new TestApplicationEventListener2();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,7 +205,7 @@ public class StateMachineErrorTests extends AbstractStateMachineTests {
|
||||
}
|
||||
}
|
||||
|
||||
static class TestApplicationEventListener implements ApplicationListener<StateMachineEvent> {
|
||||
static class TestApplicationEventListener1 implements ApplicationListener<StateMachineEvent> {
|
||||
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
int count = 0;
|
||||
@@ -211,4 +219,17 @@ public class StateMachineErrorTests extends AbstractStateMachineTests {
|
||||
}
|
||||
}
|
||||
|
||||
static class TestApplicationEventListener2 implements ApplicationListener<OnStateMachineError> {
|
||||
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
int count = 0;
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(OnStateMachineError event) {
|
||||
count++;
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -56,11 +56,13 @@ import org.springframework.statemachine.config.builders.StateMachineStateConfigu
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
|
||||
import org.springframework.statemachine.config.configurers.StateConfigurer.History;
|
||||
import org.springframework.statemachine.ensemble.StateMachineEnsemble;
|
||||
import org.springframework.statemachine.event.OnStateMachineError;
|
||||
import org.springframework.statemachine.event.StateMachineEvent;
|
||||
import org.springframework.statemachine.guard.Guard;
|
||||
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
|
||||
import org.springframework.statemachine.state.State;
|
||||
import org.springframework.statemachine.support.StateMachineInterceptor;
|
||||
import org.springframework.statemachine.support.StateMachineInterceptorAdapter;
|
||||
import org.springframework.statemachine.transition.Transition;
|
||||
|
||||
/**
|
||||
@@ -878,4 +880,67 @@ public class DocsConfigurationSampleTests extends AbstractStateMachineTests {
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class InterceptorAddExample {
|
||||
|
||||
// tag::snippet1[]
|
||||
StateMachine<String, String> stateMachine;
|
||||
|
||||
void addInterceptor() {
|
||||
stateMachine.getStateMachineAccessor()
|
||||
.doWithRegion(new StateMachineFunction<StateMachineAccess<String, String>>() {
|
||||
|
||||
@Override
|
||||
public void apply(StateMachineAccess<String, String> function) {
|
||||
function.addStateMachineInterceptor(
|
||||
new StateMachineInterceptorAdapter<String, String>() {
|
||||
@Override
|
||||
public Exception stateMachineError(StateMachine<String, String> stateMachine,
|
||||
Exception exception) {
|
||||
// return null indicating handled error
|
||||
return exception;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
// end::snippet1[]
|
||||
}
|
||||
|
||||
// tag::snippet2[]
|
||||
public static class ErrorStateMachineListener
|
||||
extends StateMachineListenerAdapter<String, String> {
|
||||
|
||||
@Override
|
||||
public void stateMachineError(StateMachine<String, String> stateMachine, Exception exception) {
|
||||
// do something with error
|
||||
}
|
||||
}
|
||||
// end::snippet2[]
|
||||
|
||||
// tag::snippet3[]
|
||||
public static class GenericApplicationEventListener
|
||||
implements ApplicationListener<StateMachineEvent> {
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(StateMachineEvent event) {
|
||||
if (event instanceof OnStateMachineError) {
|
||||
// do something with error
|
||||
}
|
||||
}
|
||||
}
|
||||
// end::snippet3[]
|
||||
|
||||
// tag::snippet4[]
|
||||
public static class ErrorApplicationEventListener
|
||||
implements ApplicationListener<OnStateMachineError> {
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(OnStateMachineError event) {
|
||||
// do something with error
|
||||
}
|
||||
}
|
||||
// end::snippet4[]
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user