Polish account context

This commit is contained in:
Kenny Bastani
2016-12-07 04:35:24 -08:00
parent d0e8b2eba8
commit 38109cf433
32 changed files with 239 additions and 150 deletions

View File

@@ -26,17 +26,17 @@ public class Account extends BaseEntity {
private String accountNumber;
private Boolean defaultAccount;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@OneToMany(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
private Set<AccountEvent> events = new HashSet<>();
@Enumerated(value = EnumType.STRING)
private AccountEventStatus status;
private AccountStatus status;
public Account() {
status = AccountEventStatus.ACCOUNT_CREATED;
status = AccountStatus.ACCOUNT_CREATED;
}
public Account(String accountNumber, Boolean defaultAccount, AccountEventStatus status) {
public Account(String accountNumber, Boolean defaultAccount, AccountStatus status) {
this.accountNumber = accountNumber;
this.defaultAccount = defaultAccount;
this.status = status;
@@ -83,11 +83,11 @@ public class Account extends BaseEntity {
this.events = events;
}
public AccountEventStatus getStatus() {
public AccountStatus getStatus() {
return status;
}
public void setStatus(AccountEventStatus status) {
public void setStatus(AccountStatus status) {
this.status = status;
}

View File

@@ -3,7 +3,7 @@ package demo.account;
/**
* The {@link AccountCommand} represents an action that can be performed to an
* {@link Account} aggregate. Commands initiate an action that can mutate the state of
* an account entity as it transitions between {@link AccountEventStatus} values.
* an account entity as it transitions between {@link AccountStatus} values.
*
* @author kbastani
*/

View File

@@ -1,8 +1,6 @@
package demo.account;
import demo.event.AccountEvent;
import demo.event.EventService;
import org.springframework.data.rest.webmvc.support.RepositoryEntityLinks;
import demo.event.*;
import org.springframework.hateoas.LinkBuilder;
import org.springframework.hateoas.Resource;
import org.springframework.stereotype.Service;
@@ -12,7 +10,7 @@ import org.springframework.util.Assert;
import java.util.Arrays;
import java.util.Objects;
import static demo.account.AccountEventStatus.*;
import static demo.account.AccountStatus.*;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
/**
@@ -30,13 +28,10 @@ public class AccountService {
private final AccountRepository accountRepository;
private final EventService eventService;
private final RepositoryEntityLinks entityLinks;
public AccountService(AccountRepository accountRepository, EventService eventService,
RepositoryEntityLinks entityLinks) {
public AccountService(AccountRepository accountRepository, EventService eventService) {
this.accountRepository = accountRepository;
this.eventService = eventService;
this.entityLinks = entityLinks;
}
/**
@@ -103,10 +98,9 @@ public class AccountService {
if (event != null) {
eventResource = new Resource<>(event,
linkTo(AccountController.class)
.slash("accounts")
.slash(accountId)
linkTo(EventController.class)
.slash("events")
.slash(event.getEventId())
.withSelfRel(),
linkTo(AccountController.class)
.slash("accounts")
@@ -130,11 +124,11 @@ public class AccountService {
Assert.notNull(account, "The account for the supplied id could not be found");
AccountEventStatus status = account.getContent().getStatus();
AccountStatus status = account.getContent().getStatus();
switch (accountCommand) {
case CONFIRM_ACCOUNT:
Assert.isTrue(status == ACCOUNT_CREATED, "The account has already been confirmed");
Assert.isTrue(status == ACCOUNT_PENDING, "The account has already been confirmed");
// Confirm the account
Account updateAccount = account.getContent();
@@ -302,10 +296,23 @@ public class AccountService {
* @return the updated {@link Account} entity
*/
private Account updateAccount(Long id, Account account) {
Assert.notNull(id);
Assert.notNull(account);
Assert.isTrue(Objects.equals(id, account.getAccountId()));
return accountRepository.save(account);
Assert.notNull(id, "Account id must be present in the resource URL");
Assert.notNull(account, "Account request body cannot be null");
if(account.getAccountId() != null) {
Assert.isTrue(Objects.equals(id, account.getAccountId()),
"The account id in the request body must match the resource URL");
} else {
account.setAccountId(id);
}
Account currentAccount = getAccount(id);
currentAccount.setStatus(account.getStatus());
currentAccount.setDefaultAccount(account.getDefaultAccount());
currentAccount.setAccountNumber(account.getAccountNumber());
currentAccount.setUserId(account.getUserId());
return accountRepository.save(currentAccount);
}
/**

View File

@@ -1,14 +1,15 @@
package demo.account;
/**
* The {@link AccountEventStatus} describes the state of an {@link Account}.
* The {@link AccountStatus} describes the state of an {@link Account}.
* The aggregate state of a {@link Account} is sourced from attached domain
* events in the form of {@link demo.event.AccountEvent}.
*
* @author kbastani
*/
public enum AccountEventStatus {
public enum AccountStatus {
ACCOUNT_CREATED,
ACCOUNT_PENDING,
ACCOUNT_CONFIRMED,
ACCOUNT_ACTIVE,
ACCOUNT_SUSPENDED,

View File

@@ -2,7 +2,6 @@ package demo.event;
import com.fasterxml.jackson.annotation.JsonIgnore;
import demo.account.Account;
import demo.account.AccountEventType;
import demo.domain.BaseEntity;
import demo.log.Log;
import org.springframework.data.rest.core.annotation.RestResource;
@@ -33,11 +32,11 @@ public class AccountEvent extends BaseEntity {
@Enumerated(EnumType.STRING)
private AccountEventType type;
@OneToOne(fetch = FetchType.LAZY)
@OneToOne(cascade = CascadeType.MERGE,fetch = FetchType.LAZY)
@JsonIgnore
private Account account;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@OneToMany(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
@JsonIgnore
private Set<Log> logs = new HashSet<>();

View File

@@ -1,8 +1,11 @@
package demo.account;
package demo.event;
import demo.account.Account;
import demo.account.AccountStatus;
/**
* The {@link AccountEventType} represents a collection of possible events that describe
* state transitions of {@link AccountEventStatus} on the {@link Account} aggregate.
* state transitions of {@link AccountStatus} on the {@link Account} aggregate.
*
* @author kbastani
*/

View File

@@ -1,19 +1,27 @@
package demo.account;
package demo.event;
import com.fasterxml.jackson.annotation.JsonIgnore;
import demo.event.AccountEvent;
import demo.event.EventController;
import demo.account.Account;
import demo.account.AccountController;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.Resources;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
/**
* The {@link AccountEvents} is a hypermedia collection of {@link AccountEvent} resources.
*
* @author kbastani
*/
public class AccountEvents extends Resources<AccountEvent> {
private Long accountId;
/**
* Creates an empty {@link Resources} instance.
* Create a new {@link AccountEvents} hypermedia resources collection for an {@link Account}.
*
* @param accountId is the unique identifier for the {@link Account}
* @param content is the collection of {@link AccountEvents} attached to the {@link Account}
*/
public AccountEvents(Long accountId, Iterable<AccountEvent> content) {
this(content);
@@ -45,10 +53,15 @@ public class AccountEvents extends Resources<AccountEvent> {
* @param content must not be {@literal null}.
* @param links the links to be added to the {@link Resources}.
*/
public AccountEvents(Iterable<AccountEvent> content, Link... links) {
private AccountEvents(Iterable<AccountEvent> content, Link... links) {
super(content, links);
}
/**
* Get the {@link Account} identifier that the {@link AccountEvents} apply to.
*
* @return the account identifier
*/
@JsonIgnore
public Long getAccountId() {
return accountId;

View File

@@ -2,8 +2,6 @@ package demo.event;
import demo.account.Account;
import demo.account.AccountController;
import demo.account.AccountEventType;
import demo.account.AccountEvents;
import demo.log.Log;
import demo.log.LogRepository;
import org.springframework.cloud.stream.messaging.Source;
@@ -118,6 +116,17 @@ public class EventService {
return logResource;
}
/**
* Get {@link AccountEvents} for the supplied {@link Account} identifier.
*
* @param id is the unique identifier of the {@link Account}
* @return a list of {@link AccountEvent} wrapped in a hypermedia {@link AccountEvents} resource
*/
public AccountEvents getEvents(Long id) {
Page<AccountEvent> events = eventRepository.findAccountEventsByAccountId(id, new PageRequest(0, Integer.MAX_VALUE));
return new AccountEvents(id, events);
}
/**
* Gets a hypermedia resource for a {@link Log} entity.
*
@@ -148,10 +157,6 @@ public class EventService {
.slash("events")
.slash(event.getEventId())
.withSelfRel(),
entityLinks.linkFor(AccountEvent.class)
.slash(event.getId())
.slash("logs")
.withRel("logs"),
linkTo(AccountController.class)
.slash("accounts")
.slash(event.getAccount().getAccountId())
@@ -169,15 +174,4 @@ public class EventService {
event = eventRepository.save(event);
return event;
}
/**
* Get {@link AccountEvents} for the supplied {@link Account} identifier.
*
* @param id is the unique identifier of the {@link Account}
* @return a list of {@link AccountEvent} wrapped in a hypermedia {@link AccountEvents} resource
*/
public AccountEvents getEvents(Long id) {
Page<AccountEvent> events = eventRepository.findAccountEventsByAccountId(id, new PageRequest(0, Integer.MAX_VALUE));
return new AccountEvents(id, events);
}
}

View File

@@ -1,7 +1,7 @@
package demo.log;
import com.fasterxml.jackson.annotation.JsonIgnore;
import demo.account.AccountEventType;
import demo.event.AccountEventType;
import demo.domain.BaseEntity;
import javax.persistence.*;

View File

@@ -1,3 +0,0 @@
server.port=0
spring.cloud.stream.bindings.output.destination=account
spring.cloud.stream.bindings.output.contentType=application/json

View File

@@ -0,0 +1,12 @@
spring:
profiles:
active: development
---
spring:
profiles: development
cloud:
stream:
bindings:
output:
destination: account
contentType: 'application/json'

View File

@@ -0,0 +1,5 @@
spring:
application:
name: account-web
server:
port: 0

View File

@@ -23,6 +23,10 @@
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>

View File

@@ -6,7 +6,7 @@ public class Account extends BaseEntity {
private Long userId;
private String accountNumber;
private Boolean defaultAccount;
private AccountEventStatus status;
private AccountStatus status;
public Account() {
}
@@ -35,11 +35,11 @@ public class Account extends BaseEntity {
this.defaultAccount = defaultAccount;
}
public AccountEventStatus getStatus() {
public AccountStatus getStatus() {
return status;
}
public void setStatus(AccountEventStatus status) {
public void setStatus(AccountStatus status) {
this.status = status;
}

View File

@@ -1,22 +1,15 @@
package demo.account;
/**
* The {@link AccountEventStatus} describes the state of an {@link Account}.
* The {@link AccountStatus} describes the state of an {@link Account}.
* The aggregate state of a {@link Account} is sourced from attached domain
* events in the form of {@link demo.event.AccountEvent}.
*/
public enum AccountEventStatus {
public enum AccountStatus {
ACCOUNT_CREATED,
ACCOUNT_PENDING,
ACCOUNT_CONFIRMED,
ACCOUNT_ACTIVE,
ACCOUNT_SUSPENDED,
ACCOUNT_ARCHIVED;
@Override
public String toString() {
return super.toString();
}
ACCOUNT_ARCHIVED
}

View File

@@ -1,7 +1,7 @@
package demo.command;
import demo.account.AccountEventStatus;
import demo.account.AccountEventType;
import demo.account.AccountStatus;
import demo.event.AccountEventType;
import demo.event.AccountEvent;
import org.apache.log4j.Logger;
import org.springframework.statemachine.StateContext;
@@ -10,9 +10,9 @@ public abstract class AccountCommand {
final private Logger log = Logger.getLogger(AccountCommand.class);
final private StateContext<AccountEventStatus, AccountEventType> context;
final private StateContext<AccountStatus, AccountEventType> context;
public AccountCommand(StateContext<AccountEventStatus, AccountEventType> context) {
public AccountCommand(StateContext<AccountStatus, AccountEventType> context) {
this.context = context;
}

View File

@@ -1,11 +1,11 @@
package demo.command;
import demo.account.AccountEventStatus;
import demo.account.AccountEventType;
import demo.account.AccountStatus;
import demo.event.AccountEventType;
import org.springframework.statemachine.StateContext;
public class ActivateAccountCommand extends AccountCommand {
public ActivateAccountCommand(StateContext<AccountEventStatus, AccountEventType> context) {
public ActivateAccountCommand(StateContext<AccountStatus, AccountEventType> context) {
super(context);
}
}

View File

@@ -1,11 +1,11 @@
package demo.command;
import demo.account.AccountEventStatus;
import demo.account.AccountEventType;
import demo.account.AccountStatus;
import demo.event.AccountEventType;
import org.springframework.statemachine.StateContext;
public class ArchiveAccountCommand extends AccountCommand {
public ArchiveAccountCommand(StateContext<AccountEventStatus, AccountEventType> context) {
public ArchiveAccountCommand(StateContext<AccountStatus, AccountEventType> context) {
super(context);
}
}

View File

@@ -1,8 +1,8 @@
package demo.command;
import demo.account.Account;
import demo.account.AccountEventStatus;
import demo.account.AccountEventType;
import demo.account.AccountStatus;
import demo.event.AccountEventType;
import demo.event.AccountEvent;
import org.apache.log4j.Logger;
import org.springframework.hateoas.MediaTypes;
@@ -15,10 +15,15 @@ public class ConfirmAccountCommand extends AccountCommand {
final private Logger log = Logger.getLogger(ConfirmAccountCommand.class);
public ConfirmAccountCommand(StateContext<AccountEventStatus, AccountEventType> context) {
public ConfirmAccountCommand(StateContext<AccountStatus, AccountEventType> context) {
super(context);
}
/**
* Applies the {@link AccountEvent} to the {@link Account} aggregate.
*
* @param event is the {@link AccountEvent} for this context
*/
@Override
public void apply(AccountEvent event) throws Exception {
super.apply(event);

View File

@@ -1,41 +1,84 @@
package demo.command;
import demo.account.Account;
import demo.account.AccountEventStatus;
import demo.account.AccountEventType;
import demo.account.AccountStatus;
import demo.event.AccountEvent;
import demo.event.AccountEventType;
import org.apache.log4j.Logger;
import org.springframework.hateoas.MediaTypes;
import org.springframework.hateoas.client.Traverson;
import org.springframework.http.RequestEntity;
import org.springframework.statemachine.StateContext;
import org.springframework.web.client.RestTemplate;
import java.net.URI;
import java.net.URISyntaxException;
public class CreateAccountCommand extends AccountCommand {
final private Logger log = Logger.getLogger(CreateAccountCommand.class);
public CreateAccountCommand(StateContext<AccountEventStatus, AccountEventType> context) {
public CreateAccountCommand(StateContext<AccountStatus, AccountEventType> context) {
super(context);
}
/**
* Applies the {@link AccountEvent} to the {@link Account} aggregate.
*
* @param event is the {@link AccountEvent} for this context
*/
@Override
public void apply(AccountEvent event) throws Exception {
super.apply(event);
// Create a new hypermedia traversal for the account
// Create a traverson for the root account
Traverson traverson = new Traverson(
new URI(event.getLink("account").getHref()),
MediaTypes.HAL_JSON
);
// Traverse to confirm the account
Account account = traverson.follow("commands")
.follow("confirm")
// Get the account resource attached to the event
Account account = traverson.follow("self")
.toEntity(Account.class)
.getBody();
log.info("Account confirmed: " + account);
// Set the account to a pending state
account = setAccountPendingStatus(event, account);
// The account can only be confirmed if it is in a pending state
if (account.getStatus() == AccountStatus.ACCOUNT_PENDING) {
// Traverse to the confirm account command
account = traverson.follow("commands")
.follow("confirm")
.toEntity(Account.class)
.getBody();
log.info("Account confirmed: " + account);
}
}
/**
* Set the {@link Account} resource to a pending state.
*
* @param event is the {@link AccountEvent} for this context
* @param account is the {@link Account} attached to the {@link AccountEvent} resource
* @return an {@link Account} with its updated state set to pending
* @throws URISyntaxException is thrown if the {@link Account} hypermedia link cannot be parsed
*/
private Account setAccountPendingStatus(AccountEvent event, Account account) throws URISyntaxException {
// Set the account status to pending
account.setStatus(AccountStatus.ACCOUNT_PENDING);
RestTemplate restTemplate = new RestTemplate();
// Create a new request entity
RequestEntity<Account> requestEntity = RequestEntity.put(
new URI(event.getLink("account").getHref()))
.contentType(MediaTypes.HAL_JSON)
.body(account);
// Update the account entity's status
account = restTemplate.exchange(requestEntity, Account.class).getBody();
return account;
}
}

View File

@@ -1,11 +1,11 @@
package demo.command;
import demo.account.AccountEventStatus;
import demo.account.AccountEventType;
import demo.account.AccountStatus;
import demo.event.AccountEventType;
import org.springframework.statemachine.StateContext;
public class SuspendAccountCommand extends AccountCommand {
public SuspendAccountCommand(StateContext<AccountEventStatus, AccountEventType> context) {
public SuspendAccountCommand(StateContext<AccountStatus, AccountEventType> context) {
super(context);
}
}

View File

@@ -1,11 +1,11 @@
package demo.command;
import demo.account.AccountEventStatus;
import demo.account.AccountEventType;
import demo.account.AccountStatus;
import demo.event.AccountEventType;
import org.springframework.statemachine.StateContext;
public class UnarchiveAccountCommand extends AccountCommand {
public UnarchiveAccountCommand(StateContext<AccountEventStatus, AccountEventType> context) {
public UnarchiveAccountCommand(StateContext<AccountStatus, AccountEventType> context) {
super(context);
}
}

View File

@@ -1,11 +1,11 @@
package demo.command;
import demo.account.AccountEventStatus;
import demo.account.AccountEventType;
import demo.account.AccountStatus;
import demo.event.AccountEventType;
import org.springframework.statemachine.StateContext;
public class UnsuspendAccountCommand extends AccountCommand {
public UnsuspendAccountCommand(StateContext<AccountEventStatus, AccountEventType> context) {
public UnsuspendAccountCommand(StateContext<AccountStatus, AccountEventType> context) {
super(context);
}
}

View File

@@ -1,6 +1,5 @@
package demo.event;
import demo.account.AccountEventType;
import demo.domain.BaseEntity;
public class AccountEvent extends BaseEntity {

View File

@@ -1,8 +1,7 @@
package demo.event;
import demo.account.AccountEventStatus;
import demo.account.AccountEventType;
import demo.account.AccountEvents;
import demo.account.Account;
import demo.account.AccountStatus;
import demo.state.StateMachineService;
import org.apache.log4j.Logger;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@@ -22,7 +21,7 @@ import java.util.Map;
/**
* The {@link AccountEventStream} monitors for a variety of {@link AccountEvent} domain
* events for an {@link demo.account.Account}.
* events for an {@link Account}.
*/
@EnableAutoConfiguration
@EnableBinding(Sink.class)
@@ -46,7 +45,7 @@ public class AccountEventStream {
logger.info("Account event received: " + accountEvent.toString());
// Create a new ephemeral account state machine
StateMachine<AccountEventStatus, AccountEventType> stateMachine =
StateMachine<AccountStatus, AccountEventType> stateMachine =
stateMachineService.getStateMachine();
// Traverse the hypermedia link for the attached account

View File

@@ -1,4 +1,4 @@
package demo.account;
package demo.event;
public enum AccountEventType {
ACCOUNT_CREATED,

View File

@@ -1,6 +1,5 @@
package demo.account;
package demo.event;
import demo.event.AccountEvent;
import org.springframework.hateoas.Resources;
public class AccountEvents extends Resources<AccountEvent> {

View File

@@ -1,7 +1,7 @@
package demo.state;
import demo.account.AccountEventStatus;
import demo.account.AccountEventType;
import demo.account.AccountStatus;
import demo.event.AccountEventType;
import demo.command.*;
import demo.event.AccountEvent;
import org.apache.log4j.Logger;
@@ -18,69 +18,69 @@ import java.util.EnumSet;
@Configuration
@EnableStateMachineFactory
public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<AccountEventStatus, AccountEventType> {
public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<AccountStatus, AccountEventType> {
final private Logger log = Logger.getLogger(StateMachineConfig.class);
@Override
public void configure(StateMachineStateConfigurer<AccountEventStatus, AccountEventType> states)
public void configure(StateMachineStateConfigurer<AccountStatus, AccountEventType> states)
throws Exception {
// Describe initial condition of account status
states.withStates()
.initial(AccountEventStatus.ACCOUNT_CREATED)
.states(EnumSet.allOf(AccountEventStatus.class));
.initial(AccountStatus.ACCOUNT_CREATED)
.states(EnumSet.allOf(AccountStatus.class));
}
@Override
public void configure(StateMachineTransitionConfigurer<AccountEventStatus, AccountEventType> transitions)
public void configure(StateMachineTransitionConfigurer<AccountStatus, AccountEventType> transitions)
throws Exception {
// Describe state machine transitions for accounts
transitions
.withExternal()
.source(AccountEventStatus.ACCOUNT_CREATED)
.target(AccountEventStatus.ACCOUNT_PENDING)
.source(AccountStatus.ACCOUNT_CREATED)
.target(AccountStatus.ACCOUNT_PENDING)
.event(AccountEventType.ACCOUNT_CREATED)
.action(createAccount())
.and()
.withExternal()
.source(AccountEventStatus.ACCOUNT_PENDING)
.target(AccountEventStatus.ACCOUNT_CONFIRMED)
.source(AccountStatus.ACCOUNT_PENDING)
.target(AccountStatus.ACCOUNT_CONFIRMED)
.event(AccountEventType.ACCOUNT_CONFIRMED)
.action(confirmAccount())
.and()
.withExternal()
.source(AccountEventStatus.ACCOUNT_CONFIRMED)
.target(AccountEventStatus.ACCOUNT_ACTIVE)
.source(AccountStatus.ACCOUNT_CONFIRMED)
.target(AccountStatus.ACCOUNT_ACTIVE)
.event(AccountEventType.ACCOUNT_ACTIVATED)
.action(activateAccount())
.and()
.withExternal()
.source(AccountEventStatus.ACCOUNT_ACTIVE)
.target(AccountEventStatus.ACCOUNT_ARCHIVED)
.source(AccountStatus.ACCOUNT_ACTIVE)
.target(AccountStatus.ACCOUNT_ARCHIVED)
.event(AccountEventType.ACCOUNT_ARCHIVED)
.action(archiveAccount())
.and()
.withExternal()
.source(AccountEventStatus.ACCOUNT_ACTIVE)
.target(AccountEventStatus.ACCOUNT_SUSPENDED)
.source(AccountStatus.ACCOUNT_ACTIVE)
.target(AccountStatus.ACCOUNT_SUSPENDED)
.event(AccountEventType.ACCOUNT_SUSPENDED)
.action(suspendAccount())
.and()
.withExternal()
.source(AccountEventStatus.ACCOUNT_ARCHIVED)
.target(AccountEventStatus.ACCOUNT_ACTIVE)
.source(AccountStatus.ACCOUNT_ARCHIVED)
.target(AccountStatus.ACCOUNT_ACTIVE)
.event(AccountEventType.ACCOUNT_ACTIVATED)
.action(unarchiveAccount())
.and()
.withExternal()
.source(AccountEventStatus.ACCOUNT_SUSPENDED)
.target(AccountEventStatus.ACCOUNT_ACTIVE)
.source(AccountStatus.ACCOUNT_SUSPENDED)
.target(AccountStatus.ACCOUNT_ACTIVE)
.event(AccountEventType.ACCOUNT_ACTIVATED)
.action(unsuspendAccount());
}
@Bean
public Action<AccountEventStatus, AccountEventType> createAccount() {
public Action<AccountStatus, AccountEventType> createAccount() {
return context -> {
AccountEvent accountEvent = replicateEvent(context);
if (accountEvent != null) {
@@ -95,7 +95,7 @@ public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<Accoun
}
@Bean
public Action<AccountEventStatus, AccountEventType> confirmAccount() {
public Action<AccountStatus, AccountEventType> confirmAccount() {
return context -> {
AccountEvent accountEvent = replicateEvent(context);
if (accountEvent != null) {
@@ -110,7 +110,7 @@ public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<Accoun
}
@Bean
public Action<AccountEventStatus, AccountEventType> activateAccount() {
public Action<AccountStatus, AccountEventType> activateAccount() {
return context -> {
AccountEvent accountEvent = replicateEvent(context);
if (accountEvent != null) {
@@ -125,7 +125,7 @@ public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<Accoun
}
@Bean
public Action<AccountEventStatus, AccountEventType> archiveAccount() {
public Action<AccountStatus, AccountEventType> archiveAccount() {
return context -> {
AccountEvent accountEvent = replicateEvent(context);
if (accountEvent != null) {
@@ -140,7 +140,7 @@ public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<Accoun
}
@Bean
public Action<AccountEventStatus, AccountEventType> suspendAccount() {
public Action<AccountStatus, AccountEventType> suspendAccount() {
return context -> {
AccountEvent accountEvent = replicateEvent(context);
if (accountEvent != null) {
@@ -155,7 +155,7 @@ public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<Accoun
}
@Bean
public Action<AccountEventStatus, AccountEventType> unarchiveAccount() {
public Action<AccountStatus, AccountEventType> unarchiveAccount() {
return context -> {
AccountEvent accountEvent = replicateEvent(context);
if (accountEvent != null) {
@@ -170,7 +170,7 @@ public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<Accoun
}
@Bean
public Action<AccountEventStatus, AccountEventType> unsuspendAccount() {
public Action<AccountStatus, AccountEventType> unsuspendAccount() {
return context -> {
AccountEvent accountEvent = replicateEvent(context);
if (accountEvent != null) {
@@ -191,7 +191,7 @@ public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<Accoun
* @param context the state machine context that may include an {@link AccountEvent}
* @return an {@link AccountEvent} only if this event has not yet been processed, otherwise returns null
*/
private AccountEvent replicateEvent(StateContext<AccountEventStatus, AccountEventType> context) {
private AccountEvent replicateEvent(StateContext<AccountStatus, AccountEventType> context) {
AccountEvent currentEvent = null;
log.info(context.getMessage());

View File

@@ -1,7 +1,7 @@
package demo.state;
import demo.account.AccountEventStatus;
import demo.account.AccountEventType;
import demo.account.AccountStatus;
import demo.event.AccountEventType;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.stereotype.Service;
@@ -11,14 +11,14 @@ import java.util.UUID;
@Service
public class StateMachineService {
private final StateMachineFactory<AccountEventStatus, AccountEventType> factory;
private final StateMachineFactory<AccountStatus, AccountEventType> factory;
public StateMachineService(StateMachineFactory<AccountEventStatus, AccountEventType> factory) {
public StateMachineService(StateMachineFactory<AccountStatus, AccountEventType> factory) {
this.factory = factory;
}
public StateMachine<AccountEventStatus, AccountEventType> getStateMachine() {
StateMachine<AccountEventStatus, AccountEventType> stateMachine =
public StateMachine<AccountStatus, AccountEventType> getStateMachine() {
StateMachine<AccountStatus, AccountEventType> stateMachine =
factory.getStateMachine(UUID.randomUUID().toString());
stateMachine.start();
return stateMachine;

View File

@@ -1,5 +0,0 @@
spring.cloud.stream.bindings.input.destination=account
spring.cloud.stream.bindings.input.group=account-group
spring.cloud.stream.bindings.input.consumer.durableSubscription=true
spring.cloud.stream.bindings.input.contentType=application/json
server.port=0

View File

@@ -0,0 +1,17 @@
spring:
profiles:
active: development
---
spring:
profiles: development
cloud:
stream:
bindings:
input:
destination: account
group: account-group
contentType: 'application/json'
consumer:
durableSubscription: true
server:
port: 0

View File

@@ -0,0 +1,4 @@
spring:
application:
name: account-worker
---