Add initial infra for config repository

- Initial infra for config abstraction with
  Spring Data Repositories via RepositoryStateMachineModelFactory.
- Initial jpa impl.
- Initial jpa sample atop of H2 DB.
- Relates to #250
This commit is contained in:
Janne Valkealahti
2016-09-23 17:26:39 +01:00
parent 693d7b8951
commit 0d329d9e57
22 changed files with 882 additions and 0 deletions

View File

@@ -195,6 +195,14 @@ project('spring-statemachine-redis') {
}
}
project('spring-statemachine-data-common') {
dependencies {
compile project(":spring-statemachine-core")
compile "org.springframework.data:spring-data-commons:$springDataCommonsVersion"
optional "org.springframework.security:spring-security-core:$springSecurityVersion"
}
}
project('spring-statemachine-cluster') {
description = "Spring State Machine Cluster"

View File

@@ -1,6 +1,8 @@
springShellVersion=1.1.0.RELEASE
springSecurityVersion=4.0.3.RELEASE
springDataRedisVersion=1.6.2.RELEASE
springDataCommonsVersion=1.12.2.RELEASE
springDataJpaVersion=1.10.2.RELEASE
springCloudClusterVersion=1.0.0.RELEASE
jedisVersion=2.7.3
junitVersion=4.12
@@ -17,6 +19,7 @@ tomcatEmbedVersion=8.0.30
servletApiVersion=3.0.1
commonsPool2Version=2.4.2
hsqlVersion=2.3.1
h2Version=1.4.190
eclipseUml2UmlVersion=5.0.0-v20140602-0749
eclipseUml2TypesVersion=2.0.0-v20140602-0749
eclipseUml2CommonVersion=2.0.0-v20140602-0749

View File

@@ -24,6 +24,10 @@ include 'spring-statemachine-samples:security'
include 'spring-statemachine-samples:eventservice'
include 'spring-statemachine-samples:deploy'
include 'spring-statemachine-samples:ordershipping'
include 'spring-statemachine-samples:datajpa'
include 'spring-statemachine-data'
include 'spring-statemachine-data:jpa'
rootProject.children.find {
if (it.name == 'spring-statemachine-recipes') {
@@ -35,5 +39,11 @@ rootProject.children.find {
it.name = 'spring-statemachine-samples-' + it.name
}
}
if (it.name == 'spring-statemachine-data') {
it.name = 'spring-statemachine-data-common'
it.children.each {
it.name = 'spring-statemachine-data-' + it.name
}
}
}

View File

@@ -0,0 +1,11 @@
description = "Spring State Machine Data Common"
project('spring-statemachine-data-jpa') {
description = "Spring State Machine Data Jpa"
dependencies {
compile project(":spring-statemachine-data-common")
optional "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
testCompile "org.hsqldb:hsqldb:$hsqlVersion"
testCompile "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
}
}

View File

@@ -0,0 +1,82 @@
/*
* 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.jpa;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import org.springframework.statemachine.data.RepositoryState;
/**
* JPA entity for states.
*
* @author Janne Valkealahti
*
*/
@Entity
public class JpaRepositoryState implements RepositoryState {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
protected String state;
protected boolean initial;
/**
* Instantiates a new jpa repository state.
*/
public JpaRepositoryState() {
}
public JpaRepositoryState(String state) {
this.state = state;
}
/**
* Instantiates a new jpa repository state.
*
* @param state the state
* @param initial the initial
*/
public JpaRepositoryState(String state, boolean initial) {
super();
this.state = state;
this.initial = initial;
}
@Override
public String getState() {
return state;
}
@Override
public void setState(String state) {
this.state = state;
}
@Override
public boolean isInitial() {
return initial;
}
@Override
public void setInitial(boolean initial) {
this.initial = initial;
}
}

View File

@@ -0,0 +1,90 @@
/*
* 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.jpa;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import org.springframework.statemachine.data.RepositoryTransition;
/**
* JPA entity for transitions.
*
* @author Janne Valkealahti
*
*/
@Entity
public class JpaRepositoryTransition implements RepositoryTransition {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String source;
private String target;
private String event;
/**
* Instantiates a new jpa repository transition.
*/
public JpaRepositoryTransition() {
}
/**
* Instantiates a new jpa repository transition.
*
* @param source the source
* @param target the target
* @param event the event
*/
public JpaRepositoryTransition(String source, String target, String event) {
this.source = source;
this.target = target;
this.event = event;
}
@Override
public String getSource() {
return source;
}
@Override
public void setSource(String source) {
this.source = source;
}
@Override
public String getTarget() {
return target;
}
@Override
public void setTarget(String target) {
this.target = target;
}
@Override
public String getEvent() {
return event;
}
@Override
public void setEvent(String event) {
this.event = event;
}
}

View File

@@ -0,0 +1,27 @@
/*
* 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.jpa;
import org.springframework.statemachine.data.StateRepository;
/**
* A {@link StateRepository} interface for JPA used for states.
*
* @author Janne Valkealahti
*
*/
public interface JpaStateRepository extends StateRepository<JpaRepositoryState> {
}

View File

@@ -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.jpa;
import org.springframework.statemachine.data.StateRepository;
import org.springframework.statemachine.data.TransitionRepository;
/**
* A {@link StateRepository} interface for JPA used for transitions.
*
* @author Janne Valkealahti
*
*/
public interface JpaTransitionRepository extends TransitionRepository<JpaRepositoryTransition> {
}

View File

@@ -0,0 +1,114 @@
/*
* 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.jpa;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.data.RepositoryState;
import org.springframework.statemachine.data.StateRepository;
import org.springframework.statemachine.data.RepositoryTransition;
import org.springframework.statemachine.data.TransitionRepository;
public class JpaRepositoryTests {
@Test
public void testRepository1() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(Config.class);
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"));
JpaTransitionRepository transitionsRepository = context.getBean(JpaTransitionRepository.class);
JpaRepositoryTransition transition = new JpaRepositoryTransition("S1", "S2", "E1");
transitionsRepository.save(transition);
JpaRepositoryTransition transition2 = transitionsRepository.findAll().iterator().next();
assertThat(transition2.getSource(), is("S1"));
assertThat(transition2.getTarget(), is("S2"));
assertThat(transition2.getEvent(), is("E1"));
context.close();
}
@Test
public void testRepository2() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(Config.class);
context.refresh();
@SuppressWarnings("unchecked")
StateRepository<JpaRepositoryState> statesRepository1 = context.getBean(StateRepository.class);
JpaRepositoryState state = new JpaRepositoryState("S1");
statesRepository1.save(state);
@SuppressWarnings("unchecked")
StateRepository<? extends RepositoryState> statesRepository2 = context.getBean(StateRepository.class);
Iterable<? extends RepositoryState> findAll = statesRepository2.findAll();
assertThat(findAll.iterator().next().getState(), is("S1"));
@SuppressWarnings("unchecked")
TransitionRepository<RepositoryTransition> transitionsRepository = context.getBean(TransitionRepository.class);
RepositoryTransition transition = new JpaRepositoryTransition("S1", "S2", "E1");
transitionsRepository.save(transition);
RepositoryTransition transition2 = transitionsRepository.findAll().iterator().next();
assertThat(transition2.getSource(), is("S1"));
assertThat(transition2.getTarget(), is("S2"));
assertThat(transition2.getEvent(), is("E1"));
context.close();
}
@Test
public void testAutowire() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(Config.class, WireConfig.class);
context.refresh();
context.close();
}
@EnableAutoConfiguration
static class Config {
}
@Configuration
static class WireConfig {
@Autowired
StateRepository<JpaRepositoryState> statesRepository1;
@Autowired
TransitionRepository<JpaRepositoryTransition> statesRepository11;
@SuppressWarnings("rawtypes")
@Autowired
StateRepository statesRepository2;
@Autowired
JpaStateRepository statesRepository3;
@Autowired
StateRepository<? extends RepositoryState> statesRepository4;
}
}

View File

@@ -0,0 +1,33 @@
/*
* 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;
/**
* Generic interface representing state entity.
*
* @author Janne Valkealahti
*
*/
public interface RepositoryState {
String getState();
void setState(String state);
boolean isInitial();
void setInitial(boolean initial);
}

View File

@@ -0,0 +1,73 @@
/*
* 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 java.util.ArrayList;
import java.util.Collection;
import org.springframework.statemachine.config.model.ConfigurationData;
import org.springframework.statemachine.config.model.DefaultStateMachineModel;
import org.springframework.statemachine.config.model.StateData;
import org.springframework.statemachine.config.model.StateMachineModel;
import org.springframework.statemachine.config.model.StateMachineModelFactory;
import org.springframework.statemachine.config.model.StatesData;
import org.springframework.statemachine.config.model.TransitionData;
import org.springframework.statemachine.config.model.TransitionsData;
/**
* A generic {@link StateMachineModelFactory} which is backed by a Spring Data
* Repository abstraction.
*
* @author Janne Valkealahti
*
*/
public class RepositoryStateMachineModelFactory implements StateMachineModelFactory<String, String> {
private final StateRepository<? extends RepositoryState> stateRepository;
private final TransitionRepository<? extends RepositoryTransition> transitionRepository;
/**
* Instantiates a new repository state machine model factory.
*
* @param stateRepository the state repository
* @param transitionRepository the transition repository
*/
public RepositoryStateMachineModelFactory(StateRepository<? extends RepositoryState> stateRepository,
TransitionRepository<? extends RepositoryTransition> transitionRepository) {
this.stateRepository = stateRepository;
this.transitionRepository = transitionRepository;
}
@Override
public StateMachineModel<String, String> build() {
ConfigurationData<String, String> configurationData = new ConfigurationData<>();
Collection<StateData<String, String>> stateData = new ArrayList<>();
for (RepositoryState s : stateRepository.findAll()) {
stateData.add(new StateData<String, String>(s.getState(), s.isInitial()));
}
StatesData<String, String> statesData = new StatesData<>(stateData);
Collection<TransitionData<String, String>> transitionData = new ArrayList<>();
for (RepositoryTransition t : transitionRepository.findAll()) {
transitionData.add(new TransitionData<String, String>(t.getSource(), t.getTarget(), t.getEvent()));
}
TransitionsData<String, String> transitionsData = new TransitionsData<>(transitionData);
StateMachineModel<String, String> stateMachineModel = new DefaultStateMachineModel<>(configurationData, statesData, transitionsData);
return stateMachineModel;
}
}

View File

@@ -0,0 +1,37 @@
/*
* 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;
/**
* Generic interface representing transition entity.
*
* @author Janne Valkealahti
*
*/
public interface RepositoryTransition {
String getSource();
void setSource(String source);
String getTarget();
void setTarget(String target);
String getEvent();
void setEvent(String event);
}

View File

@@ -0,0 +1,31 @@
/*
* 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 org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.Repository;
/**
* Generic {@link Repository} interface for states.
*
* @author Janne Valkealahti
*
* @param <S> the state entity type
*/
@NoRepositoryBean
public interface StateRepository<S extends RepositoryState> extends CrudRepository<S, Long> {
}

View File

@@ -0,0 +1,31 @@
/*
* 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 org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.Repository;
/**
* Generic {@link Repository} interface for transitions.
*
* @author Janne Valkealahti
*
* @param <T> the transition entity type
*/
@NoRepositoryBean
public interface TransitionRepository<T extends RepositoryTransition> extends CrudRepository<T, Long> {
}

View File

@@ -109,3 +109,14 @@ project('spring-statemachine-samples-ordershipping') {
}
}
project('spring-statemachine-samples-datajpa') {
description = 'Spring State Machine Data Jpa Sample'
dependencies {
compile project(":spring-statemachine-data-common:spring-statemachine-data-jpa")
compile("org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVersion")
compile("org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion")
compile("org.springframework.boot:spring-boot-devtools:$springBootVersion")
compile("com.h2database:h2:$h2Version")
}
}

