- splitted account deletion to 2 separate endpoints: /api/customers/{customerId}/toaccounts/{accountId} and /api/accounts/{accountId}
- simplified the tests - cleared the code
This commit is contained in:
@@ -20,7 +20,7 @@ public class Account extends ReflectiveMutableCommandProcessingAggregate<Account
|
||||
}
|
||||
|
||||
public List<Event> process(DeleteAccountCommand cmd) {
|
||||
return EventUtil.events(new AccountDeletedEvent(new Date()));
|
||||
return EventUtil.events(new AccountDeletedEvent());
|
||||
}
|
||||
|
||||
public List<Event> process(DebitAccountCommand cmd) {
|
||||
|
||||
@@ -19,4 +19,7 @@ public class AccountService {
|
||||
return accountRepository.save(new OpenAccountCommand(customerId, title, initialBalance, description));
|
||||
}
|
||||
|
||||
public CompletableFuture<EntityWithIdAndVersion<Account>> deleteAccount(String accountId) {
|
||||
return accountRepository.update(accountId, new DeleteAccountCommand());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import io.eventuate.EntityWithIdAndVersion;
|
||||
import io.eventuate.EventHandlerContext;
|
||||
import io.eventuate.EventHandlerMethod;
|
||||
import io.eventuate.EventSubscriber;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers.CustomerAccountDeleted;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers.CustomerToAccountDeleted;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.DebitRecordedEvent;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.MoneyTransferCreatedEvent;
|
||||
|
||||
@@ -37,8 +37,8 @@ public class AccountWorkflow {
|
||||
}
|
||||
|
||||
@EventHandlerMethod
|
||||
public CompletableFuture<EntityWithIdAndVersion<Account>> deleteAccount(EventHandlerContext<CustomerAccountDeleted> ctx) {
|
||||
CustomerAccountDeleted event = ctx.getEvent();
|
||||
public CompletableFuture<EntityWithIdAndVersion<Account>> deleteAccount(EventHandlerContext<CustomerToAccountDeleted> ctx) {
|
||||
CustomerToAccountDeleted event = ctx.getEvent();
|
||||
String accountId = event.getAccountId();
|
||||
|
||||
return ctx.update(Account.class, accountId, new DeleteAccountCommand());
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.accounts;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 9/14/16.
|
||||
*/
|
||||
public class DeleteAccountCommand implements AccountCommand {
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.chrisrichardson.eventstore.javaexamples.banking.web.commandside.acco
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.accounts.AccountService;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.CreateAccountRequest;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.CreateAccountResponse;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.DeleteAccountResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@@ -23,6 +24,12 @@ public class AccountController {
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
public CompletableFuture<CreateAccountResponse> createAccount(@Validated @RequestBody CreateAccountRequest request) {
|
||||
return accountService.openAccount(request.getCustomerId(), request.getTitle(), request.getInitialBalance(), request.getDescription())
|
||||
.thenApply(entityAndEventInfo -> new CreateAccountResponse(entityAndEventInfo.getEntityId()));
|
||||
.thenApply(entityAndEventInfo -> new CreateAccountResponse(entityAndEventInfo.getEntityId()));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "{accountId}", method = RequestMethod.DELETE)
|
||||
public CompletableFuture<DeleteAccountResponse> deleteAccount(@PathVariable String accountId) {
|
||||
return accountService.deleteAccount(accountId)
|
||||
.thenApply(entityAndEventInfo -> new DeleteAccountResponse(accountId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,12 +59,10 @@ public class AccountInfoUpdateService {
|
||||
|
||||
|
||||
public void addTransaction(String accountId, AccountTransactionInfo ti) {
|
||||
System.out.println("Start addTransaction for: "+ti.toString());
|
||||
mongoTemplate.upsert(new Query(where("id").is(accountId)),
|
||||
new Update().
|
||||
set("transactions." + ti.getTransactionId(), ti),
|
||||
AccountInfo.class);
|
||||
System.out.println("End addTransaction for: "+ti.toString());
|
||||
}
|
||||
|
||||
|
||||
@@ -78,11 +76,9 @@ public class AccountInfoUpdateService {
|
||||
}
|
||||
|
||||
public void updateTransactionStatus(String accountId, String transactionId, TransferState status) {
|
||||
System.out.println("Start updateTransactionStatus "+accountId +" "+transactionId+" "+status);
|
||||
mongoTemplate.upsert(new Query(where("id").is(accountId)),
|
||||
new Update().
|
||||
set("transactions." + transactionId + ".status", status),
|
||||
AccountInfo.class);
|
||||
System.out.println("End updateTransactionStatus "+accountId +" "+transactionId+" "+status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,6 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 15.01.16.
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "api.gateway")
|
||||
public class ApiGatewayProperties {
|
||||
|
||||
|
||||
@@ -20,9 +20,6 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 15.01.16.
|
||||
*/
|
||||
@Configuration
|
||||
@ComponentScan
|
||||
@EnableAutoConfiguration
|
||||
|
||||
@@ -2,9 +2,6 @@ package net.chrisrichardson.eventstore.javaexamples.banking.apigateway;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 07.12.15.
|
||||
*/
|
||||
public class RestUtil {
|
||||
|
||||
public static boolean isError(HttpStatus status) {
|
||||
|
||||
@@ -33,9 +33,6 @@ import java.util.stream.Stream;
|
||||
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.*;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 15.01.16.
|
||||
*/
|
||||
@RestController
|
||||
public class GatewayController {
|
||||
|
||||
|
||||
@@ -10,9 +10,6 @@ import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 21.01.16.
|
||||
*/
|
||||
public class ContentRequestTransformer extends ProxyRequestTransformer {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -8,9 +8,6 @@ import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Enumeration;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 21.01.16.
|
||||
*/
|
||||
public class HeadersRequestTransformer extends ProxyRequestTransformer {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -7,9 +7,6 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 21.01.16.
|
||||
*/
|
||||
public abstract class ProxyRequestTransformer {
|
||||
|
||||
protected ProxyRequestTransformer predecessor;
|
||||
|
||||
@@ -9,9 +9,6 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 21.01.16.
|
||||
*/
|
||||
public class URLRequestTransformer extends ProxyRequestTransformer {
|
||||
|
||||
private ApiGatewayProperties apiGatewayProperties;
|
||||
|
||||
@@ -25,4 +25,7 @@ api.gateway.endpoints[5].method=POST
|
||||
api.gateway.endpoints[5].location=http://${transfers.commandside.service.host}:8080
|
||||
api.gateway.endpoints[6].path=[/]*api/customers.*
|
||||
api.gateway.endpoints[6].method=DELETE
|
||||
api.gateway.endpoints[6].location=http://${customers.commandside.service.host}:8080
|
||||
api.gateway.endpoints[6].location=http://${customers.commandside.service.host}:8080\
|
||||
api.gateway.endpoints[7].path=[/]*api/accounts.*
|
||||
api.gateway.endpoints[7].method=DELETE
|
||||
api.gateway.endpoints[7].location=http://${accounts.commandside.service.host}:8080
|
||||
@@ -61,7 +61,7 @@ public class CustomerQuerySideIntegrationTest {
|
||||
public void verify(QuerySideCustomer querySideCustomer) {
|
||||
Assert.assertEquals(customerInfo.getName(), querySideCustomer.getName());
|
||||
Assert.assertEquals(customerInfo.getSsn(), querySideCustomer.getSsn());
|
||||
Assert.assertEquals(customerInfo.getEmail(), querySideCustomer.getEmail());
|
||||
Assert.assertEquals(customerInfo.getUserCredentials().getEmail(), querySideCustomer.getEmail());
|
||||
Assert.assertEquals(customerInfo.getPhoneNumber(), querySideCustomer.getPhoneNumber());
|
||||
Assert.assertEquals(customerInfo.getAddress(), querySideCustomer.getAddress());
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package net.chrisrichardson.eventstore.javaexamples.banking.commonauth.controlle
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.QuerySideCustomer;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.UserCredentials;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.commonauth.CustomerAuthService;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.commonauth.model.AuthRequest;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.commonauth.model.ErrorResponse;
|
||||
@@ -23,9 +24,6 @@ import java.io.IOException;
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.GET;
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.POST;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 21.09.15.
|
||||
*/
|
||||
@RestController
|
||||
@Validated
|
||||
@RequestMapping("/api")
|
||||
@@ -40,7 +38,7 @@ public class AuthController {
|
||||
private static ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@RequestMapping(value = "/login", method = POST)
|
||||
public ResponseEntity<QuerySideCustomer> doAuth(@RequestBody @Valid AuthRequest request) throws IOException {
|
||||
public ResponseEntity<QuerySideCustomer> doAuth(@RequestBody @Valid UserCredentials request) throws IOException {
|
||||
QuerySideCustomer customer = customerAuthService.findByEmailAndPassword(request.getEmail(), request.getPassword());
|
||||
|
||||
Token token = tokenService.allocateToken(objectMapper.writeValueAsString(new User(request.getEmail())));
|
||||
|
||||
@@ -3,9 +3,6 @@ package net.chrisrichardson.eventstore.javaexamples.banking.commonauth.model;
|
||||
import org.hibernate.validator.constraints.Email;
|
||||
import org.hibernate.validator.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 19.10.15.
|
||||
*/
|
||||
public class AuthRequest {
|
||||
|
||||
@NotBlank
|
||||
|
||||
@@ -19,14 +19,10 @@ import org.springframework.security.core.token.KeyBasedPersistenceTokenService;
|
||||
import org.springframework.security.core.token.TokenService;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 21.09.15.
|
||||
*/
|
||||
@Configuration
|
||||
@ComponentScan
|
||||
@EnableWebSecurity
|
||||
@@ -45,7 +41,6 @@ public class AuthConfiguration extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
//auth.inMemoryAuthentication();
|
||||
auth.userDetailsService(userDetailsServiceBean());
|
||||
}
|
||||
|
||||
@@ -53,12 +48,8 @@ public class AuthConfiguration extends WebSecurityConfigurerAdapter {
|
||||
public UserDetailsService userDetailsServiceBean() {
|
||||
return email -> {
|
||||
QuerySideCustomer customer = customerAuthService.findByEmail(email);
|
||||
if (customer != null) {
|
||||
return new User(email, customer.getPassword(), true, true, true, true,
|
||||
AuthorityUtils.createAuthorityList("USER"));
|
||||
} else {
|
||||
throw new UsernameNotFoundException(String.format("could not find the customer '%s'", email));
|
||||
}
|
||||
return new User(email, customer.getPassword(), true, true, true, true,
|
||||
AuthorityUtils.createAuthorityList("USER"));
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,6 @@ package net.chrisrichardson.eventstore.javaexamples.banking.commonauth;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 21.09.15.
|
||||
*/
|
||||
@ConfigurationProperties(locations = "classpath:auth.properties", ignoreUnknownFields = false, prefix = "auth")
|
||||
public class AuthProperties {
|
||||
private String serverSecret;
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.commonauth;
|
||||
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.QuerySideCustomer;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.dao.support.DataAccessUtils;
|
||||
|
||||
/**
|
||||
* Created by Main on 15.02.2016.
|
||||
@@ -16,18 +14,10 @@ public class CustomerAuthService {
|
||||
}
|
||||
|
||||
public QuerySideCustomer findByEmail(String email) {
|
||||
List<QuerySideCustomer> customers = customerAuthRepository.findByEmail(email);
|
||||
if (customers.isEmpty())
|
||||
throw new EmptyResultDataAccessException(1);
|
||||
else
|
||||
return customers.get(0);
|
||||
return DataAccessUtils.uniqueResult(customerAuthRepository.findByEmail(email));
|
||||
}
|
||||
|
||||
public QuerySideCustomer findByEmailAndPassword(String email, String password) {
|
||||
List<QuerySideCustomer> customers = customerAuthRepository.findByEmailAndPassword(email, password);
|
||||
if (customers.isEmpty())
|
||||
throw new EmptyResultDataAccessException(1);
|
||||
else
|
||||
return customers.get(0);
|
||||
return DataAccessUtils.uniqueResult(customerAuthRepository.findByEmailAndPassword(email, password));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,6 @@ import org.springframework.stereotype.Service;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 23.09.15.
|
||||
*/
|
||||
@Service
|
||||
public class TokenAuthenticationService {
|
||||
|
||||
|
||||
@@ -11,9 +11,6 @@ import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 23.09.15.
|
||||
*/
|
||||
public class StatelessAuthenticationFilter extends GenericFilterBean {
|
||||
|
||||
private final TokenAuthenticationService tokenAuthenticationService;
|
||||
|
||||
@@ -10,9 +10,6 @@ import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 23.09.15.
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class User implements UserDetails {
|
||||
|
||||
|
||||
@@ -5,9 +5,6 @@ import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 23.09.15.
|
||||
*/
|
||||
public class UserAuthentication implements Authentication {
|
||||
|
||||
private final User user;
|
||||
|
||||
@@ -5,21 +5,4 @@ import io.eventuate.Event;
|
||||
import java.util.Date;
|
||||
|
||||
public class AccountDeletedEvent implements Event {
|
||||
|
||||
private Date timestamp;
|
||||
|
||||
public AccountDeletedEvent() {
|
||||
}
|
||||
|
||||
public AccountDeletedEvent(Date timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public Date getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(Date timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,6 @@ package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.custo
|
||||
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerInfo;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 02.02.16.
|
||||
*/
|
||||
public class CustomerCreatedEvent extends CustomerEvent {
|
||||
|
||||
private CustomerInfo customerInfo;
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 9/14/16.
|
||||
*/
|
||||
public class CustomerAccountDeleted extends CustomerEvent {
|
||||
public class CustomerToAccountDeleted extends CustomerEvent {
|
||||
|
||||
private String accountId;
|
||||
|
||||
public CustomerAccountDeleted() {
|
||||
public CustomerToAccountDeleted() {
|
||||
}
|
||||
|
||||
public CustomerAccountDeleted(String accountId) {
|
||||
public CustomerToAccountDeleted(String accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
@@ -5,9 +5,6 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 9/1/16.
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS,
|
||||
include = JsonTypeInfo.As.PROPERTY,
|
||||
property = "entryType")
|
||||
|
||||
@@ -2,9 +2,6 @@ package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 9/1/16.
|
||||
*/
|
||||
public class AccountHistoryResponse {
|
||||
private List<AccountHistoryEntry> transactionsHistory;
|
||||
|
||||
|
||||
@@ -2,9 +2,6 @@ package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 9/1/16.
|
||||
*/
|
||||
public class AccountOpenInfo extends AccountHistoryEntry {
|
||||
|
||||
private long initialBalance;
|
||||
|
||||
@@ -2,9 +2,6 @@ package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 9/1/16.
|
||||
*/
|
||||
public class GetAccountsResponse {
|
||||
private List<GetAccountResponse> accounts;
|
||||
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.common.customers;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 24.03.16.
|
||||
*/
|
||||
public class AddToAccountResponse {
|
||||
|
||||
private String version;
|
||||
|
||||
@@ -5,9 +5,6 @@ import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 02.02.16.
|
||||
*/
|
||||
public class Address {
|
||||
@NotNull
|
||||
private String street1;
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.common.customers;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonUnwrapped;
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 03.02.16.
|
||||
*/
|
||||
public class CustomerInfo {
|
||||
private Name name;
|
||||
@NotNull
|
||||
protected String email;
|
||||
@NotNull
|
||||
protected String password;
|
||||
@JsonUnwrapped
|
||||
protected UserCredentials userCredentials;
|
||||
@NotNull
|
||||
protected String ssn;
|
||||
protected String phoneNumber;
|
||||
@@ -22,10 +18,9 @@ public class CustomerInfo {
|
||||
public CustomerInfo() {
|
||||
}
|
||||
|
||||
public CustomerInfo(Name name, String email, String password, String ssn, String phoneNumber, Address address) {
|
||||
public CustomerInfo(Name name, UserCredentials userCredentials, String ssn, String phoneNumber, Address address) {
|
||||
this.name = name;
|
||||
this.email = email;
|
||||
this.password = password;
|
||||
this.userCredentials = userCredentials;
|
||||
this.ssn = ssn;
|
||||
this.phoneNumber = phoneNumber;
|
||||
this.address = address;
|
||||
@@ -35,12 +30,8 @@ public class CustomerInfo {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
public UserCredentials getUserCredentials() {
|
||||
return userCredentials;
|
||||
}
|
||||
|
||||
public String getSsn() {
|
||||
|
||||
@@ -3,9 +3,6 @@ package net.chrisrichardson.eventstore.javaexamples.banking.common.customers;
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 03.02.16.
|
||||
*/
|
||||
public class CustomerResponse {
|
||||
|
||||
private String id;
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.common.customers;
|
||||
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
import org.hibernate.validator.constraints.Email;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
public class UserCredentials {
|
||||
@NotNull
|
||||
@Email
|
||||
private String email;
|
||||
@NotNull
|
||||
private String password;
|
||||
|
||||
public UserCredentials() {
|
||||
}
|
||||
|
||||
public UserCredentials(String email, String password) {
|
||||
this.email = email;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return EqualsBuilder.reflectionEquals(this, o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return HashCodeBuilder.reflectionHashCode(this);
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,6 @@ package net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.
|
||||
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerInfo;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 02.02.16.
|
||||
*/
|
||||
public class CreateCustomerCommand implements CustomerCommand {
|
||||
private CustomerInfo customerInfo;
|
||||
|
||||
|
||||
@@ -3,16 +3,13 @@ package net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.
|
||||
import io.eventuate.Event;
|
||||
import io.eventuate.EventUtil;
|
||||
import io.eventuate.ReflectiveMutableCommandProcessingAggregate;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers.CustomerAccountDeleted;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers.CustomerToAccountDeleted;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers.CustomerAddedToAccount;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers.CustomerCreatedEvent;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 02.02.16.
|
||||
*/
|
||||
public class Customer extends ReflectiveMutableCommandProcessingAggregate<Customer, CustomerCommand> {
|
||||
|
||||
private CustomerInfo customerInfo;
|
||||
@@ -24,8 +21,8 @@ public class Customer extends ReflectiveMutableCommandProcessingAggregate<Custom
|
||||
public List<Event> process(AddToAccountCommand cmd) {
|
||||
return EventUtil.events(new CustomerAddedToAccount(cmd.getToAccountInfo()));
|
||||
}
|
||||
public List<Event> process(DeleteAccountCommand cmd) {
|
||||
return EventUtil.events(new CustomerAccountDeleted(cmd.getAccountId()));
|
||||
public List<Event> process(DeleteToAccountCommand cmd) {
|
||||
return EventUtil.events(new CustomerToAccountDeleted(cmd.getAccountId()));
|
||||
}
|
||||
|
||||
public void apply(CustomerCreatedEvent event) {
|
||||
@@ -34,7 +31,7 @@ public class Customer extends ReflectiveMutableCommandProcessingAggregate<Custom
|
||||
|
||||
public void apply(CustomerAddedToAccount event) {
|
||||
}
|
||||
public void apply(CustomerAccountDeleted event) {
|
||||
public void apply(CustomerToAccountDeleted event) {
|
||||
}
|
||||
|
||||
public CustomerInfo getCustomerInfo() {
|
||||
|
||||
@@ -24,7 +24,7 @@ public class CustomerService {
|
||||
return accountRepository.update(customerId, new AddToAccountCommand(toAccountInfo));
|
||||
}
|
||||
|
||||
public CompletableFuture<EntityWithIdAndVersion<Customer>> deleteAccount(String customerId, String accountId) {
|
||||
return accountRepository.update(customerId, new DeleteAccountCommand(accountId));
|
||||
public CompletableFuture<EntityWithIdAndVersion<Customer>> deleteToAccount(String customerId, String accountId) {
|
||||
return accountRepository.update(customerId, new DeleteToAccountCommand(accountId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.customers;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 9/14/16.
|
||||
*/
|
||||
public class DeleteAccountCommand implements CustomerCommand {
|
||||
public class DeleteToAccountCommand implements CustomerCommand {
|
||||
|
||||
private String accountId;
|
||||
|
||||
public DeleteAccountCommand() {
|
||||
public DeleteToAccountCommand() {
|
||||
}
|
||||
|
||||
public DeleteAccountCommand(String accountId) {
|
||||
public DeleteToAccountCommand(String accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
@@ -13,9 +13,6 @@ import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 03.02.16.
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/customers")
|
||||
public class CustomerController {
|
||||
@@ -39,9 +36,9 @@ public class CustomerController {
|
||||
.thenApply(entityAndEventInfo -> new AddToAccountResponse(entityAndEventInfo.getEntityVersion().toString()));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/{customerId}/accounts/{accountId}", method = RequestMethod.DELETE)
|
||||
public CompletableFuture<DeleteAccountResponse> deleteAccount(@PathVariable String customerId, @PathVariable String accountId) {
|
||||
return customerService.deleteAccount(customerId, accountId)
|
||||
@RequestMapping(value = "/{customerId}/toaccounts/{accountId}", method = RequestMethod.DELETE)
|
||||
public CompletableFuture<DeleteAccountResponse> deleteToAccount(@PathVariable String customerId, @PathVariable String accountId) {
|
||||
return customerService.deleteToAccount(customerId, accountId)
|
||||
.thenApply(entityAndEventInfo -> new DeleteAccountResponse(accountId));
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,6 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 03.02.16.
|
||||
*/
|
||||
@Configuration
|
||||
@Import({CustomerConfiguration.class})
|
||||
@ComponentScan
|
||||
|
||||
@@ -33,8 +33,8 @@ public class CustomerInfoUpdateService {
|
||||
try {
|
||||
querySideCustomerRepository.save(new QuerySideCustomer(id,
|
||||
customerInfo.getName(),
|
||||
customerInfo.getEmail(),
|
||||
customerInfo.getPassword(),
|
||||
customerInfo.getUserCredentials().getEmail(),
|
||||
customerInfo.getUserCredentials().getPassword(),
|
||||
customerInfo.getSsn(),
|
||||
customerInfo.getPhoneNumber(),
|
||||
customerInfo.getAddress(),
|
||||
@@ -44,28 +44,27 @@ public class CustomerInfoUpdateService {
|
||||
logger.info("Saved in mongo");
|
||||
} catch (DuplicateKeyException t) {
|
||||
logger.warn("When saving ", t);
|
||||
} catch (Throwable t) {
|
||||
logger.error("Error during saving: ", t);
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
}
|
||||
|
||||
public void addToAccount(String id, ToAccountInfo accountInfo) {
|
||||
QuerySideCustomer customer = querySideCustomerRepository.findOne(id);
|
||||
if (customer != null) {
|
||||
customer.getToAccounts().put(accountInfo.getId(), accountInfo);
|
||||
querySideCustomerRepository.save(customer);
|
||||
}
|
||||
mongoTemplate.upsert(new Query(where("id").is(id)),
|
||||
new Update().
|
||||
set("toAccounts." + accountInfo.getId(), accountInfo),
|
||||
QuerySideCustomer.class);
|
||||
}
|
||||
|
||||
public void deleteFromToAccount(String accountId) {
|
||||
mongoTemplate.find(new Query(where("toAccounts." + accountId).exists(true)),
|
||||
QuerySideCustomer.class).stream()
|
||||
.forEach(querySideCustomer ->
|
||||
mongoTemplate.upsert(new Query(where("id").is(querySideCustomer.getId())),
|
||||
new Update().
|
||||
unset("toAccounts." + accountId),
|
||||
QuerySideCustomer.class)
|
||||
);
|
||||
public void deleteToAccountFromAllCustomers(String accountId) {
|
||||
mongoTemplate.updateMulti(new Query(where("toAccounts." + accountId).exists(true)),
|
||||
new Update().
|
||||
unset("toAccounts." + accountId),
|
||||
QuerySideCustomer.class);
|
||||
}
|
||||
|
||||
public void deleteToAccount(String customerId, String accountId) {
|
||||
mongoTemplate.upsert(new Query(where("id").is(customerId)),
|
||||
new Update().
|
||||
unset("toAccounts." + accountId),
|
||||
QuerySideCustomer.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@ package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.cu
|
||||
import io.eventuate.DispatchedEvent;
|
||||
import io.eventuate.EventHandlerMethod;
|
||||
import io.eventuate.EventSubscriber;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers.CustomerAccountDeleted;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts.AccountDeletedEvent;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers.CustomerToAccountDeleted;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers.CustomerAddedToAccount;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers.CustomerCreatedEvent;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.ToAccountInfo;
|
||||
@@ -44,10 +45,18 @@ public class CustomerQueryWorkflow {
|
||||
}
|
||||
|
||||
@EventHandlerMethod
|
||||
public void deleteToAccounts(DispatchedEvent<CustomerAccountDeleted> de) {
|
||||
CustomerAccountDeleted event = de.getEvent();
|
||||
public void deleteToAccount(DispatchedEvent<CustomerToAccountDeleted> de) {
|
||||
String id = de.getEntityId();
|
||||
CustomerToAccountDeleted event = de.getEvent();
|
||||
String accountId = event.getAccountId();
|
||||
|
||||
customerInfoUpdateService.deleteFromToAccount(accountId);
|
||||
customerInfoUpdateService.deleteToAccount(id, accountId);
|
||||
}
|
||||
|
||||
@EventHandlerMethod
|
||||
public void deleteToAccounts(DispatchedEvent<AccountDeletedEvent> de) {
|
||||
String accountId = de.getEntityId();
|
||||
|
||||
customerInfoUpdateService.deleteToAccountFromAllCustomers(accountId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.cu
|
||||
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.QuerySideCustomer;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
import org.springframework.data.mongodb.repository.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ public class CustomerInfoUpdateServiceTest {
|
||||
|
||||
assertEquals(customerInfo.getName(), querySideCustomer.getName());
|
||||
assertEquals(customerInfo.getAddress(), querySideCustomer.getAddress());
|
||||
assertEquals(customerInfo.getEmail(), querySideCustomer.getEmail());
|
||||
assertEquals(customerInfo.getUserCredentials().getEmail(), querySideCustomer.getEmail());
|
||||
assertEquals(customerInfo.getPhoneNumber(), querySideCustomer.getPhoneNumber());
|
||||
assertEquals(customerInfo.getSsn(), querySideCustomer.getSsn());
|
||||
}
|
||||
@@ -82,7 +82,7 @@ public class CustomerInfoUpdateServiceTest {
|
||||
assertTrue(querySideCustomer.getToAccounts().containsKey(accountId));
|
||||
assertEquals(toAccountInfo, querySideCustomer.getToAccounts().get(accountId));
|
||||
|
||||
customerInfoUpdateService.deleteFromToAccount(accountId);
|
||||
customerInfoUpdateService.deleteToAccountFromAllCustomers(accountId);
|
||||
querySideCustomer = customerQueryService.findByCustomerId(customerId).get();
|
||||
|
||||
assertFalse(querySideCustomer.getToAccounts().containsKey(accountId));
|
||||
|
||||
@@ -48,10 +48,8 @@ public class CustomersQuerySideServiceIntegrationTest {
|
||||
|
||||
final CustomerResponse customerResponse = restTemplate.postForEntity(baseUrl("/customers"), customerInfo, CustomerResponse.class).getBody();
|
||||
final String customerId = customerResponse.getId();
|
||||
final String email = customerResponse.getCustomerInfo().getEmail();
|
||||
final String password = customerResponse.getCustomerInfo().getPassword();
|
||||
|
||||
customersTestUtils.assertCustomerResponse(customerId, email, password, customerInfo);
|
||||
customersTestUtils.assertCustomerResponse(customerId, customerInfo);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package net.chrisrichardson.eventstore.examples.bank.web;
|
||||
|
||||
|
||||
import net.chrisrichardson.eventstorestore.javaexamples.testutil.AbstractRestAPITest;
|
||||
import net.chrisrichardson.eventstorestore.javaexamples.testutil.AuthenticatedRestTemplate;
|
||||
import net.chrisrichardson.eventstorestore.javaexamples.testutil.CustomersTestUtils;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
@@ -43,11 +42,6 @@ public class EndToEndTest extends AbstractRestAPITest {
|
||||
return customersTestUtils;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthenticatedRestTemplate getAuthenticatedRestTemplate() {
|
||||
return new AuthenticatedRestTemplate(restTemplate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestTemplate getRestTemplate() {
|
||||
return restTemplate;
|
||||
|
||||
@@ -5,6 +5,6 @@ eventuateMavenRepoUrl=http://mavenrepo.eventuate.io/release
|
||||
|
||||
springBootVersion=1.3.5.RELEASE
|
||||
|
||||
eventuateClientVersion=0.8.0.RELEASE
|
||||
eventuateLocalVersion=0.2.0.RELEASE
|
||||
eventuateClientVersion=0.10.0.RELEASE
|
||||
eventuateLocalVersion=0.4.0.RELEASE
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.chrisrichardson.eventstore.javaexamples.banking.web;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerInfo;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerResponse;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.QuerySideCustomer;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.UserCredentials;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.commonauth.model.AuthRequest;
|
||||
import net.chrisrichardson.eventstorestore.javaexamples.testutil.CustomersTestUtils;
|
||||
import org.junit.Assert;
|
||||
@@ -48,27 +49,18 @@ public class BankingAuthTest {
|
||||
|
||||
@Test
|
||||
public void shouldCreateCustomerAndLogin() {
|
||||
String email = uniqueEmail();
|
||||
CustomerInfo customerInfo = generateCustomerInfo(email);
|
||||
CustomerInfo customerInfo = generateCustomerInfo();
|
||||
|
||||
final CustomerResponse customerResponse = restTemplate.postForEntity(baseUrl("/customers"), customerInfo, CustomerResponse.class).getBody();
|
||||
final String customerId = customerResponse.getId();
|
||||
final String password = customerResponse.getCustomerInfo().getPassword();
|
||||
|
||||
Assert.assertNotNull(customerId);
|
||||
Assert.assertEquals(customerInfo, customerResponse.getCustomerInfo());
|
||||
|
||||
customersTestUtils.assertCustomerResponse(customerId, email, password, customerInfo);
|
||||
customersTestUtils.assertCustomerResponse(customerId, customerInfo);
|
||||
|
||||
AuthRequest authRequest = new AuthRequest(email, password);
|
||||
|
||||
final QuerySideCustomer loginQuerySideCustomer = restTemplate.postForEntity(baseUrl("/login"), authRequest, QuerySideCustomer.class).getBody();
|
||||
final QuerySideCustomer loginQuerySideCustomer = restTemplate.postForEntity(baseUrl("/login"), customerInfo.getUserCredentials(), QuerySideCustomer.class).getBody();
|
||||
|
||||
customersTestUtils.assertQuerySideCustomerEqualscCustomerInfo(loginQuerySideCustomer, customerResponse.getCustomerInfo());
|
||||
}
|
||||
|
||||
|
||||
private String uniqueEmail() {
|
||||
return System.currentTimeMillis() + "@email.com";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,11 +43,6 @@ public class BankingWebIntegrationTest extends AbstractRestAPITest {
|
||||
@Autowired
|
||||
RestTemplate restTemplate;
|
||||
|
||||
@Override
|
||||
public AuthenticatedRestTemplate getAuthenticatedRestTemplate() {
|
||||
return new AuthenticatedRestTemplate(restTemplate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestTemplate getRestTemplate() {
|
||||
return restTemplate;
|
||||
|
||||
@@ -1,38 +1,33 @@
|
||||
package net.chrisrichardson.eventstorestore.javaexamples.testutil;
|
||||
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.*;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerInfo;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerResponse;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.QuerySideCustomer;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.ToAccountInfo;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.*;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.transactions.CreateMoneyTransferRequest;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.transactions.CreateMoneyTransferResponse;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static net.chrisrichardson.eventstorestore.javaexamples.testutil.CustomersTestUtils.generateCustomerInfo;
|
||||
import static net.chrisrichardson.eventstorestore.javaexamples.testutil.CustomersTestUtils.generateToAccountInfo;
|
||||
import static net.chrisrichardson.eventstorestore.javaexamples.testutil.TestUtil.eventually;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public abstract class AbstractRestAPITest {
|
||||
|
||||
@Test
|
||||
public void shouldCreateAccountsAndTransferMoney() {
|
||||
CustomerInfo customerInfo = generateCustomerInfo();
|
||||
AuthenticatedRestTemplate authenticatedRestTemplate = getAuthenticatedRestTemplate(customerInfo.getUserCredentials());
|
||||
|
||||
final CustomerResponse customerResponse = getRestTemplate().postForEntity(baseUrl("/customers"), customerInfo, CustomerResponse.class).getBody();
|
||||
final String customerId = customerResponse.getId();
|
||||
final String email = customerResponse.getCustomerInfo().getEmail();
|
||||
final String password = customerResponse.getCustomerInfo().getPassword();
|
||||
|
||||
BigDecimal initialFromAccountBalance = new BigDecimal(500);
|
||||
BigDecimal initialToAccountBalance = new BigDecimal(100);
|
||||
@@ -41,54 +36,46 @@ public abstract class AbstractRestAPITest {
|
||||
BigDecimal finalFromAccountBalance = initialFromAccountBalance.subtract(amountToTransfer);
|
||||
BigDecimal finalToAccountBalance = initialToAccountBalance.add(amountToTransfer);
|
||||
|
||||
final CreateAccountResponse fromAccount = getAuthenticatedRestTemplate().postForEntity(baseUrl("/accounts"),
|
||||
final CreateAccountResponse fromAccount = authenticatedRestTemplate.postForEntity(baseUrl("/accounts"),
|
||||
new CreateAccountRequest(customerId, "My 1 Account", "", initialFromAccountBalance),
|
||||
CreateAccountResponse.class, email, password);
|
||||
CreateAccountResponse.class);
|
||||
|
||||
final String fromAccountId = fromAccount.getAccountId();
|
||||
|
||||
CreateAccountResponse toAccount = getAuthenticatedRestTemplate().postForEntity(baseUrl("/accounts"),
|
||||
CreateAccountResponse toAccount = authenticatedRestTemplate.postForEntity(baseUrl("/accounts"),
|
||||
new CreateAccountRequest(customerId, "My 2 Account", "", initialToAccountBalance),
|
||||
CreateAccountResponse.class, email, password);
|
||||
CreateAccountResponse.class);
|
||||
|
||||
String toAccountId = toAccount.getAccountId();
|
||||
|
||||
Assert.assertNotNull(fromAccountId);
|
||||
Assert.assertNotNull(toAccountId);
|
||||
|
||||
assertAccountBalance(email, password, fromAccountId, initialFromAccountBalance);
|
||||
assertAccountBalance(email, password, toAccountId, initialToAccountBalance);
|
||||
assertAccountBalance(authenticatedRestTemplate, fromAccountId, initialFromAccountBalance);
|
||||
assertAccountBalance(authenticatedRestTemplate, toAccountId, initialToAccountBalance);
|
||||
|
||||
final CreateMoneyTransferResponse moneyTransfer = getAuthenticatedRestTemplate().postForEntity(baseUrl("/transfers"),
|
||||
final CreateMoneyTransferResponse moneyTransfer = authenticatedRestTemplate.postForEntity(baseUrl("/transfers"),
|
||||
new CreateMoneyTransferRequest(fromAccountId, toAccountId, amountToTransfer, ""),
|
||||
CreateMoneyTransferResponse.class, email, password);
|
||||
CreateMoneyTransferResponse.class);
|
||||
|
||||
assertAccountBalance(email, password, fromAccountId, finalFromAccountBalance);
|
||||
assertAccountBalance(email, password, toAccountId, finalToAccountBalance);
|
||||
assertAccountBalance(authenticatedRestTemplate, fromAccountId, finalFromAccountBalance);
|
||||
assertAccountBalance(authenticatedRestTemplate, toAccountId, finalToAccountBalance);
|
||||
|
||||
eventually(
|
||||
new Producer<AccountHistoryResponse>() {
|
||||
@Override
|
||||
public CompletableFuture<AccountHistoryResponse> produce() {
|
||||
return CompletableFuture.completedFuture(getAuthenticatedRestTemplate().getForEntity(baseUrl("/accounts/" + fromAccountId + "/history"),
|
||||
AccountHistoryResponse.class, email, password));
|
||||
}
|
||||
},
|
||||
new Verifier<AccountHistoryResponse>() {
|
||||
@Override
|
||||
public void verify(AccountHistoryResponse accountHistoryResponse) {
|
||||
Optional<AccountHistoryEntry> first = accountHistoryResponse.getTransactionsHistory().stream().filter( ahe -> ahe.getEntryType() == AccountHistoryEntry.EntryType.transaction && ((AccountTransactionInfo)ahe).getTransactionId().equals(moneyTransfer.getMoneyTransferId())).findFirst();
|
||||
() -> CompletableFuture.completedFuture(authenticatedRestTemplate.getForEntity(baseUrl("/accounts/" + fromAccountId + "/history"),
|
||||
AccountHistoryResponse.class)),
|
||||
accountHistoryResponse -> {
|
||||
Optional<AccountHistoryEntry> first = accountHistoryResponse.getTransactionsHistory().stream().filter(ahe -> ahe.getEntryType() == AccountHistoryEntry.EntryType.transaction && ((AccountTransactionInfo) ahe).getTransactionId().equals(moneyTransfer.getMoneyTransferId())).findFirst();
|
||||
|
||||
assertTrue(first.isPresent());
|
||||
assertTrue(first.isPresent());
|
||||
|
||||
AccountTransactionInfo ti = (AccountTransactionInfo)first.get();
|
||||
AccountTransactionInfo ti = (AccountTransactionInfo) first.get();
|
||||
|
||||
assertEquals(fromAccountId, ti.getFromAccountId());
|
||||
assertEquals(toAccountId, ti.getToAccountId());
|
||||
assertEquals(toAccountId, ti.getToAccountId());
|
||||
assertEquals(fromAccountId, ti.getFromAccountId());
|
||||
assertEquals(toCents(amountToTransfer).longValue(), ti.getAmount());
|
||||
}
|
||||
assertEquals(fromAccountId, ti.getFromAccountId());
|
||||
assertEquals(toAccountId, ti.getToAccountId());
|
||||
assertEquals(toAccountId, ti.getToAccountId());
|
||||
assertEquals(fromAccountId, ti.getFromAccountId());
|
||||
assertEquals(toCents(amountToTransfer).longValue(), ti.getAmount());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -96,126 +83,90 @@ public abstract class AbstractRestAPITest {
|
||||
public void shouldCreateAndDeleteAccountsAndGetByCustomer() {
|
||||
BigDecimal initialFromAccountBalance = new BigDecimal(500);
|
||||
CustomerInfo customerInfo = generateCustomerInfo();
|
||||
AuthenticatedRestTemplate authenticatedRestTemplate = getAuthenticatedRestTemplate(customerInfo.getUserCredentials());
|
||||
|
||||
final CustomerResponse customerResponse = getRestTemplate().postForEntity(baseUrl("/customers"), customerInfo, CustomerResponse.class).getBody();
|
||||
final String customerId = customerResponse.getId();
|
||||
final String email = customerResponse.getCustomerInfo().getEmail();
|
||||
final String password = customerResponse.getCustomerInfo().getPassword();
|
||||
|
||||
Assert.assertNotNull(customerId);
|
||||
assertEquals(customerInfo, customerResponse.getCustomerInfo());
|
||||
|
||||
getCustomersTestUtils().assertCustomerResponse(customerId, email, password, customerInfo);
|
||||
getCustomersTestUtils().assertCustomerResponse(customerId, customerInfo);
|
||||
|
||||
final CreateAccountResponse account = getAuthenticatedRestTemplate().postForEntity(baseUrl("/accounts"),
|
||||
final CreateAccountResponse account = authenticatedRestTemplate.postForEntity(baseUrl("/accounts"),
|
||||
new CreateAccountRequest(customerId, "My 1 Account", "", initialFromAccountBalance),
|
||||
CreateAccountResponse.class, email, password);
|
||||
CreateAccountResponse.class);
|
||||
|
||||
final String accountId = account.getAccountId();
|
||||
|
||||
Assert.assertNotNull(accountId);
|
||||
|
||||
assertAccountBalance(email, password, accountId, initialFromAccountBalance);
|
||||
assertAccountBalance(authenticatedRestTemplate, accountId, initialFromAccountBalance);
|
||||
|
||||
eventually(
|
||||
new Producer<GetAccountsResponse>() {
|
||||
@Override
|
||||
public CompletableFuture<GetAccountsResponse> produce() {
|
||||
return CompletableFuture.completedFuture(getAuthenticatedRestTemplate().getForEntity(baseUrl("/customers/"+customerId+"/accounts"),
|
||||
GetAccountsResponse.class, email, password));
|
||||
}
|
||||
},
|
||||
new Verifier<GetAccountsResponse>() {
|
||||
@Override
|
||||
public void verify(GetAccountsResponse accountResponses) {
|
||||
assertTrue(accountResponses.getAccounts().stream().filter(acc -> acc.getAccountId().equals(accountId)).findFirst().isPresent());
|
||||
}
|
||||
});
|
||||
() -> CompletableFuture.completedFuture(authenticatedRestTemplate.getForEntity(baseUrl("/customers/" + customerId + "/accounts"),
|
||||
GetAccountsResponse.class)),
|
||||
accountResponses -> assertTrue(accountResponses.getAccounts().stream().filter(acc -> acc.getAccountId().equals(accountId)).findFirst().isPresent()));
|
||||
|
||||
final DeleteAccountResponse deleteAccountResponse = getAuthenticatedRestTemplate().deleteEntity(baseUrl("/customers/"+customerId+"/accounts/"+accountId),
|
||||
DeleteAccountResponse.class, email, password);
|
||||
authenticatedRestTemplate.deleteEntity(baseUrl("/accounts/" + accountId),
|
||||
DeleteAccountResponse.class);
|
||||
|
||||
eventually(
|
||||
new Producer<GetAccountsResponse>() {
|
||||
@Override
|
||||
public CompletableFuture<GetAccountsResponse> produce() {
|
||||
return CompletableFuture.completedFuture(getAuthenticatedRestTemplate().getForEntity(baseUrl("/customers/"+customerId+"/accounts"),
|
||||
GetAccountsResponse.class, email, password));
|
||||
}
|
||||
},
|
||||
new Verifier<GetAccountsResponse>() {
|
||||
@Override
|
||||
public void verify(GetAccountsResponse accountResponses) {
|
||||
assertFalse(accountResponses.getAccounts().stream().filter(acc -> acc.getAccountId().equals(accountId)).findFirst().isPresent());
|
||||
}
|
||||
});
|
||||
() -> CompletableFuture.completedFuture(authenticatedRestTemplate.getForEntity(baseUrl("/customers/" + customerId + "/accounts"),
|
||||
GetAccountsResponse.class)),
|
||||
accountResponses -> assertFalse(accountResponses.getAccounts().stream().filter(acc -> acc.getAccountId().equals(accountId)).findFirst().isPresent()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCreateCustomersAndAddToAccount() {
|
||||
CustomerInfo customerInfo = generateCustomerInfo();
|
||||
AuthenticatedRestTemplate authenticatedRestTemplate = getAuthenticatedRestTemplate(customerInfo.getUserCredentials());
|
||||
|
||||
final CustomerResponse customerResponse = getRestTemplate().postForEntity(baseUrl("/customers"), customerInfo, CustomerResponse.class).getBody();
|
||||
final String customerId = customerResponse.getId();
|
||||
final String email = customerResponse.getCustomerInfo().getEmail();
|
||||
final String password = customerResponse.getCustomerInfo().getPassword();
|
||||
|
||||
Assert.assertNotNull(customerId);
|
||||
assertEquals(customerInfo, customerResponse.getCustomerInfo());
|
||||
|
||||
getCustomersTestUtils().assertCustomerResponse(customerId, email, password, customerInfo);
|
||||
getCustomersTestUtils().assertCustomerResponse(customerId, customerInfo);
|
||||
|
||||
ToAccountInfo toAccountInfo = generateToAccountInfo();
|
||||
|
||||
getAuthenticatedRestTemplate().postForEntity(baseUrl("/customers/" + customerId + "/toaccounts"),
|
||||
authenticatedRestTemplate.postForEntity(baseUrl("/customers/" + customerId + "/toaccounts"),
|
||||
toAccountInfo,
|
||||
null, email, password);
|
||||
null);
|
||||
|
||||
assertToAccountsContains(customerId, email, password, toAccountInfo);
|
||||
assertToAccountsContains(customerId, authenticatedRestTemplate, toAccountInfo);
|
||||
}
|
||||
|
||||
private BigDecimal toCents(BigDecimal dollarAmount) {
|
||||
return dollarAmount.multiply(new BigDecimal(100));
|
||||
}
|
||||
|
||||
private void assertAccountBalance(final String email, final String password, final String fromAccountId, final BigDecimal expectedBalanceInDollars) {
|
||||
private void assertAccountBalance(AuthenticatedRestTemplate authenticatedRestTemplate, final String fromAccountId, final BigDecimal expectedBalanceInDollars) {
|
||||
final BigDecimal inCents = toCents(expectedBalanceInDollars);
|
||||
eventually(
|
||||
new Producer<GetAccountResponse>() {
|
||||
@Override
|
||||
public CompletableFuture<GetAccountResponse> produce() {
|
||||
return CompletableFuture.completedFuture(getAuthenticatedRestTemplate().getForEntity(baseUrl("/accounts/" + fromAccountId),
|
||||
GetAccountResponse.class, email, password));
|
||||
}
|
||||
},
|
||||
new Verifier<GetAccountResponse>() {
|
||||
@Override
|
||||
public void verify(GetAccountResponse accountInfo) {
|
||||
assertEquals(fromAccountId, accountInfo.getAccountId());
|
||||
assertEquals(inCents, accountInfo.getBalance());
|
||||
}
|
||||
() -> CompletableFuture.completedFuture(authenticatedRestTemplate.getForEntity(baseUrl("/accounts/" + fromAccountId),
|
||||
GetAccountResponse.class)),
|
||||
accountInfo -> {
|
||||
assertEquals(fromAccountId, accountInfo.getAccountId());
|
||||
assertEquals(inCents, accountInfo.getBalance());
|
||||
});
|
||||
}
|
||||
|
||||
private void assertToAccountsContains(final String customerId, final String email, final String password, final ToAccountInfo toAccountInfo) {
|
||||
private void assertToAccountsContains(final String customerId, AuthenticatedRestTemplate authenticatedRestTemplate, final ToAccountInfo toAccountInfo) {
|
||||
eventually(
|
||||
new Producer<QuerySideCustomer>() {
|
||||
@Override
|
||||
public CompletableFuture<QuerySideCustomer> produce() {
|
||||
return CompletableFuture.completedFuture(getAuthenticatedRestTemplate().getForEntity(baseUrl("/customers/" + customerId),
|
||||
QuerySideCustomer.class, email, password));
|
||||
}
|
||||
},
|
||||
new Verifier<QuerySideCustomer>() {
|
||||
@Override
|
||||
public void verify(QuerySideCustomer customerResponse) {
|
||||
assertEquals(customerId, customerResponse.getId());
|
||||
assertTrue(customerResponse.getToAccounts().values().stream().anyMatch(t -> t.equals(toAccountInfo)));
|
||||
}
|
||||
() -> CompletableFuture.completedFuture(authenticatedRestTemplate.getForEntity(baseUrl("/customers/" + customerId),
|
||||
QuerySideCustomer.class)),
|
||||
customerResponse -> {
|
||||
assertEquals(customerId, customerResponse.getId());
|
||||
assertTrue(customerResponse.getToAccounts().values().stream().anyMatch(t -> t.equals(toAccountInfo)));
|
||||
});
|
||||
}
|
||||
|
||||
public abstract AuthenticatedRestTemplate getAuthenticatedRestTemplate();
|
||||
public AuthenticatedRestTemplate getAuthenticatedRestTemplate(UserCredentials userCredentials) {
|
||||
return new AuthenticatedRestTemplate(getRestTemplate(), userCredentials);
|
||||
}
|
||||
|
||||
public abstract RestTemplate getRestTemplate();
|
||||
|
||||
|
||||
@@ -1,43 +1,43 @@
|
||||
package net.chrisrichardson.eventstorestore.javaexamples.testutil;
|
||||
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.UserCredentials;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
public class AuthenticatedRestTemplate {
|
||||
|
||||
private RestTemplate restTemplate;
|
||||
private UserCredentials userCredentials;
|
||||
|
||||
public AuthenticatedRestTemplate(RestTemplate restTemplate) {
|
||||
public AuthenticatedRestTemplate(RestTemplate restTemplate, UserCredentials userCredentials) {
|
||||
this.restTemplate = restTemplate;
|
||||
this.userCredentials = userCredentials;
|
||||
}
|
||||
|
||||
public <T> T getForEntity(String url, Class<T> clazz, String email, String password) {
|
||||
public <T> T getForEntity(String url, Class<T> clazz) {
|
||||
return BasicAuthUtils.doBasicAuthenticatedRequest(restTemplate,
|
||||
url,
|
||||
HttpMethod.GET,
|
||||
clazz,
|
||||
email,
|
||||
password);
|
||||
userCredentials);
|
||||
}
|
||||
|
||||
public <T> T postForEntity(String url, Object requestObject, Class<T> clazz, String email, String password) {
|
||||
public <T> T postForEntity(String url, Object requestObject, Class<T> clazz) {
|
||||
return BasicAuthUtils.doBasicAuthenticatedRequest(restTemplate,
|
||||
url,
|
||||
HttpMethod.POST,
|
||||
clazz,
|
||||
requestObject,
|
||||
email,
|
||||
password
|
||||
userCredentials
|
||||
);
|
||||
}
|
||||
|
||||
public <T> T deleteEntity(String url, Class<T> clazz, String email, String password) {
|
||||
public <T> T deleteEntity(String url, Class<T> clazz) {
|
||||
return BasicAuthUtils.doBasicAuthenticatedRequest(restTemplate,
|
||||
url,
|
||||
HttpMethod.DELETE,
|
||||
clazz,
|
||||
email,
|
||||
password
|
||||
userCredentials
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.chrisrichardson.eventstorestore.javaexamples.testutil;
|
||||
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.UserCredentials;
|
||||
import org.apache.tomcat.util.codec.binary.Base64;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -12,10 +13,10 @@ import java.nio.charset.Charset;
|
||||
*/
|
||||
public class BasicAuthUtils {
|
||||
|
||||
public static HttpHeaders basicAuthHeaders(String username, String password) {
|
||||
public static HttpHeaders basicAuthHeaders(UserCredentials userCredentials) {
|
||||
return new HttpHeaders() {
|
||||
{
|
||||
String auth = username + ":" + password;
|
||||
String auth = userCredentials.getEmail() + ":" + userCredentials.getPassword();
|
||||
byte[] encodedAuth = Base64.encodeBase64(
|
||||
auth.getBytes(Charset.forName("US-ASCII")));
|
||||
String authHeader = "Basic " + new String(encodedAuth);
|
||||
@@ -24,16 +25,16 @@ public class BasicAuthUtils {
|
||||
};
|
||||
}
|
||||
|
||||
public static <T> T doBasicAuthenticatedRequest(RestTemplate restTemplate, String url, HttpMethod httpMethod, Class<T> responseType, String email, String password) {
|
||||
return doBasicAuthenticatedRequest(restTemplate, url, httpMethod, responseType, null, email, password);
|
||||
public static <T> T doBasicAuthenticatedRequest(RestTemplate restTemplate, String url, HttpMethod httpMethod, Class<T> responseType, UserCredentials userCredentials) {
|
||||
return doBasicAuthenticatedRequest(restTemplate, url, httpMethod, responseType, null, userCredentials);
|
||||
}
|
||||
|
||||
public static <T> T doBasicAuthenticatedRequest(RestTemplate restTemplate, String url, HttpMethod httpMethod, Class<T> responseType, Object requestObject, String email, String password) {
|
||||
public static <T> T doBasicAuthenticatedRequest(RestTemplate restTemplate, String url, HttpMethod httpMethod, Class<T> responseType, Object requestObject, UserCredentials userCredentials) {
|
||||
HttpEntity httpEntity;
|
||||
if (requestObject != null) {
|
||||
httpEntity = new HttpEntity<>(requestObject, BasicAuthUtils.basicAuthHeaders(email, password));
|
||||
httpEntity = new HttpEntity<>(requestObject, BasicAuthUtils.basicAuthHeaders(userCredentials));
|
||||
} else {
|
||||
httpEntity = new HttpEntity(BasicAuthUtils.basicAuthHeaders(email, password));
|
||||
httpEntity = new HttpEntity(BasicAuthUtils.basicAuthHeaders(userCredentials));
|
||||
}
|
||||
|
||||
ResponseEntity<T> responseEntity = restTemplate.exchange(url,
|
||||
|
||||
@@ -8,9 +8,6 @@ import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static net.chrisrichardson.eventstorestore.javaexamples.testutil.TestUtil.eventually;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 02.03.16.
|
||||
*/
|
||||
public class CustomersTestUtils {
|
||||
|
||||
private RestTemplate restTemplate;
|
||||
@@ -21,41 +18,32 @@ public class CustomersTestUtils {
|
||||
this.customersBaseUrl = customersBaseUrl;
|
||||
}
|
||||
|
||||
public void assertCustomerResponse(final String customerId, final String email, final String password, final CustomerInfo customerInfo) {
|
||||
AuthenticatedRestTemplate art = new AuthenticatedRestTemplate(restTemplate);
|
||||
public void assertCustomerResponse(final String customerId, final CustomerInfo customerInfo) {
|
||||
AuthenticatedRestTemplate art = new AuthenticatedRestTemplate(restTemplate, customerInfo.getUserCredentials());
|
||||
eventually(
|
||||
new Producer<QuerySideCustomer>() {
|
||||
@Override
|
||||
public CompletableFuture<QuerySideCustomer> produce() {
|
||||
return CompletableFuture.completedFuture(art.getForEntity(customersBaseUrl + customerId, QuerySideCustomer.class, email, password));
|
||||
}
|
||||
},
|
||||
new Verifier<QuerySideCustomer>() {
|
||||
@Override
|
||||
public void verify(QuerySideCustomer querySideCustomer) {
|
||||
Assert.assertEquals(customerId, querySideCustomer.getId());
|
||||
assertQuerySideCustomerEqualscCustomerInfo(querySideCustomer, customerInfo);
|
||||
}
|
||||
() -> CompletableFuture.completedFuture(art.getForEntity(customersBaseUrl + customerId, QuerySideCustomer.class)),
|
||||
querySideCustomer -> {
|
||||
Assert.assertEquals(customerId, querySideCustomer.getId());
|
||||
assertQuerySideCustomerEqualscCustomerInfo(querySideCustomer, customerInfo);
|
||||
});
|
||||
}
|
||||
|
||||
public void assertQuerySideCustomerEqualscCustomerInfo(QuerySideCustomer querySideCustomer, CustomerInfo customerInfo) {
|
||||
Assert.assertEquals(querySideCustomer.getName(), customerInfo.getName());
|
||||
Assert.assertEquals(querySideCustomer.getEmail(), customerInfo.getEmail());
|
||||
Assert.assertEquals(querySideCustomer.getEmail(), customerInfo.getUserCredentials().getEmail());
|
||||
Assert.assertEquals(querySideCustomer.getPhoneNumber(), customerInfo.getPhoneNumber());
|
||||
Assert.assertEquals(querySideCustomer.getSsn(), customerInfo.getSsn());
|
||||
Assert.assertEquals(querySideCustomer.getAddress(), customerInfo.getAddress());
|
||||
}
|
||||
|
||||
public static CustomerInfo generateCustomerInfo() {
|
||||
return generateCustomerInfo("current@email.com");
|
||||
return generateCustomerInfo(uniqueEmail());
|
||||
}
|
||||
|
||||
public static CustomerInfo generateCustomerInfo(String email) {
|
||||
return new CustomerInfo(
|
||||
new Name("John", "Doe"),
|
||||
email,
|
||||
"simple_password",
|
||||
new UserCredentials(email, "simple_password"),
|
||||
"000-00-0000",
|
||||
"1-111-111-1111",
|
||||
new Address("street 1",
|
||||
@@ -69,4 +57,8 @@ public class CustomersTestUtils {
|
||||
public static ToAccountInfo generateToAccountInfo() {
|
||||
return new ToAccountInfo("11111111-11111111", "New Account", "John Doe", "");
|
||||
}
|
||||
|
||||
private static String uniqueEmail() {
|
||||
return System.currentTimeMillis() + "@email.com";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user