Improved module name <functional-area>-<Command|Query>....

Standalone services now use the Event Store Server (many tests still use the embedded server)
This commit is contained in:
Chris Richardson
2015-04-14 19:08:07 -07:00
parent d166c9b852
commit 2e31853ad2
150 changed files with 1237 additions and 109 deletions

View File

@@ -1,5 +1,7 @@
This is the Scala/Spring version of the Event Sourcing/CQRS money transfer example application.
# About the application
This application consists of three microservices:
* Account Service - the command side business logic for Accounts
@@ -8,25 +10,28 @@ This application consists of three microservices:
The Account Service consists of the following modules:
* commandside-backend-accounts - the Account aggregate
* commandside-web-accounts - a REST API for creating and retrieving Accounts
* accounts-command-side-backend - the Account aggregate
* accounts-command-side-web - a REST API for creating and retrieving Accounts
* accounts-command-side-service - a standalone microservice
The Money Transfer Service consists of the following modules:
* commandside-backend-transactions - the MoneyTransfer aggregate
* commandside-web-transactions - a REST API for creating and retrieving Money Transfers
* transactions-command-side-backend - the MoneyTransfer aggregate
* transactions-command-side-web - a REST API for creating and retrieving Money Transfers
* transactions-command-side-service - a standalone microservice
The Query Service consists the following modules:
* queryside-backend - MongoDB-based, denormalized view of Accounts and MoneyTransfers
* queryside-web - a REST API for querying the denormalized view
* accounts-query-side-backend - MongoDB-based, denormalized view of Accounts and MoneyTransfers
* accounts-query-side-web - a REST API for querying the denormalized view
* accounts-query-side-service - a standalone microservice
In order to be used with the embedded Event Store, the three services are currently packaged as a single monolithic web application:
# Deploying the application
* monolithic-web - all-in-one, monolithic packaging of the application
These services can be deployed either as either separate standalone services using the Event Store server, or they can be deployed as a monolithic application for simpified integration testing.
As well as the above modules there are also:
The three services can also be packaged as a single monolithic web application in order to be used with the embedded Event Store:
* common-backend - code that is shared between the command side and the query side, primarily events and value objects
* backend-integration-tests - integrations tests for the backend
* monolithic-service - all-in-one, monolithic packaging of the application

View File

@@ -2,4 +2,4 @@ dependencies {
compile "org.scala-lang:scala-library:2.10.2"
compile project(":common-backend")
compile "net.chrisrichardson.eventstore.client:eventstore-client-event-handling:$eventStoreClientVersion"
}
}

View File

@@ -20,7 +20,8 @@ class TransferWorkflowAccountHandlers(eventStore: EventStore) extends CompoundEv
@EventHandlerMethod
val performCredit = handlerForEvent[DebitRecordedEvent] { de =>
existingEntity[Account](de.event.details.toAccountId) <== CreditAccountCommand(de.event.details.amount, de.entityId)
existingEntity[Account](de.event.details.toAccountId) <==
CreditAccountCommand(de.event.details.amount, de.entityId)
}
}

View File

@@ -0,0 +1,22 @@
apply plugin: 'scala'
apply plugin: 'spring-boot'
apply plugin: VerifyEventStoreEnvironmentPlugin
dependencies {
compile "org.scala-lang:scala-library:2.10.2"
compile project(":accounts-command-side-web")
compile "org.springframework.boot:spring-boot-starter-web"
compile "org.springframework.boot:spring-boot-starter-actuator"
compile "net.chrisrichardson.eventstore.client:eventstore-http-stomp-client:$eventStoreClientVersion"
testCompile "org.springframework.boot:spring-boot-starter-test"
testCompile scalaTestDependency
}
test {
ignoreFailures true
}

View File

@@ -0,0 +1,14 @@
package net.chrisrichardson.eventstore.examples.bank.web
import net.chrisrichardson.eventstore.client.config.EventStoreHttpClientConfiguration
import net.chrisrichardson.eventstore.examples.bank.web.accounts.CommandSideWebAccountsConfiguration
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.context.annotation._
@Configuration
@EnableAutoConfiguration
@Import(Array(classOf[CommandSideWebAccountsConfiguration], classOf[EventStoreHttpClientConfiguration]))
@ComponentScan
class AccountsCommandSideServiceConfiguration {
}

