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..577b939 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 @@ -16,18 +16,18 @@ public class AccountInfo { private String description; private long balance; private List changes; - private List transactions; + private Map 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) { + public AccountInfo(String id, String customerId, String title, String description, long balance, List changes, Map 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) { + public AccountInfo(String id, String customerId, String title, String description, long balance, List changes, Map transactions, String version, Date date) { this.id = id; this.customerId = customerId; @@ -61,11 +61,11 @@ public class AccountInfo { } public List getChanges() { - return changes; + return changes == null ? Collections.EMPTY_LIST : changes; } public List getTransactions() { - return transactions; + return transactions == null ? Collections.EMPTY_LIST : new ArrayList<>(transactions.values()); } public String getVersion() { 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..595e26a 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 @@ -31,32 +31,29 @@ public class AccountInfoUpdateService { public void create(String accountId, String customerId, String title, BigDecimal initialBalance, String description, String version) { try { - accountInfoRepository.save(new AccountInfo( - accountId, - customerId, - title, - description, - toIntegerRepr(initialBalance), - Collections.emptyList(), - Collections.emptyList(), - version)); + WriteResult x = mongoTemplate.upsert(new Query(where("id").is(accountId).and("version").exists(false)), + new Update() + .set("customerId", customerId) + .set("title", title) + .set("description", description) + .set("balance", toIntegerRepr(initialBalance)) + .set("version", version), + AccountInfo.class); 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); throw new RuntimeException(t); } } - public void addTransaction(String eventId, String fromAccountId, AccountTransactionInfo ti) { - mongoTemplate.updateMulti(new Query(where("id").is(fromAccountId)), /* wrong .and("version").lt(eventId) */ + public void addTransaction(String eventId, String accountId, AccountTransactionInfo ti) { + mongoTemplate.upsert(new Query(where("id").is(accountId)), new Update(). - push("transactions", ti). - set("version", eventId), + set("transactions." + eventId, ti), AccountInfo.class); } @@ -71,12 +68,10 @@ public class AccountInfoUpdateService { } 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); - } - + mongoTemplate.upsert(new Query(where("id").is(accountId)), + new Update(). + set("transactions." + transactionId +".status", status), + AccountInfo.class); } } 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..48ab21a 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 @@ -6,6 +6,7 @@ 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 net.chrisrichardson.eventstore.javaexamples.banking.common.transactions.TransferState; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -15,11 +16,9 @@ import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.web.WebAppConfiguration; import java.math.BigDecimal; import java.util.Date; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import static org.junit.Assert.*; @@ -108,7 +107,42 @@ public class AccountInfoUpdateServiceTest { accountInfoUpdateService.create(accountId, customerId, title, initialBalance, description, version); accountInfoUpdateService.create(accountId, customerId, title, initialBalance, description, version); + } + @Test + public void shouldUpdateTransactionStatus() { + 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); + + String transactionId = x.genId().asString(); + + AccountTransactionInfo transactionInfo = new AccountTransactionInfo(); + transactionInfo.setStatus(TransferState.INITIAL); + + accountInfoUpdateService.addTransaction(transactionId, accountId, transactionInfo); + + AccountInfo accountInfo = accountQueryService.findByAccountId(accountId); + assertEquals(accountId, accountInfo.getId()); + assertFalse(accountInfo.getTransactions().isEmpty()); + assertEquals(1, accountInfo.getTransactions().size()); + + assertEquals(TransferState.INITIAL, accountInfo.getTransactions().get(0).getStatus()); + + accountInfoUpdateService.updateTransactionStatus(accountId, transactionId, TransferState.COMPLETED); + + accountInfo = accountQueryService.findByAccountId(accountId); + assertEquals(accountId, accountInfo.getId()); + assertFalse(accountInfo.getTransactions().isEmpty()); + assertEquals(1, accountInfo.getTransactions().size()); + + assertEquals(TransferState.COMPLETED, accountInfo.getTransactions().get(0).getStatus()); } } \ No newline at end of file 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..44942a4 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 @@ -111,7 +111,7 @@ public abstract class AbstractRestAPITest { new Producer() { @Override public CompletableFuture produce() { - return CompletableFuture.completedFuture(getAuthenticatedRestTemplate().getForEntity(baseUrl("/customer/"+customerId+"/accounts"), + return CompletableFuture.completedFuture(getAuthenticatedRestTemplate().getForEntity(baseUrl("/customers/"+customerId+"/accounts"), GetAccountsResponse.class)); } },