View File

@@ -0,0 +1,31 @@
/*
* 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 demo.datajpa;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.orm.jpa.EntityScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@SpringBootApplication
@EntityScan(basePackages = {"org.springframework.statemachine.data.jpa"})
@EnableJpaRepositories(basePackages = {"org.springframework.statemachine.data.jpa"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@@ -0,0 +1,66 @@
/*
* 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 demo.datajpa;
import org.springframework.beans.factory.annotation.Autowired;
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;
import org.springframework.statemachine.config.model.StateMachineModelFactory;
import org.springframework.statemachine.data.RepositoryState;
import org.springframework.statemachine.data.RepositoryStateMachineModelFactory;
import org.springframework.statemachine.data.RepositoryTransition;
import org.springframework.statemachine.data.StateRepository;
import org.springframework.statemachine.data.TransitionRepository;
@Configuration
public class StateMachineConfig {
@Bean
public Jackson2RepositoryPopulatorFactoryBean jackson2RepositoryPopulatorFactoryBean() {
Jackson2RepositoryPopulatorFactoryBean factoryBean = new Jackson2RepositoryPopulatorFactoryBean();
factoryBean.setResources(new Resource[]{new ClassPathResource("data.json")});
return factoryBean;
}
@Configuration
@EnableStateMachineFactory
public static class Config extends StateMachineConfigurerAdapter<String, String> {
@Autowired
private StateRepository<? extends RepositoryState> stateRepository;
@Autowired
private TransitionRepository<? extends RepositoryTransition> transitionRepository;
@Override
public void configure(StateMachineModelConfigurer<String, String> model) throws Exception {
model
.withModel()
.factory(modelFactory());
}
@Bean
public StateMachineModelFactory<String, String> modelFactory() {
return new RepositoryStateMachineModelFactory(stateRepository, transitionRepository);
}
}
}

View File

@@ -0,0 +1,80 @@
/*
* 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 demo.datajpa;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.statemachine.data.RepositoryTransition;
import org.springframework.statemachine.data.TransitionRepository;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class StateMachineController {
@Autowired
private StateMachineFactory<String, String> stateMachineFactory;
@Autowired
private TransitionRepository<? extends RepositoryTransition> transitionRepository;
@RequestMapping("/")
public String home() {
return "redirect:/state";
}
@RequestMapping("/state")
public String feedAndGetStates(@RequestParam(value = "events", required = false) List<String> events, Model model) throws Exception {
StateMachine<String, String> stateMachine = stateMachineFactory.getStateMachine();
StateMachineLogListener listener = new StateMachineLogListener();
stateMachine.addStateListener(listener);
stateMachine.start();
if (events != null) {
for (String event : events) {
stateMachine.sendEvent(event);
}
}
stateMachine.stop();
model.addAttribute("allEvents", getEvents());
model.addAttribute("messages", createMessages(listener.getMessages()));
return "states";
}
private String[] getEvents() {
List<String> events = new ArrayList<>();
for (RepositoryTransition t : transitionRepository.findAll()) {
events.add(t.getEvent());
}
return events.toArray(new String[0]);
}
private String createMessages(List<String> messages) {
StringBuilder buf = new StringBuilder();
for (String message : messages) {
buf.append(message);
buf.append("\n");
}
return buf.toString();
}
}

View File

@@ -0,0 +1,49 @@
/*
* 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 demo.datajpa;
import java.util.LinkedList;
import java.util.List;
import org.springframework.statemachine.StateContext;
import org.springframework.statemachine.StateContext.Stage;
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
public class StateMachineLogListener extends StateMachineListenerAdapter<String, String> {
private final LinkedList<String> messages = new LinkedList<String>();
public List<String> getMessages() {
return messages;
}
public void resetMessages() {
messages.clear();
}
@Override
public void stateContext(StateContext<String, String> stateContext) {
if (stateContext.getStage() == Stage.STATE_ENTRY) {
messages.addFirst("Enter " + stateContext.getTarget().getId());
} else if (stateContext.getStage() == Stage.STATE_EXIT) {
messages.addFirst("Exit " + stateContext.getSource().getId());
} else if (stateContext.getStage() == Stage.STATEMACHINE_START) {
messages.addLast("Machine started");
} else if (stateContext.getStage() == Stage.STATEMACHINE_STOP) {
messages.addFirst("Machine stopped");
}
}
}

View File

@@ -0,0 +1,6 @@
logging:
level:
root: INFO
security:
basic:
enabled: false

View File

@@ -0,0 +1,29 @@
[
{
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState",
"initial": true,
"state": "S1"
},
{
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState",
"initial": false,
"state": "S2"
},
{
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryState",
"initial": false,
"state": "S3"
},
{
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryTransition",
"source": "S1",
"target": "S2",
"event": "E1"
},
{
"_class": "org.springframework.statemachine.data.jpa.JpaRepositoryTransition",
"source": "S2",
"target": "S3",
"event": "E2"
}
]

View File

@@ -0,0 +1,32 @@
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Spring Statemachine Demo</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<div>
<a href="/h2-console" target="_blank">h2 console</a>
</div>
<form action="#" data-th-action="@{/state}" data-th-object="${model}" method="post">
<div>
<p th:text="'Choose events'"/>
<ul>
<li th:each="ty : ${allEvents}">
<input type="checkbox" name="events" th:value="${ty}" />
<label th:text="${ty}">replaced</label>
</li>
</ul>
</div>
<button type="submit">Send Events</button>
</form>
<div>
<textarea th:text="${messages}" rows="20" cols="100"/>
</div>
<div>
<form action="#" data-th-action="@{/state}" method="get">
<button type="submit">Refresh</button>
</form>
</div>
</body>
</html>