View File

@@ -0,0 +1,10 @@
package net.chrisrichardson.eventstore.examples.bank.web.main
import net.chrisrichardson.eventstore.examples.bank.web.AccountsCommandSideServiceConfiguration
import org.springframework.boot.SpringApplication
object AccountsCommandSideServiceMain {
def main(args: Array[String]) : Unit = SpringApplication.run(classOf[AccountsCommandSideServiceConfiguration], args :_ *)
}

View File

@@ -0,0 +1,32 @@
package net.chrisrichardson.eventstore.examples.bank.web
import net.chrisrichardson.eventstore.examples.bank.web.accounts.controllers.{CreateAccountRequest, CreateAccountResponse}
import org.junit.Assert
import org.junit.runner.RunWith
import org.scalatest.FlatSpec
import org.scalatest.junit.JUnitRunner
import org.springframework.boot.SpringApplication
import org.springframework.web.client.RestTemplate
@RunWith(classOf[JUnitRunner])
class AccountsCommandSideServiceIntegrationTest extends FlatSpec {
val sa = new SpringApplication(classOf[AccountsCommandSideServiceTestConfiguration])
val ctx = sa.run()
// var server = ctx.getBean(classOf[EmbeddedServletContainer])
val port = 8080
val baseUrl = s"http://localhost:$port/"
val restTemplate = ctx.getBean(classOf[RestTemplate])
it should "create account" in {
val CreateAccountResponse(accountId) = restTemplate.postForEntity(s"$baseUrl/accounts", CreateAccountRequest(BigDecimal(500)), classOf[CreateAccountResponse]).getBody
Assert.assertNotNull(accountId)
}
}

View File

@@ -0,0 +1,26 @@
package net.chrisrichardson.eventstore.examples.bank.web
import com.fasterxml.jackson.databind.ObjectMapper
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.context.annotation.{Bean, Import, Configuration}
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
import org.springframework.web.client.RestTemplate
import scala.collection.JavaConversions._
@Configuration
@Import(Array(classOf[AccountsCommandSideServiceConfiguration]))
class AccountsCommandSideServiceTestConfiguration {
@Bean
def restTemplate(scalaObjectMapper: ObjectMapper) = {
val restTemplate = new RestTemplate()
restTemplate.getMessageConverters foreach {
case mc: MappingJackson2HttpMessageConverter =>
mc.setObjectMapper(scalaObjectMapper)
case _ =>
}
restTemplate
}
}

View File

@@ -2,9 +2,9 @@ apply plugin: 'scala'
dependencies {
compile "org.scala-lang:scala-library:2.10.2"
compile project(":commandside-backend-accounts")
compile project(":web-common")
compile project(":accounts-command-side-backend")
compile project(":common-web")
testCompile "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
testCompile scalaTestDependency
}
}

View File

@@ -0,0 +1,17 @@
package net.chrisrichardson.eventstore.examples.bank.queryside
import net.chrisrichardson.eventstore.EntityId
class AccountInfoQueryService(accountInfoRepository : AccountInfoRepository) {
def findByAccountId(accountId : EntityId) : AccountInfo = {
val account = accountInfoRepository.findOne(accountId.id)
if (account == null)
throw new AccountNotFoundException(accountId)
else
account
}
}
class AccountNotFoundException(accountId : EntityId) extends RuntimeException("Account not found " + accountId)

View File

