diff --git a/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountChangeInfo.java b/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountChangeInfo.java deleted file mode 100644 index b988eb1..0000000 --- a/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountChangeInfo.java +++ /dev/null @@ -1,31 +0,0 @@ -package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.accounts; - -import org.apache.commons.lang.builder.EqualsBuilder; -import org.apache.commons.lang.builder.HashCodeBuilder; - -public class AccountChangeInfo { - - private String changeId; - private String transactionId; - private String transactionType; - private long amount; - private long balanceDelta; - - public AccountChangeInfo(String changeId, String transactionId, String transactionType, long amount, long balanceDelta) { - this.changeId = changeId; - this.transactionId = transactionId; - this.transactionType = transactionType; - this.amount = amount; - this.balanceDelta = balanceDelta; - } - - @Override - public boolean equals(Object o) { - return EqualsBuilder.reflectionEquals(this, o); - } - - @Override - public int hashCode() { - return HashCodeBuilder.reflectionHashCode(this); - } -} diff --git a/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountInfo.java b/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountInfo.java index 46eab5d..abdfe38 100644 --- a/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountInfo.java +++ b/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountInfo.java @@ -1,11 +1,9 @@ package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.accounts; +import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountChangeInfo; import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountTransactionInfo; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; /** * Created by cer on 11/21/14. @@ -20,11 +18,16 @@ public class AccountInfo { private List changes; private List transactions; private String version; + private Date date; private AccountInfo() { } public AccountInfo(String id, String customerId, String title, String description, long balance, List changes, List transactions, String version) { + this(id, customerId, title, description, balance, changes, transactions, version, new Date()); + } + + public AccountInfo(String id, String customerId, String title, String description, long balance, List changes, List transactions, String version, Date date) { this.id = id; this.customerId = customerId; @@ -34,6 +37,7 @@ public class AccountInfo { this.changes = changes; this.transactions = transactions; this.version = version; + this.date = date; } public String getId() { @@ -67,4 +71,8 @@ public class AccountInfo { public String getVersion() { return version; } + + public Date getDate() { + return date; + } } diff --git a/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountInfoUpdateService.java b/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountInfoUpdateService.java index ecc47fb..2161ffb 100644 --- a/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountInfoUpdateService.java +++ b/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountInfoUpdateService.java @@ -1,9 +1,12 @@ package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.accounts; import com.mongodb.WriteResult; +import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountChangeInfo; import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountTransactionInfo; +import net.chrisrichardson.eventstore.javaexamples.banking.common.transactions.TransferState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.dao.DuplicateKeyException; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; @@ -38,6 +41,9 @@ public class AccountInfoUpdateService { Collections.emptyList(), version)); logger.info("Saved in mongo"); + + } catch (DuplicateKeyException t) { + logger.warn("When saving ", t); } catch (Throwable t) { logger.error("Error during saving: "); logger.error("Error during saving: ", t); @@ -64,5 +70,13 @@ public class AccountInfoUpdateService { AccountInfo.class); } + public void updateTransactionStatus(String accountId, String transactionId, TransferState status) { + AccountInfo account = accountInfoRepository.findOne(accountId); + if (account != null) { + account.getTransactions().stream().filter(ati -> ati.getTransactionId().equals(transactionId)).forEach(ati -> ati.setStatus(status)); + accountInfoRepository.save(account); + } + + } } diff --git a/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountQueryService.java b/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountQueryService.java index fc4e12e..3dfa68b 100644 --- a/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountQueryService.java +++ b/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountQueryService.java @@ -1,9 +1,6 @@ package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.accounts; -import io.eventuate.CompletableFutureUtil; - import java.util.List; -import java.util.concurrent.CompletableFuture; public class AccountQueryService { @@ -13,15 +10,15 @@ public class AccountQueryService { this.accountInfoRepository = accountInfoRepository; } - public CompletableFuture findByAccountId(String accountId) { + public AccountInfo findByAccountId(String accountId) { AccountInfo account = accountInfoRepository.findOne(accountId); if (account == null) - return CompletableFutureUtil.failedFuture(new AccountNotFoundException(accountId)); + throw new AccountNotFoundException(accountId); else - return CompletableFuture.completedFuture(account); + return account; } - public CompletableFuture> findByCustomerId(String customerId) { - return CompletableFuture.completedFuture(accountInfoRepository.findByCustomerId(customerId)); + public List findByCustomerId(String customerId) { + return accountInfoRepository.findByCustomerId(customerId); } } diff --git a/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountQueryWorkflow.java b/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountQueryWorkflow.java index 047e894..39ddded 100644 --- a/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountQueryWorkflow.java +++ b/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountQueryWorkflow.java @@ -3,12 +3,14 @@ package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.ac import io.eventuate.DispatchedEvent; import io.eventuate.EventHandlerMethod; import io.eventuate.EventSubscriber; -import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts.AccountChangedEvent; -import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts.AccountCreditedEvent; -import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts.AccountDebitedEvent; -import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts.AccountOpenedEvent; +import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts.*; +import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.CreditRecordedEvent; +import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.DebitRecordedEvent; +import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.FailedDebitRecordedEvent; import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.MoneyTransferCreatedEvent; +import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountChangeInfo; import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountTransactionInfo; +import net.chrisrichardson.eventstore.javaexamples.banking.common.transactions.TransferState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -63,14 +65,30 @@ public class AccountQueryWorkflow { @EventHandlerMethod public void recordDebit(DispatchedEvent de) { + String accountId = de.getEntityId(); + String transactionId = de.getEvent().getTransactionId(); + + accountInfoUpdateService.updateTransactionStatus(accountId, transactionId, TransferState.DEBITED); saveChange(de, -1); } @EventHandlerMethod public void recordCredit(DispatchedEvent de) { + String accountId = de.getEntityId(); + String transactionId = de.getEvent().getTransactionId(); + + accountInfoUpdateService.updateTransactionStatus(accountId, transactionId, TransferState.COMPLETED); saveChange(de, +1); } + @EventHandlerMethod + public void recordFailed(DispatchedEvent de) { + String accountId = de.getEntityId(); + String transactionId = de.getEvent().getTransactionId(); + + accountInfoUpdateService.updateTransactionStatus(accountId, transactionId, TransferState.FAILED_DUE_TO_INSUFFICIENT_FUNDS); + } + public void saveChange(DispatchedEvent de, int delta) { String changeId = de.getEventId().asString(); String transactionId = de.getEvent().getTransactionId(); diff --git a/java-spring/accounts-query-side-backend/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountInfoUpdateServiceTest.java b/java-spring/accounts-query-side-backend/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountInfoUpdateServiceTest.java index 2b7baec..cbe048e 100644 --- a/java-spring/accounts-query-side-backend/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountInfoUpdateServiceTest.java +++ b/java-spring/accounts-query-side-backend/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountInfoUpdateServiceTest.java @@ -4,6 +4,7 @@ import io.eventuate.javaclient.spring.jdbc.EventuateJdbcEventStoreConfiguration; import io.eventuate.javaclient.spring.jdbc.IdGenerator; import io.eventuate.javaclient.spring.jdbc.IdGeneratorImpl; import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts.AccountCreditedEvent; +import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountChangeInfo; import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountTransactionInfo; import org.junit.Test; import org.junit.runner.RunWith; @@ -54,7 +55,7 @@ public class AccountInfoUpdateServiceTest { accountInfoUpdateService.create(accountId, customerId, title, initialBalance, description, version); - AccountInfo accountInfo = accountQueryService.findByAccountId(accountId).get(); + AccountInfo accountInfo = accountQueryService.findByAccountId(accountId); assertEquals(accountId, accountInfo.getId()); assertEquals(customerId, accountInfo.getCustomerId()); @@ -76,7 +77,7 @@ public class AccountInfoUpdateServiceTest { accountInfoUpdateService.updateBalance(accountId, changeId, 500, change); - accountInfo = accountQueryService.findByAccountId(accountId).get(); + accountInfo = accountQueryService.findByAccountId(accountId); assertEquals(initialBalance.add(new BigDecimal(5)).longValue() * 100, accountInfo.getBalance()); assertFalse(accountInfo.getChanges().isEmpty()); @@ -88,10 +89,26 @@ public class AccountInfoUpdateServiceTest { accountInfoUpdateService.addTransaction(eventId, accountId, ti); - accountInfo = accountQueryService.findByAccountId(accountId).get(); + accountInfo = accountQueryService.findByAccountId(accountId); assertFalse(accountInfo.getTransactions().isEmpty()); assertEquals(ti, accountInfo.getTransactions().get(0)); } + @Test + public void shouldHandleDuplicateSaveAccountInfo() throws ExecutionException, InterruptedException { + IdGenerator x = new IdGeneratorImpl(); + String accountId = x.genId().asString(); + String customerId = x.genId().asString(); + String version = x.genId().asString(); + + String title = "Checking account"; + BigDecimal initialBalance = new BigDecimal("1345"); + String description = "Some account"; + + accountInfoUpdateService.create(accountId, customerId, title, initialBalance, description, version); + accountInfoUpdateService.create(accountId, customerId, title, initialBalance, description, version); + + + } } \ No newline at end of file diff --git a/java-spring/accounts-query-side-web/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/web/queryside/accounts/AccountQueryController.java b/java-spring/accounts-query-side-web/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/web/queryside/accounts/AccountQueryController.java index 3521389..9609985 100644 --- a/java-spring/accounts-query-side-web/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/web/queryside/accounts/AccountQueryController.java +++ b/java-spring/accounts-query-side-web/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/web/queryside/accounts/AccountQueryController.java @@ -1,18 +1,19 @@ package net.chrisrichardson.eventstore.javaexamples.banking.web.queryside.accounts; +import com.fasterxml.jackson.databind.ObjectMapper; import net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.accounts.AccountInfo; import net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.accounts.AccountNotFoundException; import net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.accounts.AccountQueryService; -import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountTransactionInfo; -import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.GetAccountResponse; +import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.math.BigDecimal; +import java.util.ArrayList; import java.util.List; -import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; @RestController @@ -26,21 +27,35 @@ public class AccountQueryController { } @RequestMapping(value = "/accounts/{accountId}", method = RequestMethod.GET) - public CompletableFuture get(@PathVariable String accountId) { - return accountInfoQueryService.findByAccountId(accountId) - .thenApply(accountInfo -> new GetAccountResponse(accountInfo.getId(), new BigDecimal(accountInfo.getBalance()), accountInfo.getTitle(), accountInfo.getDescription())); + public ResponseEntity get(@PathVariable String accountId) { + AccountInfo accountInfo = accountInfoQueryService.findByAccountId(accountId); + return ResponseEntity.ok().body(new GetAccountResponse(accountInfo.getId(), new BigDecimal(accountInfo.getBalance()), accountInfo.getTitle(), accountInfo.getDescription())); } - @RequestMapping(value = "/accounts", method = RequestMethod.GET) - public CompletableFuture> getAccountsForCustomer(@RequestParam("customerId") String customerId) { - return accountInfoQueryService.findByCustomerId(customerId) - .thenApply(accountInfoList -> accountInfoList.stream().map(accountInfo -> new GetAccountResponse(accountInfo.getId(), new BigDecimal(accountInfo.getBalance()), accountInfo.getTitle(), accountInfo.getDescription())).collect(Collectors.toList())); + @RequestMapping(value = "/customers/{customerId}/accounts", method = RequestMethod.GET) + public ResponseEntity getAccountsForCustomer(@PathVariable("customerId") String customerId) { + return ResponseEntity.ok().body( + new GetAccountsResponse( + accountInfoQueryService.findByCustomerId(customerId) + .stream() + .map(accountInfo -> new GetAccountResponse( + accountInfo.getId(), + new BigDecimal(accountInfo.getBalance()), + accountInfo.getTitle(), + accountInfo.getDescription())) + .collect(Collectors.toList()) + ) + ); } @RequestMapping(value = "/accounts/{accountId}/history", method = RequestMethod.GET) - public CompletableFuture> getTransactionsHistory(@PathVariable String accountId) { - return accountInfoQueryService.findByAccountId(accountId) - .thenApply(AccountInfo::getTransactions); + public ResponseEntity getTransactionsHistory(@PathVariable String accountId) { + AccountInfo accountInfo = accountInfoQueryService.findByAccountId(accountId); + List historyEntries = new ArrayList<>(); + historyEntries.add(new AccountOpenInfo(accountInfo.getDate(), AccountHistoryEntry.EntryType.account)); + accountInfo.getTransactions().forEach(historyEntries::add); + + return ResponseEntity.ok().body(new AccountHistoryResponse(historyEntries)); } @ResponseStatus(value= HttpStatus.NOT_FOUND, reason="account not found") diff --git a/java-spring/api-gateway-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/apigateway/controller/GatewayController.java b/java-spring/api-gateway-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/apigateway/controller/GatewayController.java index 941f175..4cb2ccb 100755 --- a/java-spring/api-gateway-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/apigateway/controller/GatewayController.java +++ b/java-spring/api-gateway-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/apigateway/controller/GatewayController.java @@ -4,6 +4,7 @@ import net.chrisrichardson.eventstore.javaexamples.banking.apigateway.ApiGateway import net.chrisrichardson.eventstore.javaexamples.banking.apigateway.utils.ContentRequestTransformer; import net.chrisrichardson.eventstore.javaexamples.banking.apigateway.utils.HeadersRequestTransformer; import net.chrisrichardson.eventstore.javaexamples.banking.apigateway.utils.URLRequestTransformer; +import org.apache.http.Header; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpUriRequest; @@ -12,8 +13,10 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.util.MultiValueMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException; @@ -26,6 +29,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.net.URISyntaxException; import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.springframework.web.bind.annotation.RequestMethod.GET; import static org.springframework.web.bind.annotation.RequestMethod.POST; @@ -52,13 +56,19 @@ public class GatewayController { .build(); } - @RequestMapping(value = "/**", method = {GET, POST}) + @RequestMapping(value = {"/accounts**","/customers**","/transfers**","/login","/user"}, method = {GET, POST}) public ResponseEntity proxyRequest(HttpServletRequest request) throws NoSuchRequestHandlingMethodException, IOException, URISyntaxException { HttpUriRequest proxiedRequest = createHttpUriRequest(request); logger.info("request: {}", proxiedRequest); HttpResponse proxiedResponse = httpClient.execute(proxiedRequest); logger.info("Response {}", proxiedResponse.getStatusLine().getStatusCode()); - return new ResponseEntity<>(read(proxiedResponse.getEntity().getContent()), HttpStatus.valueOf(proxiedResponse.getStatusLine().getStatusCode())); + return new ResponseEntity<>(read(proxiedResponse.getEntity().getContent()), processHeaders(proxiedResponse.getAllHeaders()), HttpStatus.valueOf(proxiedResponse.getStatusLine().getStatusCode())); + } + + private HttpHeaders processHeaders(Header[] headers) { + HttpHeaders result = new HttpHeaders(); + Stream.of(headers).forEach( h -> result.set(h.getName(), h.getValue())); + return result; } private HttpUriRequest createHttpUriRequest(HttpServletRequest request) throws URISyntaxException, NoSuchRequestHandlingMethodException, IOException { diff --git a/java-spring/backend-integration-tests/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/MoneyTransferIntegrationTest.java b/java-spring/backend-integration-tests/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/MoneyTransferIntegrationTest.java index 6516ee4..0f7df9c 100644 --- a/java-spring/backend-integration-tests/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/MoneyTransferIntegrationTest.java +++ b/java-spring/backend-integration-tests/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/MoneyTransferIntegrationTest.java @@ -6,7 +6,7 @@ import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.a import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.accounts.AccountService; import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.transactions.MoneyTransfer; import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.transactions.MoneyTransferService; -import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.transactions.TransferState; +import net.chrisrichardson.eventstore.javaexamples.banking.common.transactions.TransferState; import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.TransferDetails; import org.junit.Assert; import org.junit.Test; diff --git a/java-spring/backend-integration-tests/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountQuerySideIntegrationTest.java b/java-spring/backend-integration-tests/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountQuerySideIntegrationTest.java index bb1bfbd..46cba9b 100644 --- a/java-spring/backend-integration-tests/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountQuerySideIntegrationTest.java +++ b/java-spring/backend-integration-tests/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountQuerySideIntegrationTest.java @@ -6,7 +6,7 @@ import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.a import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.accounts.AccountService; import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.transactions.MoneyTransfer; import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.transactions.MoneyTransferService; -import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.transactions.TransferState; +import net.chrisrichardson.eventstore.javaexamples.banking.common.transactions.TransferState; import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.TransferDetails; import org.junit.Assert; import org.junit.Test; @@ -17,6 +17,7 @@ import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.math.BigDecimal; +import java.util.concurrent.CompletableFuture; import static net.chrisrichardson.eventstorestore.javaexamples.testutil.TestUtil.await; import static net.chrisrichardson.eventstorestore.javaexamples.testutil.TestUtil.eventually; @@ -55,10 +56,10 @@ public class AccountQuerySideIntegrationTest { updatedTransaction -> Assert.assertEquals(TransferState.COMPLETED, updatedTransaction.getEntity().getState())); eventually( - () -> accountQueryService.findByAccountId(fromAccount.getEntityId()), + () -> CompletableFuture.completedFuture(accountQueryService.findByAccountId(fromAccount.getEntityId())), accountInfo -> Assert.assertEquals(70 * 100, accountInfo.getBalance())); eventually( - () -> accountQueryService.findByAccountId(toAccount.getEntityId()), + () -> CompletableFuture.completedFuture(accountQueryService.findByAccountId(toAccount.getEntityId())), accountInfo -> Assert.assertEquals(380 * 100, accountInfo.getBalance())); } } diff --git a/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountChangeInfo.java b/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountChangeInfo.java new file mode 100644 index 0000000..6e4eeb5 --- /dev/null +++ b/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountChangeInfo.java @@ -0,0 +1,80 @@ +package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +import java.util.Date; + +public class AccountChangeInfo { + + private String changeId; + private String transactionId; + private String transactionType; + private long amount; + private long balanceDelta; + + public AccountChangeInfo() { + } + + public AccountChangeInfo(String changeId, String transactionId, String transactionType, long amount, long balanceDelta) { + this(new Date(), changeId, transactionId, transactionType, amount, balanceDelta); + } + + public AccountChangeInfo(Date date, String changeId, String transactionId, String transactionType, long amount, long balanceDelta) { + this.changeId = changeId; + this.transactionId = transactionId; + this.transactionType = transactionType; + this.amount = amount; + this.balanceDelta = balanceDelta; + } + + public String getChangeId() { + return changeId; + } + + public void setChangeId(String changeId) { + this.changeId = changeId; + } + + public String getTransactionId() { + return transactionId; + } + + public void setTransactionId(String transactionId) { + this.transactionId = transactionId; + } + + public String getTransactionType() { + return transactionType; + } + + public void setTransactionType(String transactionType) { + this.transactionType = transactionType; + } + + public long getAmount() { + return amount; + } + + public void setAmount(long amount) { + this.amount = amount; + } + + public long getBalanceDelta() { + return balanceDelta; + } + + public void setBalanceDelta(long balanceDelta) { + this.balanceDelta = balanceDelta; + } + + @Override + public boolean equals(Object o) { + return EqualsBuilder.reflectionEquals(this, o); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } +} diff --git a/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountHistoryEntry.java b/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountHistoryEntry.java new file mode 100644 index 0000000..f91c2e7 --- /dev/null +++ b/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountHistoryEntry.java @@ -0,0 +1,50 @@ +package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +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") +@JsonSubTypes({ + @JsonSubTypes.Type(value = AccountTransactionInfo.class, name = "transaction"), + @JsonSubTypes.Type(value = AccountOpenInfo.class, name = "account") +}) +public class AccountHistoryEntry { + + protected Date date; + protected EntryType entryType; + + public AccountHistoryEntry() { + } + + public AccountHistoryEntry(Date date, EntryType entryType) { + this.date = date; + this.entryType = entryType; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public EntryType getEntryType() { + return entryType; + } + + public void setEntryType(EntryType entryType) { + this.entryType = entryType; + } + + public enum EntryType { + transaction, account + } +} diff --git a/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountHistoryResponse.java b/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountHistoryResponse.java new file mode 100644 index 0000000..b20d958 --- /dev/null +++ b/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountHistoryResponse.java @@ -0,0 +1,26 @@ +package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts; + +import java.util.List; + +/** + * Created by popikyardo on 9/1/16. + */ +public class AccountHistoryResponse { + private List transactionsHistory; + + public AccountHistoryResponse() { + } + + public AccountHistoryResponse(List transactionsHistory) { + + this.transactionsHistory = transactionsHistory; + } + + public List getTransactionsHistory() { + return transactionsHistory; + } + + public void setTransactionsHistory(List transactionsHistory) { + this.transactionsHistory = transactionsHistory; + } +} diff --git a/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountOpenInfo.java b/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountOpenInfo.java new file mode 100644 index 0000000..8136b22 --- /dev/null +++ b/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountOpenInfo.java @@ -0,0 +1,16 @@ +package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts; + +import java.util.Date; + +/** + * Created by popikyardo on 9/1/16. + */ +public class AccountOpenInfo extends AccountHistoryEntry { + + public AccountOpenInfo() { + } + + public AccountOpenInfo(Date date, EntryType entryType) { + super(date, entryType); + } +} diff --git a/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountTransactionInfo.java b/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountTransactionInfo.java index d168bf5..6cc88d5 100644 --- a/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountTransactionInfo.java +++ b/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountTransactionInfo.java @@ -1,19 +1,20 @@ package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts; +import net.chrisrichardson.eventstore.javaexamples.banking.common.transactions.TransferState; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; import java.util.Date; -public class AccountTransactionInfo { +public class AccountTransactionInfo extends AccountHistoryEntry{ private String transactionId; private String fromAccountId; private String toAccountId; private long amount; - private Date date; private String description; + private TransferState status = TransferState.INITIAL; public AccountTransactionInfo() { } @@ -35,6 +36,7 @@ public class AccountTransactionInfo { this.amount = amount; this.date = date; this.description = description; + this.entryType = EntryType.transaction; } public String getTransactionId() { @@ -69,14 +71,6 @@ public class AccountTransactionInfo { this.amount = amount; } - public Date getDate() { - return date; - } - - public void setDate(Date date) { - this.date = date; - } - public String getDescription() { return description; } @@ -85,6 +79,14 @@ public class AccountTransactionInfo { this.description = description; } + public TransferState getStatus() { + return status; + } + + public void setStatus(TransferState status) { + this.status = status; + } + @Override public boolean equals(Object o) { return EqualsBuilder.reflectionEquals(this, o); diff --git a/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/GetAccountsResponse.java b/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/GetAccountsResponse.java new file mode 100644 index 0000000..814f3f8 --- /dev/null +++ b/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/GetAccountsResponse.java @@ -0,0 +1,25 @@ +package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts; + +import java.util.List; + +/** + * Created by popikyardo on 9/1/16. + */ +public class GetAccountsResponse { + private List accounts; + + public GetAccountsResponse() { + } + + public GetAccountsResponse(List accounts) { + this.accounts = accounts; + } + + public List getAccounts() { + return accounts; + } + + public void setAccounts(List accounts) { + this.accounts = accounts; + } +} diff --git a/java-spring/transactions-command-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/commandside/transactions/TransferState.java b/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/transactions/TransferState.java similarity index 51% rename from java-spring/transactions-command-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/commandside/transactions/TransferState.java rename to java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/transactions/TransferState.java index 539d2ad..993f12d 100644 --- a/java-spring/transactions-command-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/commandside/transactions/TransferState.java +++ b/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/transactions/TransferState.java @@ -1,4 +1,4 @@ -package net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.transactions; +package net.chrisrichardson.eventstore.javaexamples.banking.common.transactions; public enum TransferState { NEW, INITIAL, DEBITED, COMPLETED, FAILED_DUE_TO_INSUFFICIENT_FUNDS diff --git a/java-spring/customers-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/customers/CustomerInfoUpdateService.java b/java-spring/customers-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/customers/CustomerInfoUpdateService.java index fd70386..3964683 100644 --- a/java-spring/customers-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/customers/CustomerInfoUpdateService.java +++ b/java-spring/customers-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/customers/CustomerInfoUpdateService.java @@ -5,6 +5,7 @@ import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.Quer import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.ToAccountInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.dao.DuplicateKeyException; import java.util.Collections; @@ -13,36 +14,38 @@ import java.util.Collections; */ public class CustomerInfoUpdateService { - private Logger logger = LoggerFactory.getLogger(getClass()); + private Logger logger = LoggerFactory.getLogger(getClass()); - private QuerySideCustomerRepository accountInfoRepository; + private QuerySideCustomerRepository querySideCustomerRepository; - public CustomerInfoUpdateService(QuerySideCustomerRepository accountInfoRepository) { - this.accountInfoRepository = accountInfoRepository; - } - - public void create(String id, CustomerInfo customerInfo) { - try { - accountInfoRepository.save(new QuerySideCustomer(id, - customerInfo.getName(), - customerInfo.getEmail(), - customerInfo.getSsn(), - customerInfo.getPhoneNumber(), - customerInfo.getAddress(), - Collections.emptyMap() - ) - ); - logger.info("Saved in mongo"); - } catch (Throwable t) { - logger.error("Error during saving: ", t); - throw new RuntimeException(t); + public CustomerInfoUpdateService(QuerySideCustomerRepository querySideCustomerRepository) { + this.querySideCustomerRepository = querySideCustomerRepository; } - } - public void addToAccount(String id, ToAccountInfo accountInfo) { - QuerySideCustomer customer = accountInfoRepository.findOne(id); - customer.getToAccounts().put(accountInfo.getId(), accountInfo); - accountInfoRepository.save(customer); - } + public void create(String id, CustomerInfo customerInfo) { + try { + querySideCustomerRepository.save(new QuerySideCustomer(id, + customerInfo.getName(), + customerInfo.getEmail(), + customerInfo.getSsn(), + customerInfo.getPhoneNumber(), + customerInfo.getAddress(), + Collections.emptyMap() + ) + ); + 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); + customer.getToAccounts().put(accountInfo.getId(), accountInfo); + querySideCustomerRepository.save(customer); + } } diff --git a/java-spring/customers-query-side-service/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/web/CustomersQuerySideServiceIntegrationTest.java b/java-spring/customers-query-side-service/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/web/CustomersQuerySideServiceIntegrationTest.java index fb4cd23..badb967 100644 --- a/java-spring/customers-query-side-service/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/web/CustomersQuerySideServiceIntegrationTest.java +++ b/java-spring/customers-query-side-service/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/web/CustomersQuerySideServiceIntegrationTest.java @@ -1,9 +1,8 @@ package net.chrisrichardson.eventstore.javaexamples.banking.web; -import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.*; +import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerInfo; +import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerResponse; import net.chrisrichardson.eventstorestore.javaexamples.testutil.CustomersTestUtils; -import org.apache.tomcat.jni.Thread; -import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -13,7 +12,6 @@ import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.web.client.RestTemplate; -import rx.Observable; import javax.annotation.PostConstruct; @@ -51,12 +49,6 @@ public class CustomersQuerySideServiceIntegrationTest { final CustomerResponse customerResponse = restTemplate.postForEntity(baseUrl("/customers"), customerInfo, CustomerResponse.class).getBody(); final String customerId = customerResponse.getId(); - try { - java.lang.Thread.sleep(10000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - customersTestUtils.assertCustomerResponse(customerId, customerInfo); } diff --git a/java-spring/docker-compose-eventuate-local.yml b/java-spring/docker-compose-eventuate-local.yml index 0f347d8..cd542c7 100644 --- a/java-spring/docker-compose-eventuate-local.yml +++ b/java-spring/docker-compose-eventuate-local.yml @@ -3,7 +3,7 @@ apigateway: working_dir: /app volumes: - ./api-gateway-service/build/libs:/app - command: java -jar /app/api-gateway-service.jar --accounts.commandside.service.host=accountscommandside --transactions.commandside.service.host=transactionscommandside --accounts.queryside.service.host=accountsqueryside --customers.commandside.service.host=customerscommandside --customers.queryside.service.host=customersqueryside + command: java -jar /app/api-gateway-service.jar --accounts.commandside.service.host=accountscommandside --transfers.commandside.service.host=transactionscommandside --accounts.queryside.service.host=accountsqueryside --customers.commandside.service.host=customerscommandside --customers.queryside.service.host=customersqueryside ports: - "8080:8080" links: diff --git a/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/AbstractRestAPITest.java b/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/AbstractRestAPITest.java index 6055ed1..a0faecb 100644 --- a/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/AbstractRestAPITest.java +++ b/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/AbstractRestAPITest.java @@ -1,9 +1,6 @@ package net.chrisrichardson.eventstorestore.javaexamples.testutil; -import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountTransactionInfo; -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.GetAccountResponse; +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; @@ -51,12 +48,6 @@ public abstract class AbstractRestAPITest { Assert.assertNotNull(fromAccountId); Assert.assertNotNull(toAccountId); - try { - Thread.sleep(10000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - assertAccountBalance(fromAccountId, initialFromAccountBalance); assertAccountBalance(toAccountId, initialToAccountBalance); @@ -68,21 +59,21 @@ public abstract class AbstractRestAPITest { assertAccountBalance(toAccountId, finalToAccountBalance); eventually( - new Producer() { + new Producer() { @Override - public CompletableFuture produce() { + public CompletableFuture produce() { return CompletableFuture.completedFuture(getAuthenticatedRestTemplate().getForEntity(baseUrl("/accounts/" + fromAccountId + "/history"), - AccountTransactionInfo[].class)); + AccountHistoryResponse.class)); } }, - new Verifier() { + new Verifier() { @Override - public void verify(AccountTransactionInfo[] transactionInfos) { - Optional first = Arrays.asList(transactionInfos).stream().filter(ti -> ti.getTransactionId().equals(moneyTransfer.getMoneyTransferId())).findFirst(); + public void verify(AccountHistoryResponse accountHistoryResponse) { + Optional first = accountHistoryResponse.getTransactionsHistory().stream().filter( ahe -> ahe.getEntryType() == AccountHistoryEntry.EntryType.transaction && ((AccountTransactionInfo)ahe).getTransactionId().equals(moneyTransfer.getMoneyTransferId())).findFirst(); assertTrue(first.isPresent()); - AccountTransactionInfo ti = first.get(); + AccountTransactionInfo ti = (AccountTransactionInfo)first.get(); assertEquals(fromAccountId, ti.getFromAccountId()); assertEquals(toAccountId, ti.getToAccountId()); @@ -104,12 +95,6 @@ public abstract class AbstractRestAPITest { Assert.assertNotNull(customerId); assertEquals(customerInfo, customerResponse.getCustomerInfo()); - try { - Thread.sleep(10000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - getCustomersTestUtils().assertCustomerResponse(customerId, customerInfo); final CreateAccountResponse account = getAuthenticatedRestTemplate().postForEntity(baseUrl("/accounts"), @@ -123,17 +108,17 @@ public abstract class AbstractRestAPITest { assertAccountBalance(accountId, initialFromAccountBalance); eventually( - new Producer() { + new Producer() { @Override - public CompletableFuture produce() { - return CompletableFuture.completedFuture(getAuthenticatedRestTemplate().getForEntity(baseUrl("/accounts?customerId=" + customerId), - GetAccountResponse[].class)); + public CompletableFuture produce() { + return CompletableFuture.completedFuture(getAuthenticatedRestTemplate().getForEntity(baseUrl("/customer/"+customerId+"/accounts"), + GetAccountsResponse.class)); } }, - new Verifier() { + new Verifier() { @Override - public void verify(GetAccountResponse[] accountResponses) { - assertTrue(Arrays.asList(accountResponses).stream().filter(acc -> acc.getAccountId().equals(accountId)).findFirst().isPresent()); + public void verify(GetAccountsResponse accountResponses) { + assertTrue(accountResponses.getAccounts().stream().filter(acc -> acc.getAccountId().equals(accountId)).findFirst().isPresent()); } }); } diff --git a/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/AuthenticatedRestTemplate.java b/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/AuthenticatedRestTemplate.java index bd980e4..991c18e 100644 --- a/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/AuthenticatedRestTemplate.java +++ b/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/AuthenticatedRestTemplate.java @@ -1,6 +1,5 @@ package net.chrisrichardson.eventstorestore.javaexamples.testutil; -import net.chrisrichardson.eventstore.javaexamples.banking.commonauth.utils.BasicAuthUtils; import org.springframework.http.HttpMethod; import org.springframework.web.client.RestTemplate; diff --git a/java-spring/common-auth/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/commonauth/utils/BasicAuthUtils.java b/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/BasicAuthUtils.java similarity index 95% rename from java-spring/common-auth/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/commonauth/utils/BasicAuthUtils.java rename to java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/BasicAuthUtils.java index 4f29ba1..da496a9 100644 --- a/java-spring/common-auth/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/commonauth/utils/BasicAuthUtils.java +++ b/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/BasicAuthUtils.java @@ -1,4 +1,4 @@ -package net.chrisrichardson.eventstore.javaexamples.banking.commonauth.utils; +package net.chrisrichardson.eventstorestore.javaexamples.testutil; import org.apache.tomcat.util.codec.binary.Base64; import org.springframework.http.*; diff --git a/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/CustomersTestUtils.java b/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/CustomersTestUtils.java index 4fc4fe1..a9e6e6e 100644 --- a/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/CustomersTestUtils.java +++ b/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/CustomersTestUtils.java @@ -6,7 +6,6 @@ import org.springframework.web.client.RestTemplate; import java.util.concurrent.CompletableFuture; -import static net.chrisrichardson.eventstorestore.javaexamples.testutil.TestUtil.awaitSuccessfulRequest; import static net.chrisrichardson.eventstorestore.javaexamples.testutil.TestUtil.eventually; /** diff --git a/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/TestUtil.java b/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/TestUtil.java index 025cdb1..2c84554 100644 --- a/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/TestUtil.java +++ b/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/TestUtil.java @@ -1,7 +1,5 @@ package net.chrisrichardson.eventstorestore.javaexamples.testutil; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import rx.Observable; import rx.Subscriber; import rx.functions.Action1; @@ -13,7 +11,6 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import java.util.function.Supplier; public class TestUtil { @@ -25,18 +22,6 @@ public class TestUtil { } } - public static T awaitSuccessfulRequest(Supplier> func, Func1 predicate) { - try { - return Observable.interval(400, TimeUnit.MILLISECONDS) - .take(50) - .map(x -> func.get()) - .filter(re -> re.getStatusCode().equals(HttpStatus.OK) && re.getBody() != null && predicate.call(re.getBody())) - .toBlocking().first().getBody(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - static class Tuple2 { private A first; @@ -52,7 +37,7 @@ public class TestUtil { } - static class Success implements Outcome { + static class Success implements Outcome { T value; @@ -69,51 +54,26 @@ public class TestUtil { } } - public static void eventually(final Producer producer, final Verifier verifier) { - final int n = 150; - Object possibleException = Observable.timer(0, 200, TimeUnit.MILLISECONDS).flatMap(new Func1>>() { - - @Override - public Observable> call(Long aLong) { - try { - return fromCompletableFuture(producer.produce()).map(new Func1>() { - @Override - public Outcome call(T t) { - return new Success(t); - } - }); - } catch (Exception e) { - Outcome value = new Failure(e); - return Observable.just(value); - } + public static void eventually(Producer producer, Verifier predicate) { + Throwable laste = null; + for (int i = 0; i < 30 ; i++) { + try { + T x = producer.produce().get(30, TimeUnit.SECONDS); + predicate.verify(x); + return; + } catch (Throwable t) { + laste = t; } - }).map(new Func1, Throwable>() { - @Override - public Throwable call(Outcome t) { - try { - if (t instanceof Success) { - verifier.verify(((Success) t).value); - return null; - } else - return ((Failure) t).t; - } catch (Throwable e) { - return e; - } + try { + TimeUnit.SECONDS.sleep(1); + } catch (InterruptedException e) { + throw new RuntimeException(e); } - }).take(n).zipWith(Observable.range(0, n), new Func2>() { - @Override - public Tuple2 call(Throwable e, Integer idx) { - return new Tuple2(e, idx); - } - }).skipWhile(new Func1, Boolean>() { - @Override - public Boolean call(Tuple2 tuple2) { - return tuple2.first != null && tuple2.second < n - 1; - } - }).first().toBlocking().getIterator().next().first; - - if (possibleException != null) - throw new RuntimeException((Throwable) possibleException); + } + if (laste != null) + throw new RuntimeException("Last exception was", laste); + else + throw new RuntimeException("predicate never satisfied"); } private static Observable fromCompletableFuture(CompletableFuture future) { diff --git a/java-spring/transactions-command-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/commandside/transactions/MoneyTransfer.java b/java-spring/transactions-command-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/commandside/transactions/MoneyTransfer.java index 896e8b7..849175a 100644 --- a/java-spring/transactions-command-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/commandside/transactions/MoneyTransfer.java +++ b/java-spring/transactions-command-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/commandside/transactions/MoneyTransfer.java @@ -4,6 +4,7 @@ import io.eventuate.Event; import io.eventuate.EventUtil; import io.eventuate.ReflectiveMutableCommandProcessingAggregate; import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.*; +import net.chrisrichardson.eventstore.javaexamples.banking.common.transactions.TransferState; import java.util.List;