Polish "Upgrade to Spring Boot 3"

This commit is contained in:
Janne Valkealahti
2023-10-05 12:49:46 +01:00
parent 497eebe55c
commit 2025282e06
20 changed files with 242 additions and 191 deletions

View File

@@ -15,7 +15,6 @@
*/
package org.springframework.statemachine.boot.autoconfigure;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration;
import org.springframework.boot.autoconfigure.AutoConfiguration;
@@ -32,6 +31,8 @@ import org.springframework.statemachine.boot.actuate.StateMachineTraceEndpoint;
import org.springframework.statemachine.boot.actuate.StateMachineTraceRepository;
import org.springframework.statemachine.boot.support.BootStateMachineMonitor;
import io.micrometer.core.instrument.MeterRegistry;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Statemachine.
*
@@ -43,41 +44,41 @@ import org.springframework.statemachine.boot.support.BootStateMachineMonitor;
@ConditionalOnProperty(prefix = "spring.statemachine.monitor", name = "enabled", havingValue = "true", matchIfMissing = true)
public class StateMachineAutoConfiguration {
@ManagementContextConfiguration
public static class StateMachineTraceEndpointConfiguration {
@ManagementContextConfiguration
public static class StateMachineTraceEndpointConfiguration {
@Bean
public StateMachineTraceEndpoint stateMachineTraceEndpoint(StateMachineTraceRepository stateMachineTraceRepository) {
return new StateMachineTraceEndpoint(stateMachineTraceRepository);
}
}
@Bean
public StateMachineTraceEndpoint stateMachineTraceEndpoint(StateMachineTraceRepository stateMachineTraceRepository) {
return new StateMachineTraceEndpoint(stateMachineTraceRepository);
}
}
@Configuration
public static class StateMachineTraceRepositoryConfiguration {
@Configuration
public static class StateMachineTraceRepositoryConfiguration {
@ConditionalOnMissingBean(StateMachineTraceRepository.class)
@Bean
public InMemoryStateMachineTraceRepository stateMachineTraceRepository() {
return new InMemoryStateMachineTraceRepository();
}
}
@ConditionalOnMissingBean(StateMachineTraceRepository.class)
@Bean
public InMemoryStateMachineTraceRepository stateMachineTraceRepository() {
return new InMemoryStateMachineTraceRepository();
}
}
@Configuration
public static class StateMachineMonitoringConfiguration {
@Configuration
public static class StateMachineMonitoringConfiguration {
private final MeterRegistry meterRegistry;
private final StateMachineTraceRepository stateMachineTraceRepository;
private final MeterRegistry meterRegistry;
private final StateMachineTraceRepository stateMachineTraceRepository;
public StateMachineMonitoringConfiguration(
ObjectProvider<MeterRegistry> meterRegistryProvider,
ObjectProvider<StateMachineTraceRepository> traceRepositoryProvider) {
this.meterRegistry = meterRegistryProvider.getIfAvailable();
this.stateMachineTraceRepository = traceRepositoryProvider.getIfAvailable();
}
public StateMachineMonitoringConfiguration(
ObjectProvider<MeterRegistry> meterRegistryProvider,
ObjectProvider<StateMachineTraceRepository> traceRepositoryProvider) {
this.meterRegistry = meterRegistryProvider.getIfAvailable();
this.stateMachineTraceRepository = traceRepositoryProvider.getIfAvailable();
}
@Bean
public BootStateMachineMonitor<?, ?> bootStateMachineMonitor() {
return new BootStateMachineMonitor<>(meterRegistry, stateMachineTraceRepository);
}
}
@Bean
public BootStateMachineMonitor<?, ?> bootStateMachineMonitor() {
return new BootStateMachineMonitor<>(meterRegistry, stateMachineTraceRepository);
}
}
}

View File

@@ -18,7 +18,11 @@ package org.springframework.statemachine.buildtests.tck.mongodb;
import static org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled;
import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled;
import java.net.Socket;
import java.net.InetAddress;
import java.net.ServerSocket;
import javax.net.ServerSocketFactory;
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
import org.junit.jupiter.api.extension.ExecutionCondition;
import org.junit.jupiter.api.extension.ExtensionContext;
@@ -31,11 +35,19 @@ public class EnabledOnMongoDbCondition implements ExecutionCondition {
@Override
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
try {
new Socket("localhost", 27017);
return ENABLED_ON_MONGO;
} catch (Exception e) {
return DISABLED_ON_MONGO;
}
return isPortAvailable(27017) ? DISABLED_ON_MONGO : ENABLED_ON_MONGO;
}
private static boolean isPortAvailable(int port) {
try {
ServerSocket serverSocket = ServerSocketFactory.getDefault()
.createServerSocket(port, 1, InetAddress.getByName("localhost"));
serverSocket.close();
return true;
}
catch (Exception ex) {
return false;
}
}
}