@@ -29,7 +29,10 @@ class AccountInfoUpdateService(accountInfoRepository : AccountInfoRepository, mo
logger.info("About to save")
try {
accountInfoRepository.save(AccountInfo(de.entityId.id, toIntegerRepr(de.event.initialBalance), Seq(), Seq(), de.eventId.asString))
if (de.event.initialBalance != null)
accountInfoRepository.save(AccountInfo(de.entityId.id, toIntegerRepr(de.event.initialBalance), Seq(), Seq(), de.eventId.asString))
else
logger.error("Event with initialBalance == null {}", de.entityId)
}
catch {
case t : Throwable =>

View File

@@ -0,0 +1,23 @@
apply plugin: 'scala'
apply plugin: 'spring-boot'
apply plugin: VerifyMongoDBConfigurationPlugin
apply plugin: VerifyEventStoreEnvironmentPlugin
dependencies {
compile "org.scala-lang:scala-library:2.10.2"
compile project(":accounts-query-side-web")
compile "org.springframework.boot:spring-boot-starter-web"
compile "org.springframework.boot:spring-boot-starter-actuator"
compile "net.chrisrichardson.eventstore.client:eventstore-http-stomp-client:$eventStoreClientVersion"
testCompile "org.springframework.boot:spring-boot-starter-test"
testCompile scalaTestDependency
}
test {
ignoreFailures true
}

View File

@@ -0,0 +1,14 @@
package net.chrisrichardson.eventstore.examples.bank.web
import net.chrisrichardson.eventstore.client.config.EventStoreHttpClientConfiguration
import net.chrisrichardson.eventstore.examples.bank.web.queryside.QuerySideWebConfiguration
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.context.annotation._
@Configuration
@EnableAutoConfiguration
@Import(Array(classOf[QuerySideWebConfiguration], classOf[EventStoreHttpClientConfiguration]))
@ComponentScan
class AccountsQuerySideServiceConfiguration {
}

View File

@@ -0,0 +1,10 @@
package net.chrisrichardson.eventstore.examples.bank.web.main
import net.chrisrichardson.eventstore.examples.bank.web.AccountsQuerySideServiceConfiguration
import org.springframework.boot.SpringApplication
object AccountsQuerySideServiceMain {
def main(args: Array[String]) : Unit = SpringApplication.run(classOf[AccountsQuerySideServiceConfiguration], args :_ *)
}

View File

@@ -0,0 +1,30 @@
package net.chrisrichardson.eventstore.examples.bank.web
import org.junit.runner.RunWith
import org.scalatest.FlatSpec
import org.scalatest.concurrent.Eventually._
import org.scalatest.junit.JUnitRunner
import org.scalatest.time.{Millis, Span}
import org.springframework.boot.SpringApplication
import org.springframework.web.client.RestTemplate
@RunWith(classOf[JUnitRunner])
class AccountsQuerySideServiceIntegrationTest extends FlatSpec {
val sa = new SpringApplication(classOf[AccountsQuerySideServiceTestConfiguration])
val ctx = sa.run()
// var server = ctx.getBean(classOf[EmbeddedServletContainer])
val port = 8080
val baseUrl = s"http://localhost:$port/"
val restTemplate = ctx.getBean(classOf[RestTemplate])
implicit val reallyLongPatienceConfig = PatienceConfig(timeout = Span(10 * 1000, Millis), interval = Span(1 * 1000, Millis))
it should "create accounts and transfer money" in {
// FIXME
}
}

View File

@@ -0,0 +1,26 @@
package net.chrisrichardson.eventstore.examples.bank.web
import com.fasterxml.jackson.databind.ObjectMapper
import org.springframework.context.annotation.{Bean, Configuration, Import}
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
import org.springframework.web.client.RestTemplate
import scala.collection.JavaConversions._
@Configuration
@Import(Array(classOf[AccountsQuerySideServiceConfiguration]))
class AccountsQuerySideServiceTestConfiguration {
@Bean
def restTemplate(scalaObjectMapper: ObjectMapper) = {
val restTemplate = new RestTemplate()
restTemplate.getMessageConverters foreach {
case mc: MappingJackson2HttpMessageConverter =>
mc.setObjectMapper(scalaObjectMapper)
case _ =>
}
restTemplate
}
}

View File

@@ -2,8 +2,8 @@ apply plugin: 'scala'
dependencies {
compile "org.scala-lang:scala-library:2.10.2"
compile project(":queryside-backend")
compile project(":web-common")
compile project(":accounts-query-side-backend")
compile project(":common-web")
compile "org.springframework.boot:spring-boot-starter-actuator:$springBootVersion"

View File

@@ -1,11 +1,13 @@
package net.chrisrichardson.eventstore.examples.bank.web.queryside
import net.chrisrichardson.eventstore.examples.bank.queryside.QuerySideConfiguration
import net.chrisrichardson.eventstore.subscriptions.EnableEventHandlers
import org.springframework.context.annotation._
@Configuration
@Import(Array(classOf[QuerySideConfiguration]))
@ComponentScan
@EnableEventHandlers
class QuerySideWebConfiguration {
}

View File

@@ -1,9 +1,10 @@
package net.chrisrichardson.eventstore.examples.bank.web.queryside.controllers
import net.chrisrichardson.eventstore.EntityId
import net.chrisrichardson.eventstore.examples.bank.queryside.AccountInfoQueryService
import net.chrisrichardson.eventstore.examples.bank.queryside.{AccountNotFoundException, AccountInfoQueryService}
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.{PathVariable, RequestMapping, RequestMethod, RestController}
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation._
@RestController
class AccountQuerySideController @Autowired() (accountInfoQueryService : AccountInfoQueryService) {
@@ -11,4 +12,7 @@ class AccountQuerySideController @Autowired() (accountInfoQueryService : Account
@RequestMapping(value=Array("/accounts/{accountId}"), method = Array(RequestMethod.GET))
def get(@PathVariable accountId : String) = accountInfoQueryService.findByAccountId(EntityId(accountId))
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "account not found")
@ExceptionHandler(Array(classOf[AccountNotFoundException]))
def accountNotFound() {}
}

View File

@@ -5,9 +5,9 @@ dependencies {
compile "org.scala-lang:scala-library:2.10.2"
compile project(":commandside-backend-transactions")
compile project(":commandside-backend-accounts")
compile project(":queryside-backend")
compile project(":transactions-command-side-backend")
compile project(":accounts-command-side-backend")
compile project(":accounts-query-side-backend")
testCompile scalaTestDependency

View File

@@ -0,0 +1,16 @@
import org.gradle.api.*
class VerifyEventStoreEnvironmentPlugin implements Plugin<Project> {
void apply(Project project) {
project.test {
beforeSuite { x ->
if (x.parent == null) {
if (System.getenv("EVENT_STORE_URL") == null)
logger.warn("\nPLEASE make sure that Event Store-related environment variables including EVENT_STORE_URL are set, see sample-set-remote-env.sh !!!!\n")
}
}
}
}
}

View File

@@ -0,0 +1,20 @@
apply plugin: 'scala'
apply plugin: VerifyMongoDBConfigurationPlugin
dependencies {
compile "org.scala-lang:scala-library:2.10.2"
testCompile project(":accounts-command-side-web")
testCompile project(":transactions-command-side-web")
testCompile project(":accounts-query-side-web")
testCompile "junit:junit:4.11"
testCompile "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
testCompile scalaTestDependency
}
test {
ignoreFailures true
}

View File

@@ -0,0 +1,67 @@
package net.chrisrichardson.eventstore.examples.bank.web
import net.chrisrichardson.eventstore.EntityId
import net.chrisrichardson.eventstore.examples.bank.queryside.AccountInfo
import net.chrisrichardson.eventstore.examples.bank.web.accounts.controllers.{CreateAccountRequest, CreateAccountResponse}
import net.chrisrichardson.eventstore.examples.bank.web.transactions.controllers.{CreateMoneyTransferResponse, GetMoneyTransferResponse, MoneyTransferRequest}
import net.chrisrichardson.eventstore.json.EventStoreCommonObjectMapping.EventStoreCommonObjectMapper
import org.junit.runner.RunWith
import org.scalatest.FlatSpec
import org.scalatest.Matchers._
import org.scalatest.concurrent.Eventually._
import org.scalatest.junit.JUnitRunner
import org.scalatest.time.{Millis, Span}
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
import org.springframework.web.client.RestTemplate
import scala.collection.JavaConversions._
@RunWith(classOf[JUnitRunner])
class EndToEndTest extends FlatSpec {
val accountsCommandSideBaseUrl = s"http://localhost:8080/"
val accountsQuerySideBaseUrl = s"http://localhost:8081/"
val transactionsCommandSideBaseUrl = s"http://localhost:8082/"
val restTemplate = new RestTemplate()
restTemplate.getMessageConverters foreach {
case mc: MappingJackson2HttpMessageConverter =>
mc.setObjectMapper(EventStoreCommonObjectMapper)
case _ =>
}
implicit val reallyLongPatienceConfig = PatienceConfig(timeout = Span(10 * 1000, Millis), interval = Span(1 * 1000, Millis))
it should "create accounts and transfer money" in {
val CreateAccountResponse(fromAccountId) = restTemplate.postForEntity(s"$accountsCommandSideBaseUrl/accounts", CreateAccountRequest(BigDecimal(500)), classOf[CreateAccountResponse]).getBody
val CreateAccountResponse(toAccountId) = restTemplate.postForEntity(s"$accountsCommandSideBaseUrl/accounts", CreateAccountRequest(BigDecimal(100)), classOf[CreateAccountResponse]).getBody
eventually {
val accountInfo = restTemplate.getForEntity(s"$accountsQuerySideBaseUrl/accounts/" + fromAccountId, classOf[AccountInfo]).getBody
accountInfo should not be null
val AccountInfo(accountId, initialBalance, _, _, _) = accountInfo
accountId should be(fromAccountId)
initialBalance should be(500*100)
}(reallyLongPatienceConfig)
val CreateMoneyTransferResponse(transactionId) = restTemplate.postForEntity(s"$transactionsCommandSideBaseUrl/transfers",
MoneyTransferRequest(EntityId(fromAccountId), EntityId(toAccountId), BigDecimal(150)), classOf[CreateMoneyTransferResponse]).getBody
eventually {
val AccountInfo(_, newFromAccountBalance, _, _, _) = restTemplate.getForEntity(s"$accountsQuerySideBaseUrl/accounts/" + fromAccountId, classOf[AccountInfo]).getBody
newFromAccountBalance should be(350*100)
}(reallyLongPatienceConfig)
eventually {
val AccountInfo(_, newToAccountBalance, _, _, _) = restTemplate.getForEntity(s"$accountsQuerySideBaseUrl/accounts/" + toAccountId, classOf[AccountInfo]).getBody
newToAccountBalance should be(250*100)
}(reallyLongPatienceConfig)
eventually {
val GetMoneyTransferResponse(_, state) = restTemplate.getForEntity(s"$transactionsCommandSideBaseUrl/transfers/" + transactionId, classOf[GetMoneyTransferResponse]).getBody
state should be("COMPLETED$")
}(reallyLongPatienceConfig)
}
}

View File

@@ -5,5 +5,5 @@ scalaTestDependency=org.scalatest:scalatest_2.10:2.0
springBootVersion=1.1.10.RELEASE
eventStoreCommonVersion=0.2
eventStoreClientVersion=0.2
eventStoreClientVersion=0.5
eventStoreCommonVersion=0.5

View File

@@ -4,9 +4,9 @@ apply plugin: VerifyMongoDBConfigurationPlugin
dependencies {
compile "org.scala-lang:scala-library:2.10.2"
compile project(":commandside-web-accounts")
compile project(":commandside-web-transactions")
compile project(":queryside-web")
compile project(":accounts-command-side-web")
compile project(":transactions-command-side-web")
compile project(":accounts-query-side-web")
compile "org.springframework.boot:spring-boot-starter-web"
compile "org.springframework.boot:spring-boot-starter-actuator"

View File

@@ -2,17 +2,17 @@ package net.chrisrichardson.eventstore.examples.bank.web
import net.chrisrichardson.eventstore.EntityId
import net.chrisrichardson.eventstore.examples.bank.queryside.AccountInfo
import net.chrisrichardson.eventstore.examples.bank.transactions.TransferStates
import net.chrisrichardson.eventstore.examples.bank.web.accounts.controllers.{GetAccountResponse, CreateAccountRequest, CreateAccountResponse}
import net.chrisrichardson.eventstore.examples.bank.web.transactions.controllers.{GetMoneyTransferResponse, MoneyTransferRequest, CreateMoneyTransferResponse}
import net.chrisrichardson.eventstore.examples.bank.web.accounts.controllers.{CreateAccountRequest, CreateAccountResponse}
import net.chrisrichardson.eventstore.examples.bank.web.transactions.controllers.{CreateMoneyTransferResponse, GetMoneyTransferResponse, MoneyTransferRequest}
import org.junit.runner.RunWith
import org.scalatest.FlatSpec
import org.scalatest.Matchers._
import org.scalatest.concurrent.Eventually._
import org.scalatest.junit.JUnitRunner
import org.scalatest.time.{Millis, Span}
import org.springframework.boot.SpringApplication
import org.springframework.web.client.RestTemplate
import org.scalatest.Matchers._
import org.springframework.http.HttpStatus
import org.springframework.web.client.{HttpClientErrorException, RestTemplate}
@RunWith(classOf[JUnitRunner])
class BankWebIntegrationTest extends FlatSpec {
@@ -35,7 +35,11 @@ class BankWebIntegrationTest extends FlatSpec {
val CreateAccountResponse(fromAccountId) = restTemplate.postForEntity(s"$baseUrl/accounts", CreateAccountRequest(BigDecimal(500)), classOf[CreateAccountResponse]).getBody
val CreateAccountResponse(toAccountId) = restTemplate.postForEntity(s"$baseUrl/accounts", CreateAccountRequest(BigDecimal(100)), classOf[CreateAccountResponse]).getBody
val AccountInfo(accountId, initialBalance, _, _, _) = restTemplate.getForEntity(s"$baseUrl/accounts/" + fromAccountId, classOf[AccountInfo]).getBody
val AccountInfo(accountId, initialBalance, _, _, _) = eventually {
val accountInfo = restTemplate.getForEntity(s"$baseUrl/accounts/" + fromAccountId, classOf[AccountInfo]).getBody
accountInfo should not be null
accountInfo
}(reallyLongPatienceConfig)
accountId should be(fromAccountId)
initialBalance should be(500*100)
@@ -59,4 +63,8 @@ class BankWebIntegrationTest extends FlatSpec {
}
it should "Return 404 for non-existent account" in {
val t = the[HttpClientErrorException] thrownBy restTemplate.getForEntity(s"$baseUrl/accounts/" + "non-existent-account-id", classOf[AccountInfo])
t.getStatusCode shouldBe HttpStatus.NOT_FOUND
}
}

View File

@@ -1,9 +0,0 @@
package net.chrisrichardson.eventstore.examples.bank.queryside
import net.chrisrichardson.eventstore.EntityId
class AccountInfoQueryService(accountInfoRepository : AccountInfoRepository) {
def findByAccountId(accountId : EntityId) : AccountInfo = accountInfoRepository.findOne(accountId.id)
}

View File

@@ -1,18 +1,23 @@
include 'web-common'
include 'common-web'
include 'common-backend'
include 'commandside-backend-accounts'
include 'commandside-backend-transactions'
include 'commandside-web-accounts'
include 'commandside-web-transactions'
include 'accounts-command-side-backend'
include 'transactions-command-side-backend'
include 'accounts-command-side-web'
include 'transactions-command-side-web'
include 'queryside-backend'
include 'queryside-web'
include 'accounts-query-side-backend'
include 'accounts-query-side-web'
include 'backend-integration-tests'
include 'monolithic-web'
include 'monolithic-service'
include 'accounts-command-side-service'
include 'accounts-query-side-service'
include 'transactions-command-side-service'
include 'e2e-test'
rootProject.name = 'scala-spring-event-sourcing-example'

View File

@@ -2,4 +2,4 @@ dependencies {
compile "org.scala-lang:scala-library:2.10.2"
compile project(":common-backend")
compile "net.chrisrichardson.eventstore.client:eventstore-client-event-handling:$eventStoreClientVersion"
}
}

View File

@@ -0,0 +1,22 @@
apply plugin: 'scala'
apply plugin: 'spring-boot'
apply plugin: VerifyEventStoreEnvironmentPlugin
dependencies {
compile "org.scala-lang:scala-library:2.10.2"
compile project(":transactions-command-side-web")
compile "org.springframework.boot:spring-boot-starter-web"
compile "org.springframework.boot:spring-boot-starter-actuator"
compile "net.chrisrichardson.eventstore.client:eventstore-http-stomp-client:$eventStoreClientVersion"
testCompile "org.springframework.boot:spring-boot-starter-test"
testCompile scalaTestDependency
}
test {
ignoreFailures true
}

View File

@@ -0,0 +1,14 @@
package net.chrisrichardson.eventstore.examples.bank.web
import net.chrisrichardson.eventstore.client.config.EventStoreHttpClientConfiguration
import net.chrisrichardson.eventstore.examples.bank.web.transactions.CommandSideWebTransactionsConfiguration
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.context.annotation._
@Configuration
@EnableAutoConfiguration
@Import(Array(classOf[CommandSideWebTransactionsConfiguration], classOf[EventStoreHttpClientConfiguration]))
@ComponentScan
class TransactionsCommandSideServiceConfiguration {
}

View File

@@ -0,0 +1,10 @@
package net.chrisrichardson.eventstore.examples.bank.web.main
import net.chrisrichardson.eventstore.examples.bank.web.TransactionsCommandSideServiceConfiguration
import org.springframework.boot.SpringApplication
object TransactionsCommandSideServiceMain {
def main(args: Array[String]) : Unit = SpringApplication.run(classOf[TransactionsCommandSideServiceConfiguration], args :_ *)
}

View File

@@ -0,0 +1,30 @@
package net.chrisrichardson.eventstore.examples.bank.web
import org.junit.runner.RunWith
import org.scalatest.FlatSpec
import org.scalatest.concurrent.Eventually._
import org.scalatest.junit.JUnitRunner
import org.scalatest.time.{Millis, Span}
import org.springframework.boot.SpringApplication
import org.springframework.web.client.RestTemplate
@RunWith(classOf[JUnitRunner])
class TransactionsCommandSideServiceIntegrationTest extends FlatSpec {
val sa = new SpringApplication(classOf[TransactionsCommandSideServiceTestConfiguration])
val ctx = sa.run()
// var server = ctx.getBean(classOf[EmbeddedServletContainer])
val port = 8080
val baseUrl = s"http://localhost:$port/"
val restTemplate = ctx.getBean(classOf[RestTemplate])
implicit val reallyLongPatienceConfig = PatienceConfig(timeout = Span(10 * 1000, Millis), interval = Span(1 * 1000, Millis))
it should "create accounts and transfer money" in {
// FIXME
}
}

View File

@@ -0,0 +1,26 @@
package net.chrisrichardson.eventstore.examples.bank.web
import com.fasterxml.jackson.databind.ObjectMapper
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.context.annotation.{Bean, Import, Configuration}
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
import org.springframework.web.client.RestTemplate
import scala.collection.JavaConversions._
@Configuration
@Import(Array(classOf[TransactionsCommandSideServiceConfiguration]))
class TransactionsCommandSideServiceTestConfiguration {
@Bean
def restTemplate(scalaObjectMapper: ObjectMapper) = {
val restTemplate = new RestTemplate()
restTemplate.getMessageConverters foreach {
case mc: MappingJackson2HttpMessageConverter =>
mc.setObjectMapper(scalaObjectMapper)
case _ =>
}
restTemplate
}
}

View File

@@ -2,9 +2,9 @@ apply plugin: 'scala'
dependencies {
compile "org.scala-lang:scala-library:2.10.2"
compile project(":commandside-backend-transactions")
compile project(":web-common")
compile project(":transactions-command-side-backend")
compile project(":common-web")
testCompile "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
testCompile scalaTestDependency
}
}