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 AccountQueryService(AccountInfoRepository accountInfoRepository) { 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/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 0f9aa61..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 @@ -55,7 +55,7 @@ public void shouldSaveAccountInfo() throws ExecutionException, InterruptedExcept 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()); @@ -77,7 +77,7 @@ public void shouldSaveAccountInfo() throws ExecutionException, InterruptedExcept 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()); @@ -89,7 +89,7 @@ public void shouldSaveAccountInfo() throws ExecutionException, InterruptedExcept accountInfoUpdateService.addTransaction(eventId, accountId, ti); - accountInfo = accountQueryService.findByAccountId(accountId).get(); + accountInfo = accountQueryService.findByAccountId(accountId); assertFalse(accountInfo.getTransactions().isEmpty()); assertEquals(ti, accountInfo.getTransactions().get(0)); 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 83e50c4..52d4f92 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 @@ -4,12 +4,10 @@ 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.AccountHistoryEntry; -import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountHistoryResponse; -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; @@ -29,26 +27,33 @@ public AccountQueryController(AccountQueryService accountInfoQueryService) { } @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 = "/customer/{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) { - CompletableFuture res = accountInfoQueryService.findByAccountId(accountId) - .thenApply(accountInfo -> new AccountHistoryResponse(new AccountHistoryEntry(accountInfo.getDate()), + public ResponseEntity getTransactionsHistory(@PathVariable String accountId) { + AccountInfo accountInfo = accountInfoQueryService.findByAccountId(accountId); + return ResponseEntity.ok().body(new AccountHistoryResponse(new AccountHistoryEntry(accountInfo.getDate()), accountInfo.getTransactions(), - accountInfo.getChanges()) - ); - - return res; + accountInfo.getChanges())); } @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..7767892 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.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.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.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; @@ -58,7 +62,13 @@ public ResponseEntity proxyRequest(HttpServletRequest request) throws No 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/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..7d6d0df 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 @@ -17,6 +17,7 @@ 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 void shouldUpdateQuerySide() throws Exception { 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/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/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 1f49a90..391668e 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 @@ -108,17 +108,17 @@ public void shouldCreateAccountsAndGetByCustomer() { assertAccountBalance(accountId, initialFromAccountBalance); eventually( - new Producer() { + new Producer() { @Override - public CompletableFuture produce() { + public CompletableFuture produce() { return CompletableFuture.completedFuture(getAuthenticatedRestTemplate().getForEntity(baseUrl("/accounts?customerId=" + customerId), - GetAccountResponse[].class)); + 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()); } }); }