Use references in RepositoryTransition
- Refactor so that we can create RepositoryState in one place and then reference to it from JpaRepositoryTransition impls. - New common top class BaseRepositoryEntity for entities - Change RepositoryState and RepositoryTransition to be abstract classes instead of interfaces. - New custom StateMachineJackson2RepositoryPopulatorFactoryBean and StateMachineJackson2ResourceReader handling json refs. - Relates to #262
This commit is contained in:
@@ -199,6 +199,8 @@ project('spring-statemachine-data-common') {
|
||||
compile project(":spring-statemachine-core")
|
||||
compile "org.springframework.data:spring-data-commons:$springDataCommonsVersion"
|
||||
optional "org.springframework.security:spring-security-core:$springSecurityVersion"
|
||||
compile "com.fasterxml.jackson.core:jackson-core:$jackson2Version"
|
||||
compile "com.fasterxml.jackson.core:jackson-databind:$jackson2Version"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
[
|
||||
{
|
||||
"@id": "1",
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState",
|
||||
"initial": true,
|
||||
"state": "S1",
|
||||
@@ -11,6 +12,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"@id": "2",
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState",
|
||||
"initial": false,
|
||||
"state": "S2",
|
||||
@@ -22,6 +24,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"@id": "3",
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState",
|
||||
"initial": false,
|
||||
"state": "S3",
|
||||
@@ -34,15 +37,15 @@
|
||||
},
|
||||
{
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryTransition",
|
||||
"source": "S1",
|
||||
"target": "S2",
|
||||
"source": "1",
|
||||
"target": "2",
|
||||
"event": "E1",
|
||||
"kind": "EXTERNAL"
|
||||
},
|
||||
{
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryTransition",
|
||||
"source": "S2",
|
||||
"target": "S3",
|
||||
"source": "2",
|
||||
"target": "3",
|
||||
"event": "E2",
|
||||
"actions": [
|
||||
{
|
||||
|
||||
@@ -26,4 +26,5 @@ eclipseUml2CommonVersion=2.0.0-v20140602-0749
|
||||
eclipseEmfXmiVersion=2.11.1-v20150805-0538
|
||||
eclipseEmfEcoreVersion=2.11.1-v20150805-0538
|
||||
eclipseEmfCommonVersion=2.11.0-v20150805-0538
|
||||
|
||||
jackson2Version=2.8.3
|
||||
eclipsePersistenceVersion=2.1.1
|
||||
|
||||
@@ -5,10 +5,11 @@ project('spring-statemachine-data-jpa') {
|
||||
dependencies {
|
||||
compile project(":spring-statemachine-data-common")
|
||||
compile "org.springframework:spring-orm:$springVersion"
|
||||
optional "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
|
||||
testCompile project(":spring-statemachine-test")
|
||||
optional "org.eclipse.persistence:javax.persistence:$eclipsePersistenceVersion"
|
||||
testCompile "org.hsqldb:hsqldb:$hsqlVersion"
|
||||
testCompile "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
|
||||
testRuntime "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
|
||||
testRuntime "org.springframework.boot:spring-boot-starter-web:$springBootVersion"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,9 @@ import javax.persistence.OneToMany;
|
||||
|
||||
import org.springframework.statemachine.data.RepositoryState;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
|
||||
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
|
||||
|
||||
/**
|
||||
* JPA entity for states.
|
||||
*
|
||||
@@ -34,7 +37,8 @@ import org.springframework.statemachine.data.RepositoryState;
|
||||
*
|
||||
*/
|
||||
@Entity
|
||||
public class JpaRepositoryState implements RepositoryState {
|
||||
@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class)
|
||||
public class JpaRepositoryState extends RepositoryState {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
@@ -186,4 +190,11 @@ public class JpaRepositoryState implements RepositoryState {
|
||||
public void setExitActions(Set<JpaRepositoryAction> exitActions) {
|
||||
this.exitActions = exitActions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "JpaRepositoryState [id=" + id + ", machineId=" + machineId + ", parentState=" + parentState + ", state=" + state
|
||||
+ ", initial=" + initial + ", stateActions=" + stateActions + ", entryActions=" + entryActions + ", exitActions="
|
||||
+ exitActions + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,9 @@ import javax.persistence.OneToOne;
|
||||
import org.springframework.statemachine.data.RepositoryTransition;
|
||||
import org.springframework.statemachine.transition.TransitionKind;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
|
||||
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
|
||||
|
||||
/**
|
||||
* JPA entity for transitions.
|
||||
*
|
||||
@@ -36,15 +39,21 @@ import org.springframework.statemachine.transition.TransitionKind;
|
||||
*
|
||||
*/
|
||||
@Entity
|
||||
public class JpaRepositoryTransition implements RepositoryTransition {
|
||||
@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class)
|
||||
public class JpaRepositoryTransition extends RepositoryTransition {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private long id;
|
||||
|
||||
private String machineId;
|
||||
private String source;
|
||||
private String target;
|
||||
|
||||
@OneToOne(fetch = FetchType.EAGER)
|
||||
private JpaRepositoryState source;
|
||||
|
||||
@OneToOne(fetch = FetchType.EAGER)
|
||||
private JpaRepositoryState target;
|
||||
|
||||
private String event;
|
||||
private TransitionKind kind;
|
||||
|
||||
@@ -68,7 +77,7 @@ public class JpaRepositoryTransition implements RepositoryTransition {
|
||||
* @param target the target
|
||||
* @param event the event
|
||||
*/
|
||||
public JpaRepositoryTransition(String source, String target, String event) {
|
||||
public JpaRepositoryTransition(JpaRepositoryState source, JpaRepositoryState target, String event) {
|
||||
this(null, source, target, event);
|
||||
}
|
||||
|
||||
@@ -80,7 +89,7 @@ public class JpaRepositoryTransition implements RepositoryTransition {
|
||||
* @param target the target
|
||||
* @param event the event
|
||||
*/
|
||||
public JpaRepositoryTransition(String machineId, String source, String target, String event) {
|
||||
public JpaRepositoryTransition(String machineId, JpaRepositoryState source, JpaRepositoryState target, String event) {
|
||||
this(machineId, source, target, event, null);
|
||||
}
|
||||
|
||||
@@ -93,7 +102,7 @@ public class JpaRepositoryTransition implements RepositoryTransition {
|
||||
* @param event the event
|
||||
* @param actions the actions
|
||||
*/
|
||||
public JpaRepositoryTransition(String machineId, String source, String target, String event, Set<JpaRepositoryAction> actions) {
|
||||
public JpaRepositoryTransition(String machineId, JpaRepositoryState source, JpaRepositoryState target, String event, Set<JpaRepositoryAction> actions) {
|
||||
this.machineId = machineId;
|
||||
this.source = source;
|
||||
this.target = target;
|
||||
@@ -111,20 +120,20 @@ public class JpaRepositoryTransition implements RepositoryTransition {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSource() {
|
||||
public JpaRepositoryState getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
public void setSource(String source) {
|
||||
public void setSource(JpaRepositoryState source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTarget() {
|
||||
public JpaRepositoryState getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
public void setTarget(String target) {
|
||||
public void setTarget(JpaRepositoryState target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@@ -163,4 +172,10 @@ public class JpaRepositoryTransition implements RepositoryTransition {
|
||||
public void setKind(TransitionKind kind) {
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "JpaRepositoryTransition [id=" + id + ", machineId=" + machineId + ", source=" + source + ", target=" + target + ", event="
|
||||
+ event + ", kind=" + kind + ", actions=" + actions + ", guard=" + guard + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.data.repository.init.Jackson2RepositoryPopulatorFactoryBean;
|
||||
import org.springframework.statemachine.StateMachine;
|
||||
import org.springframework.statemachine.config.EnableStateMachineFactory;
|
||||
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
|
||||
@@ -43,6 +42,7 @@ import org.springframework.statemachine.data.RepositoryStateMachineModelFactory;
|
||||
import org.springframework.statemachine.data.RepositoryTransition;
|
||||
import org.springframework.statemachine.data.StateRepository;
|
||||
import org.springframework.statemachine.data.TransitionRepository;
|
||||
import org.springframework.statemachine.data.support.StateMachineJackson2RepositoryPopulatorFactoryBean;
|
||||
import org.springframework.statemachine.test.StateMachineTestPlan;
|
||||
import org.springframework.statemachine.test.StateMachineTestPlanBuilder;
|
||||
import org.springframework.statemachine.transition.TransitionKind;
|
||||
@@ -60,18 +60,24 @@ public class JpaRepositoryTests extends AbstractJpaRepositoryTests {
|
||||
context.refresh();
|
||||
|
||||
JpaStateRepository statesRepository = context.getBean(JpaStateRepository.class);
|
||||
JpaRepositoryState state = new JpaRepositoryState("S1");
|
||||
statesRepository.save(state);
|
||||
Iterable<JpaRepositoryState> findAll = statesRepository.findAll();
|
||||
assertThat(findAll.iterator().next().getState(), is("S1"));
|
||||
JpaRepositoryState stateS1 = new JpaRepositoryState("S1");
|
||||
JpaRepositoryState stateS2 = new JpaRepositoryState("S2");
|
||||
assertThat(statesRepository.count(), is(0l));
|
||||
|
||||
statesRepository.save(stateS1);
|
||||
statesRepository.save(stateS2);
|
||||
assertThat(statesRepository.count(), is(2l));
|
||||
|
||||
JpaTransitionRepository transitionsRepository = context.getBean(JpaTransitionRepository.class);
|
||||
JpaRepositoryTransition transition = new JpaRepositoryTransition("S1", "S2", "E1");
|
||||
JpaRepositoryTransition transition = new JpaRepositoryTransition(stateS1, stateS2, "E1");
|
||||
transition.setKind(TransitionKind.EXTERNAL);
|
||||
transitionsRepository.save(transition);
|
||||
|
||||
assertThat(statesRepository.count(), is(2l));
|
||||
|
||||
JpaRepositoryTransition transition2 = transitionsRepository.findAll().iterator().next();
|
||||
assertThat(transition2.getSource(), is("S1"));
|
||||
assertThat(transition2.getTarget(), is("S2"));
|
||||
assertThat(transition2.getSource().getState(), is("S1"));
|
||||
assertThat(transition2.getTarget().getState(), is("S2"));
|
||||
assertThat(transition2.getEvent(), is("E1"));
|
||||
assertThat(transition2.getKind(), is(TransitionKind.EXTERNAL));
|
||||
|
||||
@@ -85,8 +91,10 @@ public class JpaRepositoryTests extends AbstractJpaRepositoryTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
StateRepository<JpaRepositoryState> statesRepository1 = context.getBean(StateRepository.class);
|
||||
JpaRepositoryState state = new JpaRepositoryState("S1");
|
||||
statesRepository1.save(state);
|
||||
JpaRepositoryState state1 = new JpaRepositoryState("S1");
|
||||
statesRepository1.save(state1);
|
||||
JpaRepositoryState state2 = new JpaRepositoryState("S2");
|
||||
statesRepository1.save(state2);
|
||||
@SuppressWarnings("unchecked")
|
||||
StateRepository<? extends RepositoryState> statesRepository2 = context.getBean(StateRepository.class);
|
||||
Iterable<? extends RepositoryState> findAll = statesRepository2.findAll();
|
||||
@@ -94,11 +102,11 @@ public class JpaRepositoryTests extends AbstractJpaRepositoryTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
TransitionRepository<RepositoryTransition> transitionsRepository = context.getBean(TransitionRepository.class);
|
||||
RepositoryTransition transition = new JpaRepositoryTransition("S1", "S2", "E1");
|
||||
RepositoryTransition transition = new JpaRepositoryTransition(state1, state2, "E1");
|
||||
transitionsRepository.save(transition);
|
||||
RepositoryTransition transition2 = transitionsRepository.findAll().iterator().next();
|
||||
assertThat(transition2.getSource(), is("S1"));
|
||||
assertThat(transition2.getTarget(), is("S2"));
|
||||
assertThat(transition2.getSource().getState(), is("S1"));
|
||||
assertThat(transition2.getTarget().getState(), is("S2"));
|
||||
assertThat(transition2.getEvent(), is("E1"));
|
||||
|
||||
context.close();
|
||||
@@ -114,18 +122,22 @@ public class JpaRepositoryTests extends AbstractJpaRepositoryTests {
|
||||
statesRepository.save(state1);
|
||||
JpaRepositoryState state2 = new JpaRepositoryState("machine2", "S2", false);
|
||||
statesRepository.save(state2);
|
||||
JpaRepositoryState state3 = new JpaRepositoryState("machine1", "S3", true);
|
||||
statesRepository.save(state3);
|
||||
JpaRepositoryState state4 = new JpaRepositoryState("machine2", "S4", false);
|
||||
statesRepository.save(state4);
|
||||
|
||||
List<JpaRepositoryState> findByMachineId1 = statesRepository.findByMachineId("machine1");
|
||||
List<JpaRepositoryState> findByMachineId2 = statesRepository.findByMachineId("machine2");
|
||||
assertThat(findByMachineId1.size(), is(1));
|
||||
assertThat(findByMachineId2.size(), is(1));
|
||||
assertThat(findByMachineId1.size(), is(2));
|
||||
assertThat(findByMachineId2.size(), is(2));
|
||||
assertThat(findByMachineId1.get(0).getMachineId(), is("machine1"));
|
||||
assertThat(findByMachineId2.get(0).getMachineId(), is("machine2"));
|
||||
|
||||
|
||||
JpaTransitionRepository transitionsRepository = context.getBean(JpaTransitionRepository.class);
|
||||
JpaRepositoryTransition transition1 = new JpaRepositoryTransition("machine1", "S1", "S2", "E1");
|
||||
JpaRepositoryTransition transition2 = new JpaRepositoryTransition("machine2", "S3", "S4", "E2");
|
||||
JpaRepositoryTransition transition1 = new JpaRepositoryTransition("machine1", state1, state2, "E1");
|
||||
JpaRepositoryTransition transition2 = new JpaRepositoryTransition("machine2", state3, state4, "E2");
|
||||
transitionsRepository.save(transition1);
|
||||
transitionsRepository.save(transition2);
|
||||
List<JpaRepositoryTransition> findByMachineId3 = transitionsRepository.findByMachineId("machine1");
|
||||
@@ -161,10 +173,16 @@ public class JpaRepositoryTests extends AbstractJpaRepositoryTests {
|
||||
context.register(Config.class);
|
||||
context.refresh();
|
||||
|
||||
JpaStateRepository statesRepository = context.getBean(JpaStateRepository.class);
|
||||
JpaRepositoryState stateS1 = new JpaRepositoryState("S1");
|
||||
JpaRepositoryState stateS2 = new JpaRepositoryState("S2");
|
||||
statesRepository.save(stateS1);
|
||||
statesRepository.save(stateS2);
|
||||
|
||||
JpaActionRepository actionsRepository = context.getBean(JpaActionRepository.class);
|
||||
|
||||
JpaTransitionRepository transitionsRepository = context.getBean(JpaTransitionRepository.class);
|
||||
JpaRepositoryTransition transition = new JpaRepositoryTransition("S1", "S2", "E1");
|
||||
JpaRepositoryTransition transition = new JpaRepositoryTransition(stateS1, stateS2, "E1");
|
||||
|
||||
JpaRepositoryAction action1 = new JpaRepositoryAction();
|
||||
action1.setName("action1");
|
||||
@@ -174,8 +192,8 @@ public class JpaRepositoryTests extends AbstractJpaRepositoryTests {
|
||||
|
||||
transitionsRepository.save(transition);
|
||||
JpaRepositoryTransition transition2 = transitionsRepository.findAll().iterator().next();
|
||||
assertThat(transition2.getSource(), is("S1"));
|
||||
assertThat(transition2.getTarget(), is("S2"));
|
||||
assertThat(transition2.getSource().getState(), is("S1"));
|
||||
assertThat(transition2.getTarget().getState(), is("S2"));
|
||||
assertThat(transition2.getEvent(), is("E1"));
|
||||
|
||||
assertThat(actionsRepository.count(), is(1l));
|
||||
@@ -224,6 +242,16 @@ public class JpaRepositoryTests extends AbstractJpaRepositoryTests {
|
||||
plan.test();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPopulate1() {
|
||||
context.register(Config2.class);
|
||||
context.refresh();
|
||||
JpaStateRepository stateRepository = context.getBean(JpaStateRepository.class);
|
||||
JpaTransitionRepository transitionRepository = context.getBean(JpaTransitionRepository.class);
|
||||
assertThat(stateRepository.count(), is(3l));
|
||||
assertThat(transitionRepository.count(), is(3l));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutowire() {
|
||||
context.register(Config.class, WireConfig.class);
|
||||
@@ -258,8 +286,8 @@ public class JpaRepositoryTests extends AbstractJpaRepositoryTests {
|
||||
static class Config2 {
|
||||
|
||||
@Bean
|
||||
public Jackson2RepositoryPopulatorFactoryBean jackson2RepositoryPopulatorFactoryBean() {
|
||||
Jackson2RepositoryPopulatorFactoryBean factoryBean = new Jackson2RepositoryPopulatorFactoryBean();
|
||||
public StateMachineJackson2RepositoryPopulatorFactoryBean jackson2RepositoryPopulatorFactoryBean() {
|
||||
StateMachineJackson2RepositoryPopulatorFactoryBean factoryBean = new StateMachineJackson2RepositoryPopulatorFactoryBean();
|
||||
factoryBean.setResources(new Resource[]{new ClassPathResource("data2.json")});
|
||||
return factoryBean;
|
||||
}
|
||||
@@ -269,8 +297,8 @@ public class JpaRepositoryTests extends AbstractJpaRepositoryTests {
|
||||
static class Config3 {
|
||||
|
||||
@Bean
|
||||
public Jackson2RepositoryPopulatorFactoryBean jackson2RepositoryPopulatorFactoryBean() {
|
||||
Jackson2RepositoryPopulatorFactoryBean factoryBean = new Jackson2RepositoryPopulatorFactoryBean();
|
||||
public StateMachineJackson2RepositoryPopulatorFactoryBean jackson2RepositoryPopulatorFactoryBean() {
|
||||
StateMachineJackson2RepositoryPopulatorFactoryBean factoryBean = new StateMachineJackson2RepositoryPopulatorFactoryBean();
|
||||
factoryBean.setResources(new Resource[]{new ClassPathResource("data3.json")});
|
||||
return factoryBean;
|
||||
}
|
||||
|
||||
@@ -33,12 +33,16 @@ public class DocsJpaRepositorySampleTests1 {
|
||||
|
||||
void addConfig() {
|
||||
JpaRepositoryState state1 = new JpaRepositoryState("machine1", "S1", true);
|
||||
stateRepository.save(state1);
|
||||
JpaRepositoryState state2 = new JpaRepositoryState("machine2", "S2", false);
|
||||
JpaRepositoryState state3 = new JpaRepositoryState("machine1", "S3", true);
|
||||
JpaRepositoryState state4 = new JpaRepositoryState("machine2", "S4", false);
|
||||
stateRepository.save(state1);
|
||||
stateRepository.save(state2);
|
||||
stateRepository.save(state3);
|
||||
stateRepository.save(state4);
|
||||
|
||||
JpaRepositoryTransition transition1 = new JpaRepositoryTransition("machine1", "S1", "S2", "E1");
|
||||
JpaRepositoryTransition transition2 = new JpaRepositoryTransition("machine2", "S3", "S4", "E2");
|
||||
JpaRepositoryTransition transition1 = new JpaRepositoryTransition("machine1", state1, state2, "E1");
|
||||
JpaRepositoryTransition transition2 = new JpaRepositoryTransition("machine2", state3, state4, "E2");
|
||||
transitionRepository.save(transition1);
|
||||
transitionRepository.save(transition2);
|
||||
}
|
||||
|
||||
@@ -1,30 +1,33 @@
|
||||
[
|
||||
{
|
||||
"@id": "1",
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState",
|
||||
"initial": true,
|
||||
"state": "S1"
|
||||
},
|
||||
{
|
||||
"@id": "2",
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState",
|
||||
"initial": false,
|
||||
"state": "S2"
|
||||
},
|
||||
{
|
||||
"@id": "3",
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState",
|
||||
"initial": false,
|
||||
"state": "S3"
|
||||
},
|
||||
{
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryTransition",
|
||||
"source": "S1",
|
||||
"target": "S2",
|
||||
"source": "1",
|
||||
"target": "2",
|
||||
"event": "E1",
|
||||
"kind": "EXTERNAL"
|
||||
},
|
||||
{
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryTransition",
|
||||
"source": "S2",
|
||||
"target": "S3",
|
||||
"source": "2",
|
||||
"target": "3",
|
||||
"event": "E2",
|
||||
"guard": {
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryGuard",
|
||||
@@ -33,8 +36,8 @@
|
||||
},
|
||||
{
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryTransition",
|
||||
"source": "S2",
|
||||
"target": "S3",
|
||||
"source": "2",
|
||||
"target": "3",
|
||||
"event": "E3",
|
||||
"kind": "LOCAL"
|
||||
}
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
[
|
||||
{
|
||||
"@id": "1",
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState",
|
||||
"initial": true,
|
||||
"state": "S1"
|
||||
},
|
||||
{
|
||||
"@id": "2",
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState",
|
||||
"initial": false,
|
||||
"state": "S2"
|
||||
},
|
||||
{
|
||||
"@id": "3",
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState",
|
||||
"initial": true,
|
||||
"parentState": "S2",
|
||||
"state": "S20"
|
||||
},
|
||||
{
|
||||
"@id": "4",
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState",
|
||||
"initial": false,
|
||||
"parentState": "S2",
|
||||
@@ -23,26 +27,26 @@
|
||||
},
|
||||
{
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryTransition",
|
||||
"source": "S1",
|
||||
"target": "S2",
|
||||
"source": "1",
|
||||
"target": "2",
|
||||
"event": "E1"
|
||||
},
|
||||
{
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryTransition",
|
||||
"source": "S20",
|
||||
"target": "S21",
|
||||
"source": "3",
|
||||
"target": "4",
|
||||
"event": "E2"
|
||||
},
|
||||
{
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryTransition",
|
||||
"source": "S2",
|
||||
"target": "S1",
|
||||
"source": "2",
|
||||
"target": "1",
|
||||
"event": "E3"
|
||||
},
|
||||
{
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryTransition",
|
||||
"source": "S1",
|
||||
"target": "S21",
|
||||
"source": "1",
|
||||
"target": "4",
|
||||
"event": "E4"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 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.
|
||||
* 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 org.springframework.statemachine.data;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
|
||||
/**
|
||||
* Generic base class for all entity classes.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
*/
|
||||
@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="_class")
|
||||
public abstract class BaseRepositoryEntity {
|
||||
}
|
||||
@@ -18,59 +18,59 @@ package org.springframework.statemachine.data;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Generic interface representing state entity.
|
||||
* Generic base class representing state entity.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
*/
|
||||
public interface RepositoryState {
|
||||
public abstract class RepositoryState extends BaseRepositoryEntity {
|
||||
|
||||
/**
|
||||
* Gets the parent state.
|
||||
*
|
||||
* @return the parent state
|
||||
*/
|
||||
String getParentState();
|
||||
public abstract String getParentState();
|
||||
|
||||
/**
|
||||
* Gets the machine id.
|
||||
*
|
||||
* @return the machine id
|
||||
*/
|
||||
String getMachineId();
|
||||
public abstract String getMachineId();
|
||||
|
||||
/**
|
||||
* Gets the state.
|
||||
*
|
||||
* @return the state
|
||||
*/
|
||||
String getState();
|
||||
public abstract String getState();
|
||||
|
||||
/**
|
||||
* Checks if is initial.
|
||||
*
|
||||
* @return true, if is initial
|
||||
*/
|
||||
boolean isInitial();
|
||||
public abstract boolean isInitial();
|
||||
|
||||
/**
|
||||
* Gets the state actions.
|
||||
*
|
||||
* @return the state actions
|
||||
*/
|
||||
Set<? extends RepositoryAction> getStateActions();
|
||||
public abstract Set<? extends RepositoryAction> getStateActions();
|
||||
|
||||
/**
|
||||
* Gets the entry actions.
|
||||
*
|
||||
* @return the entry actions
|
||||
*/
|
||||
Set<? extends RepositoryAction> getEntryActions();
|
||||
public abstract Set<? extends RepositoryAction> getEntryActions();
|
||||
|
||||
/**
|
||||
* Gets the exit actions.
|
||||
*
|
||||
* @return the exit actions
|
||||
*/
|
||||
Set<? extends RepositoryAction> getExitActions();
|
||||
public abstract Set<? extends RepositoryAction> getExitActions();
|
||||
}
|
||||
|
||||
@@ -175,8 +175,7 @@ public class RepositoryStateMachineModelFactory extends AbstractStateMachineMode
|
||||
guard = new SpelExpressionGuard<>(parser.parseExpression(repositoryGuard.getSpel()));
|
||||
}
|
||||
}
|
||||
|
||||
transitionData.add(new TransitionData<>(t.getSource(), t.getTarget(), t.getEvent(), actions, guard, kind != null ? kind : TransitionKind.EXTERNAL));
|
||||
transitionData.add(new TransitionData<>(t.getSource().getState(), t.getTarget().getState(), t.getEvent(), actions, guard, kind != null ? kind : TransitionKind.EXTERNAL));
|
||||
}
|
||||
TransitionsData<String, String> transitionsData = new TransitionsData<>(transitionData);
|
||||
|
||||
|
||||
@@ -20,59 +20,59 @@ import java.util.Set;
|
||||
import org.springframework.statemachine.transition.TransitionKind;
|
||||
|
||||
/**
|
||||
* Generic interface representing transition entity.
|
||||
* Generic base class representing transition entity.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
*/
|
||||
public interface RepositoryTransition {
|
||||
public abstract class RepositoryTransition extends BaseRepositoryEntity {
|
||||
|
||||
/**
|
||||
* Gets the machine id.
|
||||
*
|
||||
* @return the machine id
|
||||
*/
|
||||
String getMachineId();
|
||||
public abstract String getMachineId();
|
||||
|
||||
/**
|
||||
* Gets the source.
|
||||
*
|
||||
* @return the source
|
||||
*/
|
||||
String getSource();
|
||||
public abstract RepositoryState getSource();
|
||||
|
||||
/**
|
||||
* Gets the target.
|
||||
*
|
||||
* @return the target
|
||||
*/
|
||||
String getTarget();
|
||||
public abstract RepositoryState getTarget();
|
||||
|
||||
/**
|
||||
* Gets the event.
|
||||
*
|
||||
* @return the event
|
||||
*/
|
||||
String getEvent();
|
||||
public abstract String getEvent();
|
||||
|
||||
/**
|
||||
* Gets the actions.
|
||||
*
|
||||
* @return the actions
|
||||
*/
|
||||
Set<? extends RepositoryAction> getActions();
|
||||
public abstract Set<? extends RepositoryAction> getActions();
|
||||
|
||||
/**
|
||||
* Gets the guard.
|
||||
*
|
||||
* @return the guard
|
||||
*/
|
||||
RepositoryGuard getGuard();
|
||||
public abstract RepositoryGuard getGuard();
|
||||
|
||||
/**
|
||||
* Gets the transition kind.
|
||||
*
|
||||
* @return the transition kind
|
||||
*/
|
||||
TransitionKind getKind();
|
||||
public abstract TransitionKind getKind();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 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.
|
||||
* 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 org.springframework.statemachine.data.support;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.data.repository.init.AbstractRepositoryPopulatorFactoryBean;
|
||||
import org.springframework.data.repository.init.ResourceReader;
|
||||
import org.springframework.data.repository.init.ResourceReaderRepositoryPopulator;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* {@link FactoryBean} to set up a {@link ResourceReaderRepositoryPopulator} with a {@link StateMachineJackson2ResourceReader}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Janne Valkealahti
|
||||
*/
|
||||
public class StateMachineJackson2RepositoryPopulatorFactoryBean extends AbstractRepositoryPopulatorFactoryBean {
|
||||
|
||||
private ObjectMapper mapper;
|
||||
|
||||
/**
|
||||
* Configures the {@link ObjectMapper} to be used.
|
||||
*
|
||||
* @param mapper the new mapper
|
||||
*/
|
||||
public void setMapper(ObjectMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResourceReader getResourceReader() {
|
||||
return new StateMachineJackson2ResourceReader(mapper);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 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.
|
||||
* 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 org.springframework.statemachine.data.support;
|
||||
|
||||
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.data.repository.init.Jackson2ResourceReader;
|
||||
import org.springframework.data.repository.init.ResourceReader;
|
||||
import org.springframework.statemachine.data.BaseRepositoryEntity;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.ObjectReader;
|
||||
|
||||
/**
|
||||
* A {@link ResourceReader} using Jackson to read JSON into objects.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Janne Valkealahti
|
||||
*/
|
||||
public class StateMachineJackson2ResourceReader implements ResourceReader {
|
||||
|
||||
/** The Constant DEFAULT_TYPE_KEY. */
|
||||
private static final String DEFAULT_TYPE_KEY = "_class";
|
||||
|
||||
/** The Constant DEFAULT_MAPPER. */
|
||||
private static final ObjectMapper DEFAULT_MAPPER = new ObjectMapper();
|
||||
|
||||
static {
|
||||
DEFAULT_MAPPER.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
}
|
||||
|
||||
/** The mapper. */
|
||||
private final ObjectMapper mapper;
|
||||
|
||||
/** The type key. */
|
||||
private String typeKey = DEFAULT_TYPE_KEY;
|
||||
|
||||
/**
|
||||
* Creates a new {@link Jackson2ResourceReader}.
|
||||
*/
|
||||
public StateMachineJackson2ResourceReader() {
|
||||
this(DEFAULT_MAPPER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Jackson2ResourceReader} using the given {@link ObjectMapper}.
|
||||
*
|
||||
* @param mapper the mapper
|
||||
*/
|
||||
public StateMachineJackson2ResourceReader(ObjectMapper mapper) {
|
||||
this.mapper = mapper == null ? DEFAULT_MAPPER : mapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the JSON document's key to lookup the type to instantiate the object. Defaults to
|
||||
* {@link Jackson2ResourceReader#DEFAULT_TYPE_KEY}.
|
||||
*
|
||||
* @param typeKey the new type key
|
||||
*/
|
||||
public void setTypeKey(String typeKey) {
|
||||
this.typeKey = typeKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object readFrom(Resource resource, ClassLoader classLoader) throws Exception {
|
||||
InputStream stream = resource.getInputStream();
|
||||
ObjectReader objectReader = mapper.readerFor(JsonNode.class);
|
||||
JsonNode node = objectReader.readTree(stream);
|
||||
objectReader = mapper.readerFor(BaseRepositoryEntity[].class);
|
||||
|
||||
if (node.isArray()) {
|
||||
List<Object> result = new ArrayList<Object>();
|
||||
BaseRepositoryEntity[] entitys = objectReader.readValue(node);
|
||||
result.addAll(Arrays.asList(entitys));
|
||||
return result;
|
||||
}
|
||||
|
||||
return readSingle(node, classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the given {@link JsonNode} into an instance of the type encoded in it using the configured type key.
|
||||
*
|
||||
* @param node must not be {@literal null}.
|
||||
* @param classLoader the class loader
|
||||
* @return the object
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
private Object readSingle(JsonNode node, ClassLoader classLoader) throws IOException {
|
||||
|
||||
JsonNode typeNode = node.findValue(typeKey);
|
||||
String typeName = typeNode == null ? null : typeNode.asText();
|
||||
|
||||
Class<?> type = ClassUtils.resolveClassName(typeName, classLoader);
|
||||
return mapper.readerFor(type).readValue(node);
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.data.repository.init.Jackson2RepositoryPopulatorFactoryBean;
|
||||
import org.springframework.statemachine.config.EnableStateMachineFactory;
|
||||
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
|
||||
import org.springframework.statemachine.config.builders.StateMachineModelConfigurer;
|
||||
@@ -30,14 +29,15 @@ import org.springframework.statemachine.data.RepositoryStateMachineModelFactory;
|
||||
import org.springframework.statemachine.data.RepositoryTransition;
|
||||
import org.springframework.statemachine.data.StateRepository;
|
||||
import org.springframework.statemachine.data.TransitionRepository;
|
||||
import org.springframework.statemachine.data.support.StateMachineJackson2RepositoryPopulatorFactoryBean;
|
||||
|
||||
@Configuration
|
||||
public class StateMachineConfig {
|
||||
|
||||
//tag::snippetA[]
|
||||
@Bean
|
||||
public Jackson2RepositoryPopulatorFactoryBean jackson2RepositoryPopulatorFactoryBean() {
|
||||
Jackson2RepositoryPopulatorFactoryBean factoryBean = new Jackson2RepositoryPopulatorFactoryBean();
|
||||
public StateMachineJackson2RepositoryPopulatorFactoryBean jackson2RepositoryPopulatorFactoryBean() {
|
||||
StateMachineJackson2RepositoryPopulatorFactoryBean factoryBean = new StateMachineJackson2RepositoryPopulatorFactoryBean();
|
||||
factoryBean.setResources(new Resource[]{new ClassPathResource("data.json")});
|
||||
return factoryBean;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
[
|
||||
{
|
||||
"@id": "1",
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState",
|
||||
"initial": true,
|
||||
"state": "S1",
|
||||
@@ -11,6 +12,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"@id": "2",
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState",
|
||||
"initial": false,
|
||||
"state": "S2",
|
||||
@@ -22,6 +24,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"@id": "3",
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState",
|
||||
"initial": false,
|
||||
"state": "S3",
|
||||
@@ -34,15 +37,15 @@
|
||||
},
|
||||
{
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryTransition",
|
||||
"source": "S1",
|
||||
"target": "S2",
|
||||
"source": "1",
|
||||
"target": "2",
|
||||
"event": "E1",
|
||||
"kind": "EXTERNAL"
|
||||
},
|
||||
{
|
||||
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryTransition",
|
||||
"source": "S2",
|
||||
"target": "S3",
|
||||
"source": "2",
|
||||
"target": "3",
|
||||
"event": "E2",
|
||||
"actions": [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user