View File

@@ -21,6 +21,7 @@ import static org.springframework.statemachine.TestUtils.doStartAndAssert;
import static org.springframework.statemachine.TestUtils.resolveMachine;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;

View File

@@ -20,6 +20,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;

View File

@@ -28,6 +28,7 @@ import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
@@ -73,7 +74,7 @@ public class DocsConfigurationSampleTests12 {
StepVerifier.create(machine.sendEvent(Mono.just(MessageBuilder.withPayload("E1").build())))
.consumeNextWith(result -> {
StepVerifier.create(result.complete()).consumeErrorWith(e -> {
assertThat(e).isInstanceOf(StateMachineException.class).cause().hasMessageContaining("example error");
assertThat(e).isInstanceOf(StateMachineException.class).cause().hasMessageContaining("example error");
}).verify();
})
.verifyComplete();

View File

@@ -138,16 +138,16 @@ public class DocsConfigurationSampleTests3 {
// tag::snippetE[]
@Configuration
public static class Config5 {
public static class Config5 {
@Bean
public InMemoryUserDetailsManager userDetailsService() {
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
@Bean
public InMemoryUserDetailsManager userDetailsService() {
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}
// end::snippetE[]

View File

@@ -20,6 +20,7 @@ import static org.springframework.statemachine.TestUtils.doSendEventAndConsumeAl
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

View File

@@ -15,15 +15,17 @@
*/
package org.springframework.statemachine.data.jpa;
import org.springframework.statemachine.data.RepositoryAction;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.springframework.statemachine.data.RepositoryAction;
/**
* JPA entity for actions.

View File

@@ -15,15 +15,17 @@
*/
package org.springframework.statemachine.data.jpa;
import org.springframework.statemachine.data.RepositoryGuard;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.springframework.statemachine.data.RepositoryGuard;
/**
* JPA entity for actions.

View File

@@ -15,8 +15,15 @@
*/
package org.springframework.statemachine.data.jpa;
import java.util.Set;
import org.springframework.statemachine.data.RepositoryAction;
import org.springframework.statemachine.data.RepositoryState;
import org.springframework.statemachine.state.PseudoStateKind;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import jakarta.persistence.CollectionTable;
import jakarta.persistence.Column;
import jakarta.persistence.ElementCollection;
@@ -32,10 +39,6 @@ import jakarta.persistence.ManyToMany;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import java.util.Set;
import org.springframework.statemachine.data.RepositoryAction;
import org.springframework.statemachine.data.RepositoryState;
import org.springframework.statemachine.state.PseudoStateKind;
/**
* JPA entity for states.

View File

@@ -15,14 +15,16 @@
*/
package org.springframework.statemachine.data.jpa;
import org.springframework.statemachine.data.RepositoryStateMachine;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Lob;
import jakarta.persistence.Table;
import org.springframework.statemachine.data.RepositoryStateMachine;
/**
* A {@link RepositoryStateMachine} interface for JPA used for states machines.

View File

@@ -15,8 +15,14 @@
*/
package org.springframework.statemachine.data.jpa;
import java.util.Set;
import org.springframework.statemachine.data.RepositoryTransition;
import org.springframework.statemachine.transition.TransitionKind;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
@@ -29,9 +35,6 @@ import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import java.util.Set;
import org.springframework.statemachine.data.RepositoryTransition;
import org.springframework.statemachine.transition.TransitionKind;
/**
* JPA entity for transitions.

View File

@@ -18,24 +18,36 @@ package org.springframework.statemachine.data.mongodb;
import static org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled;
import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled;
import java.net.Socket;
import java.net.InetAddress;
import java.net.ServerSocket;
import javax.net.ServerSocketFactory;
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
import org.junit.jupiter.api.extension.ExecutionCondition;
import org.junit.jupiter.api.extension.ExtensionContext;
public class EnabledOnMongoDbCondition implements ExecutionCondition {
static final ConditionEvaluationResult ENABLED_ON_MONGO = enabled("Mongo DB found");
static final ConditionEvaluationResult ENABLED_ON_MONGO = enabled("Mongo DB found");
static final ConditionEvaluationResult DISABLED_ON_MONGO = disabled("Mongo DB not found");
static final ConditionEvaluationResult DISABLED_ON_MONGO = disabled("Mongo DB not found");
@Override
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
return isPortAvailable(27017) ? DISABLED_ON_MONGO : ENABLED_ON_MONGO;
}
private static boolean isPortAvailable(int port) {
try {
ServerSocket serverSocket = ServerSocketFactory.getDefault()
.createServerSocket(port, 1, InetAddress.getByName("localhost"));
serverSocket.close();
return true;
}
catch (Exception ex) {
return false;
}
}
@Override
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
try {
new Socket("localhost", 27017);
return ENABLED_ON_MONGO;
} catch (Exception e) {
return DISABLED_ON_MONGO;
}
}
}

View File

@@ -15,12 +15,13 @@
*/
package org.springframework.statemachine.data.redis;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;
import org.springframework.statemachine.data.RepositoryAction;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
/**
* Redis entity for actions.
*

View File

@@ -15,12 +15,13 @@
*/
package org.springframework.statemachine.data.redis;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;
import org.springframework.statemachine.data.RepositoryGuard;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
/**
* Redis entity for actions.
*

View File

@@ -15,9 +15,8 @@
*/
package org.springframework.statemachine.data.redis;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import java.util.Set;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Reference;
import org.springframework.data.redis.core.RedisHash;
@@ -26,6 +25,9 @@ import org.springframework.statemachine.data.RepositoryAction;
import org.springframework.statemachine.data.RepositoryState;
import org.springframework.statemachine.state.PseudoStateKind;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
/**
* Redis entity for states.
*

View File

@@ -15,9 +15,8 @@
*/
package org.springframework.statemachine.data.redis;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import java.util.Set;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Reference;
import org.springframework.data.redis.core.RedisHash;
@@ -25,6 +24,9 @@ import org.springframework.data.redis.core.index.Indexed;
import org.springframework.statemachine.data.RepositoryTransition;
import org.springframework.statemachine.transition.TransitionKind;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
/**
* Redis entity for transitions.
*

View File

@@ -16,6 +16,7 @@
package demo.datapersist;
import java.util.EnumSet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

View File

@@ -19,6 +19,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.EnumSet;
import java.util.Scanner;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.annotation.Bean;
@@ -42,133 +43,133 @@ import org.springframework.statemachine.security.SecurityRule.ComparisonType;
@Configuration
public class StateMachineConfig {
private static final Log log = LogFactory.getLog(StateMachineConfig.class);
private static final Log log = LogFactory.getLog(StateMachineConfig.class);
//tag::snippetE[]
static class SecurityConfig {
//tag::snippetE[]
static class SecurityConfig {
@Bean
public InMemoryUserDetailsManager userDetailsService() {
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
UserDetails admin = User.withDefaultPasswordEncoder()
.username("admin")
.password("password")
.roles("USER", "ADMIN")
.build();
return new InMemoryUserDetailsManager(user, admin);
}
}
@Bean
public InMemoryUserDetailsManager userDetailsService() {
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
UserDetails admin = User.withDefaultPasswordEncoder()
.username("admin")
.password("password")
.roles("USER", "ADMIN")
.build();
return new InMemoryUserDetailsManager(user, admin);
}
}
//end::snippetE[]
@Configuration
@EnableStateMachine
static class Config
extends EnumStateMachineConfigurerAdapter<States, Events> {
@Configuration
@EnableStateMachine
static class Config
extends EnumStateMachineConfigurerAdapter<States, Events> {
//tag::snippetA[]
@Override
public void configure(StateMachineConfigurationConfigurer<States, Events> config)
throws Exception {
config
.withConfiguration()
.autoStartup(true)
.and()
.withSecurity()
.enabled(true)
.event("hasRole('USER')");
}
//tag::snippetA[]
@Override
public void configure(StateMachineConfigurationConfigurer<States, Events> config)
throws Exception {
config
.withConfiguration()
.autoStartup(true)
.and()
.withSecurity()
.enabled(true)
.event("hasRole('USER')");
}
//end::snippetA[]
@Override
public void configure(StateMachineStateConfigurer<States, Events> states)
throws Exception {
states
.withStates()
.initial(States.S0)
.states(EnumSet.allOf(States.class));
}
@Override
public void configure(StateMachineStateConfigurer<States, Events> states)
throws Exception {
states
.withStates()
.initial(States.S0)
.states(EnumSet.allOf(States.class));
}
//tag::snippetB[]
@Override
public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
throws Exception {
transitions
.withExternal()
.source(States.S0).target(States.S1).event(Events.A)
.and()
.withExternal()
.source(States.S1).target(States.S2).event(Events.B)
.and()
.withExternal()
.source(States.S2).target(States.S0).event(Events.C)
.and()
.withExternal()
.source(States.S2).target(States.S3).event(Events.E)
.secured("ROLE_ADMIN", ComparisonType.ANY)
.and()
.withExternal()
.source(States.S3).target(States.S0).event(Events.C)
.and()
.withInternal()
.source(States.S0).event(Events.D)
.action(adminAction())
.and()
.withInternal()
.source(States.S1).event(Events.F)
.action(transitionAction())
.secured("ROLE_ADMIN", ComparisonType.ANY);
}
//tag::snippetB[]
@Override
public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
throws Exception {
transitions
.withExternal()
.source(States.S0).target(States.S1).event(Events.A)
.and()
.withExternal()
.source(States.S1).target(States.S2).event(Events.B)
.and()
.withExternal()
.source(States.S2).target(States.S0).event(Events.C)
.and()
.withExternal()
.source(States.S2).target(States.S3).event(Events.E)
.secured("ROLE_ADMIN", ComparisonType.ANY)
.and()
.withExternal()
.source(States.S3).target(States.S0).event(Events.C)
.and()
.withInternal()
.source(States.S0).event(Events.D)
.action(adminAction())
.and()
.withInternal()
.source(States.S1).event(Events.F)
.action(transitionAction())
.secured("ROLE_ADMIN", ComparisonType.ANY);
}
//end::snippetB[]
//tag::snippetC[]
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
@Bean
public Action<States, Events> adminAction() {
return new Action<States, Events>() {
//tag::snippetC[]
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
@Bean
public Action<States, Events> adminAction() {
return new Action<States, Events>() {
@Secured("ROLE_ADMIN")
@Override
public void execute(StateContext<States, Events> context) {
log.info("Executed only for admin role");
}
};
}
@Secured("ROLE_ADMIN")
@Override
public void execute(StateContext<States, Events> context) {
log.info("Executed only for admin role");
}
};
}
//end::snippetC[]
//tag::snippetD[]
@Bean
public Action<States, Events> transitionAction() {
return new Action<States, Events>() {
//tag::snippetD[]
@Bean
public Action<States, Events> transitionAction() {
return new Action<States, Events>() {
@Override
public void execute(StateContext<States, Events> context) {
log.info("Executed only for admin role");
}
};
}
@Override
public void execute(StateContext<States, Events> context) {
log.info("Executed only for admin role");
}
};
}
//end::snippetD[]
}
}
@Bean
public String stateChartModel() throws IOException {
ClassPathResource model = new ClassPathResource("statechartmodel.txt");
InputStream inputStream = model.getInputStream();
Scanner scanner = new Scanner(inputStream);
String content = scanner.useDelimiter("\\Z").next();
scanner.close();
return content;
}
@Bean
public String stateChartModel() throws IOException {
ClassPathResource model = new ClassPathResource("statechartmodel.txt");
InputStream inputStream = model.getInputStream();
Scanner scanner = new Scanner(inputStream);
String content = scanner.useDelimiter("\\Z").next();
scanner.close();
return content;
}
public enum States {
S0, S1, S2, S3;
}
public enum States {
S0, S1, S2, S3;
}
public enum Events {
A, B, C, D, E, F;
}
public enum Events {
A, B, C, D, E, F;
}
}

View File

@@ -15,13 +15,11 @@
*/
package demo.web;
import demo.web.StateMachineConfig.Events;
import demo.web.StateMachineConfig.States;
import jakarta.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -46,6 +44,10 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import demo.web.StateMachineConfig.Events;
import demo.web.StateMachineConfig.States;
import jakarta.annotation.PostConstruct;
import reactor.core.publisher.Mono;
@Controller