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 new file mode 100644 index 0000000..b988eb1 --- /dev/null +++ b/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountChangeInfo.java @@ -0,0 +1,31 @@ +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 abdfe38..46eab5d 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,9 +1,11 @@ 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.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; /** * Created by cer on 11/21/14. @@ -18,16 +20,11 @@ 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; @@ -37,7 +34,6 @@ public AccountInfo(String id, String customerId, String title, String descriptio this.changes = changes; this.transactions = transactions; this.version = version; - this.date = date; } public String getId() { @@ -71,8 +67,4 @@ public List getTransactions() { 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 2161ffb..ecc47fb 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,12 +1,9 @@ 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; @@ -41,9 +38,6 @@ public void create(String accountId, String customerId, String title, BigDecimal 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); @@ -70,13 +64,5 @@ public void updateBalance(String accountId, String changeId, long balanceDelta, 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 3dfa68b..fc4e12e 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,6 +1,9 @@ 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 { @@ -10,15 +13,15 @@ public AccountQueryService(AccountInfoRepository accountInfoRepository) { this.accountInfoRepository = accountInfoRepository; } - public AccountInfo findByAccountId(String accountId) { + public CompletableFuture findByAccountId(String accountId) { AccountInfo account = accountInfoRepository.findOne(accountId); if (account == null) - throw new AccountNotFoundException(accountId); + return CompletableFutureUtil.failedFuture(new AccountNotFoundException(accountId)); else - return account; + return CompletableFuture.completedFuture(account); } - public List findByCustomerId(String customerId) { - return accountInfoRepository.findByCustomerId(customerId); + public CompletableFuture> findByCustomerId(String customerId) { + return CompletableFuture.completedFuture(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 39ddded..047e894 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,14 +3,12 @@ import io.eventuate.DispatchedEvent; import io.eventuate.EventHandlerMethod; import io.eventuate.EventSubscriber; -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.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.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; @@ -65,30 +63,14 @@ public void recordTransfer(DispatchedEvent de) { @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 cbe048e..2b7baec 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,7 +4,6 @@ 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; @@ -55,7 +54,7 @@ public void shouldSaveAccountInfo() throws ExecutionException, InterruptedExcept accountInfoUpdateService.create(accountId, customerId, title, initialBalance, description, version); - AccountInfo accountInfo = accountQueryService.findByAccountId(accountId); + AccountInfo accountInfo = accountQueryService.findByAccountId(accountId).get(); assertEquals(accountId, accountInfo.getId()); assertEquals(customerId, accountInfo.getCustomerId()); @@ -77,7 +76,7 @@ public void shouldSaveAccountInfo() throws ExecutionException, InterruptedExcept accountInfoUpdateService.updateBalance(accountId, changeId, 500, change); - accountInfo = accountQueryService.findByAccountId(accountId); + accountInfo = accountQueryService.findByAccountId(accountId).get(); assertEquals(initialBalance.add(new BigDecimal(5)).longValue() * 100, accountInfo.getBalance()); assertFalse(accountInfo.getChanges().isEmpty()); @@ -89,26 +88,10 @@ public void shouldSaveAccountInfo() throws ExecutionException, InterruptedExcept accountInfoUpdateService.addTransaction(eventId, accountId, ti); - accountInfo = accountQueryService.findByAccountId(accountId); + accountInfo = accountQueryService.findByAccountId(accountId).get(); 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 9609985..3521389 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,19 +1,18 @@ 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.*; +import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountTransactionInfo; +import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.GetAccountResponse; 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 @@ -27,35 +26,21 @@ public AccountQueryController(AccountQueryService accountInfoQueryService) { } @RequestMapping(value = "/accounts/{accountId}", method = RequestMethod.GET) - 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())); + public CompletableFuture get(@PathVariable String accountId) { + return accountInfoQueryService.findByAccountId(accountId) + .thenApply(accountInfo -> new GetAccountResponse(accountInfo.getId(), new BigDecimal(accountInfo.getBalance()), accountInfo.getTitle(), accountInfo.getDescription())); } - @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", 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 = "/accounts/{accountId}/history", method = RequestMethod.GET) - 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)); + public CompletableFuture> getTransactionsHistory(@PathVariable String accountId) { + return accountInfoQueryService.findByAccountId(accountId) + .thenApply(AccountInfo::getTransactions); } @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 4cb2ccb..941f175 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,7 +4,6 @@ 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; @@ -13,10 +12,8 @@ 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; @@ -29,7 +26,6 @@ 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; @@ -56,19 +52,13 @@ public void init() { .build(); } - @RequestMapping(value = {"/accounts**","/customers**","/transfers**","/login","/user"}, method = {GET, POST}) + @RequestMapping(value = "/**", 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()), 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; + return new ResponseEntity<>(read(proxiedResponse.getEntity().getContent()), HttpStatus.valueOf(proxiedResponse.getStatusLine().getStatusCode())); } 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 0f7df9c..6516ee4 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.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.common.transactions.TransferState; +import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.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 46cba9b..bb1bfbd 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.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.common.transactions.TransferState; +import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.transactions.TransferState; import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.TransferDetails; import org.junit.Assert; import org.junit.Test; @@ -17,7 +17,6 @@ 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; @@ -56,10 +55,10 @@ public void shouldUpdateQuerySide() throws Exception { updatedTransaction -> Assert.assertEquals(TransferState.COMPLETED, updatedTransaction.getEntity().getState())); eventually( - () -> CompletableFuture.completedFuture(accountQueryService.findByAccountId(fromAccount.getEntityId())), + () -> accountQueryService.findByAccountId(fromAccount.getEntityId()), accountInfo -> Assert.assertEquals(70 * 100, accountInfo.getBalance())); eventually( - () -> CompletableFuture.completedFuture(accountQueryService.findByAccountId(toAccount.getEntityId())), + () -> accountQueryService.findByAccountId(toAccount.getEntityId()), accountInfo -> Assert.assertEquals(380 * 100, accountInfo.getBalance())); } } diff --git a/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/BasicAuthUtils.java b/java-spring/common-auth/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/commonauth/utils/BasicAuthUtils.java similarity index 95% rename from java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/BasicAuthUtils.java rename to java-spring/common-auth/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/commonauth/utils/BasicAuthUtils.java index da496a9..4f29ba1 100644 --- a/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/BasicAuthUtils.java +++ b/java-spring/common-auth/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/commonauth/utils/BasicAuthUtils.java @@ -1,4 +1,4 @@ -package net.chrisrichardson.eventstorestore.javaexamples.testutil; +package net.chrisrichardson.eventstore.javaexamples.banking.commonauth.utils; import org.apache.tomcat.util.codec.binary.Base64; import org.springframework.http.*; 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 deleted file mode 100644 index 6e4eeb5..0000000 --- a/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountChangeInfo.java +++ /dev/null @@ -1,80 +0,0 @@ -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 deleted file mode 100644 index f91c2e7..0000000 --- a/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountHistoryEntry.java +++ /dev/null @@ -1,50 +0,0 @@ -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 deleted file mode 100644 index b20d958..0000000 --- a/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountHistoryResponse.java +++ /dev/null @@ -1,26 +0,0 @@ -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 deleted file mode 100644 index 8136b22..0000000 --- a/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountOpenInfo.java +++ /dev/null @@ -1,16 +0,0 @@ -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 6cc88d5..d168bf5 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,20 +1,19 @@ 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 extends AccountHistoryEntry{ +public class AccountTransactionInfo { 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() { } @@ -36,7 +35,6 @@ public AccountTransactionInfo(String transactionId, String fromAccountId, String this.amount = amount; this.date = date; this.description = description; - this.entryType = EntryType.transaction; } public String getTransactionId() { @@ -71,20 +69,20 @@ public void setAmount(long amount) { this.amount = amount; } - public String getDescription() { - return description; + public Date getDate() { + return date; } - public void setDescription(String description) { - this.description = description; + public void setDate(Date date) { + this.date = date; } - public TransferState getStatus() { - return status; + public String getDescription() { + return description; } - public void setStatus(TransferState status) { - this.status = status; + public void setDescription(String description) { + this.description = description; } @Override 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 deleted file mode 100644 index 814f3f8..0000000 --- a/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/GetAccountsResponse.java +++ /dev/null @@ -1,25 +0,0 @@ -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/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 3964683..fd70386 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,7 +5,6 @@ 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; @@ -14,38 +13,36 @@ */ public class CustomerInfoUpdateService { - private Logger logger = LoggerFactory.getLogger(getClass()); - - private QuerySideCustomerRepository querySideCustomerRepository; - - public CustomerInfoUpdateService(QuerySideCustomerRepository querySideCustomerRepository) { - this.querySideCustomerRepository = querySideCustomerRepository; + private Logger logger = LoggerFactory.getLogger(getClass()); + + private QuerySideCustomerRepository accountInfoRepository; + + 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 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); - } + public void addToAccount(String id, ToAccountInfo accountInfo) { + QuerySideCustomer customer = accountInfoRepository.findOne(id); + customer.getToAccounts().put(accountInfo.getId(), accountInfo); + accountInfoRepository.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 badb967..fb4cd23 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,8 +1,9 @@ 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.*; 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; @@ -12,6 +13,7 @@ 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; @@ -49,6 +51,12 @@ public void shouldGetCustomerById() { 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 cd542c7..0f347d8 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 --transfers.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 --transactions.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 a0faecb..6055ed1 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,6 +1,9 @@ package net.chrisrichardson.eventstorestore.javaexamples.testutil; -import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.*; +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.customers.CustomerInfo; import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerResponse; import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.QuerySideCustomer; @@ -48,6 +51,12 @@ public void shouldCreateAccountsAndTransferMoney() { Assert.assertNotNull(fromAccountId); Assert.assertNotNull(toAccountId); + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + assertAccountBalance(fromAccountId, initialFromAccountBalance); assertAccountBalance(toAccountId, initialToAccountBalance); @@ -59,21 +68,21 @@ public void shouldCreateAccountsAndTransferMoney() { assertAccountBalance(toAccountId, finalToAccountBalance); eventually( - new Producer() { + new Producer() { @Override - public CompletableFuture produce() { + public CompletableFuture produce() { return CompletableFuture.completedFuture(getAuthenticatedRestTemplate().getForEntity(baseUrl("/accounts/" + fromAccountId + "/history"), - AccountHistoryResponse.class)); + AccountTransactionInfo[].class)); } }, - new Verifier() { + new Verifier() { @Override - public void verify(AccountHistoryResponse accountHistoryResponse) { - Optional first = accountHistoryResponse.getTransactionsHistory().stream().filter( ahe -> ahe.getEntryType() == AccountHistoryEntry.EntryType.transaction && ((AccountTransactionInfo)ahe).getTransactionId().equals(moneyTransfer.getMoneyTransferId())).findFirst(); + public void verify(AccountTransactionInfo[] transactionInfos) { + Optional first = Arrays.asList(transactionInfos).stream().filter(ti -> ti.getTransactionId().equals(moneyTransfer.getMoneyTransferId())).findFirst(); assertTrue(first.isPresent()); - AccountTransactionInfo ti = (AccountTransactionInfo)first.get(); + AccountTransactionInfo ti = first.get(); assertEquals(fromAccountId, ti.getFromAccountId()); assertEquals(toAccountId, ti.getToAccountId()); @@ -95,6 +104,12 @@ public void shouldCreateAccountsAndGetByCustomer() { 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"), @@ -108,17 +123,17 @@ public void shouldCreateAccountsAndGetByCustomer() { assertAccountBalance(accountId, initialFromAccountBalance); eventually( - new Producer() { + new Producer() { @Override - public CompletableFuture produce() { - return CompletableFuture.completedFuture(getAuthenticatedRestTemplate().getForEntity(baseUrl("/customer/"+customerId+"/accounts"), - GetAccountsResponse.class)); + public CompletableFuture produce() { + return CompletableFuture.completedFuture(getAuthenticatedRestTemplate().getForEntity(baseUrl("/accounts?customerId=" + customerId), + GetAccountResponse[].class)); } }, - new Verifier() { + new Verifier() { @Override - public void verify(GetAccountsResponse accountResponses) { - assertTrue(accountResponses.getAccounts().stream().filter(acc -> acc.getAccountId().equals(accountId)).findFirst().isPresent()); + public void verify(GetAccountResponse[] accountResponses) { + assertTrue(Arrays.asList(accountResponses).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 991c18e..bd980e4 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,5 +1,6 @@ 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/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 a9e6e6e..4fc4fe1 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,6 +6,7 @@ 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 2c84554..025cdb1 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,5 +1,7 @@ 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; @@ -11,6 +13,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.function.Supplier; public class TestUtil { @@ -22,6 +25,18 @@ public static T await(CompletableFuture o) { } } + 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; @@ -37,7 +52,7 @@ interface Outcome { } - static class Success implements Outcome { + static class Success implements Outcome { T value; @@ -54,26 +69,51 @@ public Failure(Throwable t) { } } - 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; + 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); + } } - try { - TimeUnit.SECONDS.sleep(1); - } catch (InterruptedException e) { - throw new RuntimeException(e); + }).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; + } } - } - if (laste != null) - throw new RuntimeException("Last exception was", laste); - else - throw new RuntimeException("predicate never satisfied"); + }).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); } 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 849175a..896e8b7 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,7 +4,6 @@ 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; diff --git a/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/transactions/TransferState.java b/java-spring/transactions-command-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/commandside/transactions/TransferState.java similarity index 51% rename from java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/transactions/TransferState.java rename to java-spring/transactions-command-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/commandside/transactions/TransferState.java index 993f12d..539d2ad 100644 --- a/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/transactions/TransferState.java +++ b/java-spring/transactions-command-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/commandside/transactions/TransferState.java @@ -1,4 +1,4 @@ -package net.chrisrichardson.eventstore.javaexamples.banking.common.transactions; +package net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.transactions; public enum TransferState { NEW, INITIAL, DEBITED, COMPLETED, FAILED_DUE_TO_INSUFFICIENT_FUNDS