added customers-query-side part

added service wrappers to customers-command-side and customers-query-side
This commit is contained in:
Main
2016-02-05 01:27:17 +03:00
parent e0691a61a2
commit afb7c9bc49
36 changed files with 532 additions and 33 deletions

View File

@@ -1,6 +1,7 @@
apply plugin: 'java'
dependencies {
compile project(":common-customers")
compile "net.chrisrichardson.eventstore.client:eventstore-java-client_2.10:$eventStoreClientVersion"
testCompile "junit:junit:4.11"

View File

@@ -1,6 +1,7 @@
package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers;
import net.chrisrichardson.eventstore.Event;
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerInfo;
/**
* Created by popikyardo on 02.02.16.

View File

@@ -0,0 +1,5 @@
apply plugin: 'java'
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.11'
}

View File

@@ -1,4 +1,4 @@
package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers;
package net.chrisrichardson.eventstore.javaexamples.banking.common.customers;
/**
* Created by popikyardo on 02.02.16.

View File

@@ -1,13 +1,13 @@
package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers;
package net.chrisrichardson.eventstore.javaexamples.banking.common.customers;
/**
* Created by popikyardo on 03.02.16.
*/
public class CustomerInfo {
private String email;
private String ssn;
private String phoneNumber;
private Address address;
protected String email;
protected String ssn;
protected String phoneNumber;
protected Address address;
public CustomerInfo() {
}
@@ -23,31 +23,15 @@ public class CustomerInfo {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getSsn() {
return ssn;
}
public void setSsn(String ssn) {
this.ssn = ssn;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}

View File

@@ -1,6 +1,4 @@
package net.chrisrichardson.eventstore.javaexamples.banking.web.commandside.customers;
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers.CustomerInfo;
package net.chrisrichardson.eventstore.javaexamples.banking.common.customers;
/**
* Created by popikyardo on 03.02.16.

View File

@@ -1,6 +1,7 @@
apply plugin: 'java'
dependencies {
compile project(":common-customers")
compile project(":common-backend")
compile "net.chrisrichardson.eventstore.client:eventstore-java-client_2.10:$eventStoreClientVersion"

View File

@@ -1,6 +1,6 @@
package net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.customers;
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers.CustomerInfo;
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerInfo;
/**
* Created by popikyardo on 02.02.16.

View File

@@ -4,7 +4,7 @@ import net.chrisrichardson.eventstore.Event;
import net.chrisrichardson.eventstore.EventUtil;
import net.chrisrichardson.eventstore.ReflectiveMutableCommandProcessingAggregate;
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers.CustomerCreatedEvent;
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers.CustomerInfo;
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerInfo;
import java.util.List;
@@ -15,6 +15,7 @@ public class Customer extends ReflectiveMutableCommandProcessingAggregate<Custom
private CustomerInfo customerInfo;
public List<Event> process(CreateCustomerCommand cmd) {
return EventUtil.events(new CustomerCreatedEvent(cmd.getCustomerInfo()));
}

View File

@@ -2,8 +2,7 @@ package net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.
import net.chrisrichardson.eventstore.EntityWithIdAndVersion;
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers.Address;
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers.CustomerInfo;
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerInfo;
import net.chrisrichardson.eventstore.repository.AggregateRepository;
public class CustomerService {

View File

@@ -0,0 +1,20 @@
apply plugin: VerifyMongoDBConfigurationPlugin
apply plugin: VerifyEventStoreEnvironmentPlugin
apply plugin: 'spring-boot'
dependencies {
compile project(":customers-command-side-web")
compile project(":common-swagger")
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_2.10:$eventStoreClientVersion"
testCompile "org.springframework.boot:spring-boot-starter-test"
}
test {
ignoreFailures true
}

View File

@@ -0,0 +1,29 @@
package net.chrisrichardson.eventstore.javaexamples.banking.web;
import net.chrisrichardson.eventstore.client.config.EventStoreHttpClientConfiguration;
import net.chrisrichardson.eventstore.javaexamples.banking.commonswagger.CommonSwaggerConfiguration;
import net.chrisrichardson.eventstore.javaexamples.banking.web.commandside.customers.CommandSideWebCustomersConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
@Configuration
@Import({CommandSideWebCustomersConfiguration.class, EventStoreHttpClientConfiguration.class, CommonSwaggerConfiguration.class})
@EnableAutoConfiguration
@ComponentScan
public class CustomersCommandSideServiceConfiguration {
@Bean
public HttpMessageConverters customConverters() {
HttpMessageConverter<?> additional = new MappingJackson2HttpMessageConverter();
return new HttpMessageConverters(additional);
}
}

View File

@@ -0,0 +1,11 @@
package net.chrisrichardson.eventstore.javaexamples.banking.web.main;
import net.chrisrichardson.eventstore.javaexamples.banking.web.CustomersCommandSideServiceConfiguration;
import org.springframework.boot.SpringApplication;
public class CustomersCommandSideServiceMain {
public static void main(String[] args) {
SpringApplication.run(CustomersCommandSideServiceConfiguration.class, args);
}
}

View File

@@ -1,7 +1,8 @@
apply plugin: 'java'
dependencies {
compile project(":customer-command-side-backend")
compile project(":common-customers")
compile project(":customers-command-side-backend")
compile project(":common-web")
compile "org.springframework.boot:spring-boot-starter-web:$springBootVersion"

View File

@@ -1,7 +1,8 @@
package net.chrisrichardson.eventstore.javaexamples.banking.web.commandside.customers;
import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.customers.CustomerService;
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers.CustomerInfo;
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerInfo;
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;

View File

@@ -0,0 +1,18 @@
apply plugin: 'java'
dependencies {
compile project(":common-backend")
compile "net.chrisrichardson.eventstore.client:eventstore-java-client_2.10:$eventStoreClientVersion"
compile "org.springframework.boot:spring-boot-starter-data-mongodb:$springBootVersion"
compile 'com.fasterxml.jackson.core:jackson-core:2.4.3'
compile 'com.fasterxml.jackson.core:jackson-databind:2.4.3'
compile 'com.fasterxml.jackson.module:jackson-module-scala_2.10:2.4.3'
testCompile project(":testutil")
testCompile "junit:junit:4.11"
testCompile "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
testCompile "net.chrisrichardson.eventstore.client:eventstore-jdbc_2.10:$eventStoreClientVersion"
}

View File

@@ -0,0 +1,10 @@
package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.customers;
import org.springframework.data.mongodb.repository.MongoRepository;
import java.util.List;
interface CustomerInfoRepository extends MongoRepository<CustomerInfoWithId, String> {
List<CustomerInfoWithId> findByEmailLike(String email);
}

View File

@@ -0,0 +1,35 @@
package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.customers;
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Created by Main on 04.02.2016.
*/
public class CustomerInfoUpdateService {
private Logger logger = LoggerFactory.getLogger(getClass());
private CustomerInfoRepository accountInfoRepository;
public CustomerInfoUpdateService(CustomerInfoRepository accountInfoRepository) {
this.accountInfoRepository = accountInfoRepository;
}
public void create(String id, CustomerInfo customerInfo) {
try {
accountInfoRepository.save(new CustomerInfoWithId(id,
customerInfo.getEmail(),
customerInfo.getSsn(),
customerInfo.getPhoneNumber(),
customerInfo.getAddress())
);
logger.info("Saved in mongo");
} catch (Throwable t) {
logger.error("Error during saving: ", t);
throw new RuntimeException(t);
}
}
}

View File

@@ -0,0 +1,20 @@
package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.customers;
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.Address;
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerInfo;
/**
* Created by Main on 05.02.2016.
*/
public class CustomerInfoWithId extends CustomerInfo {
private String id;
public CustomerInfoWithId(String id, String email, String ssn, String phoneNumber, Address address) {
super(email, ssn, phoneNumber, address);
this.id = id;
}
public String getId() {
return id;
}
}

View File

@@ -0,0 +1,8 @@
package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.customers;
public class CustomerNotFoundException extends RuntimeException {
public CustomerNotFoundException(String customerId) {
super("Customer not found " + customerId);
}
}

View File

@@ -0,0 +1,31 @@
package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.customers;
import net.chrisrichardson.eventstore.EntityIdentifier;
import rx.Observable;
import java.util.List;
public class CustomerQueryService {
private CustomerInfoRepository customerInfoRepository;
public CustomerQueryService(CustomerInfoRepository customerInfoRepository) {
this.customerInfoRepository = customerInfoRepository;
}
public Observable<CustomerInfoWithId> findByCustomerId(EntityIdentifier customerId) {
CustomerInfoWithId customer = customerInfoRepository.findOne(customerId.getId());
if (customer == null)
return Observable.error(new CustomerNotFoundException(customerId.getId()));
else
return Observable.just(customer);
}
public Observable<List<CustomerInfoWithId>> findByEmail(String email){
List<CustomerInfoWithId> customers = customerInfoRepository.findByEmailLike(email);
if (customers.isEmpty())
return Observable.error(new CustomersNotFoundException());
else
return Observable.just(customers);
}
}

View File

@@ -0,0 +1,37 @@
package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.customers;
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers.CustomerCreatedEvent;
import net.chrisrichardson.eventstore.subscriptions.CompoundEventHandler;
import net.chrisrichardson.eventstore.subscriptions.DispatchedEvent;
import net.chrisrichardson.eventstore.subscriptions.EventHandlerMethod;
import net.chrisrichardson.eventstore.subscriptions.EventSubscriber;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Observable;
/**
* Created by Main on 04.02.2016.
*/
@EventSubscriber(id="querySideEventHandlers")
public class CustomerQueryWorkflow implements CompoundEventHandler {
private Logger logger = LoggerFactory.getLogger(getClass());
private CustomerInfoUpdateService customerInfoUpdateService;
public CustomerQueryWorkflow(CustomerInfoUpdateService customerInfoUpdateService) {
this.customerInfoUpdateService = customerInfoUpdateService;
}
@EventHandlerMethod
public Observable<Object> create(DispatchedEvent<CustomerCreatedEvent> de) {
CustomerCreatedEvent event = de.event();
String id = de.getEntityIdentifier().getId();
String eventId = de.eventId().asString();
logger.info("**************** customer version=" + id + ", " + eventId);
customerInfoUpdateService.create(id, event.getCustomerInfo());
return Observable.just(null);
}
}

View File

@@ -0,0 +1,8 @@
package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.customers;
public class CustomersNotFoundException extends RuntimeException {
public CustomersNotFoundException() {
super("Customers not found");
}
}

View File

@@ -0,0 +1,37 @@
package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.customers;
import net.chrisrichardson.eventstore.javaapi.consumer.EnableJavaEventHandlers;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
/**
* Created by Main on 04.02.2016.
*/
@Configuration
@EnableMongoRepositories
@EnableJavaEventHandlers
public class QuerySideCustomerConfiguration {
@Bean
public CustomerQueryWorkflow customerQueryWorkflow(CustomerInfoUpdateService accountInfoUpdateService) {
return new CustomerQueryWorkflow(accountInfoUpdateService);
}
@Bean
public CustomerInfoUpdateService customerInfoUpdateService(CustomerInfoRepository customerInfoRepository) {
return new CustomerInfoUpdateService(customerInfoRepository);
}
@Bean
public CustomerQueryService customerQueryService(CustomerInfoRepository accountInfoRepository) {
return new CustomerQueryService(accountInfoRepository);
}
@Bean
public QuerySideDependencyChecker querysideDependencyChecker(MongoTemplate mongoTemplate) {
return new QuerySideDependencyChecker(mongoTemplate);
}
}

View File

@@ -0,0 +1,41 @@
package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.customers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import rx.Observable;
import rx.Subscriber;
import javax.annotation.PostConstruct;
import java.util.concurrent.TimeUnit;
public class QuerySideDependencyChecker {
private Logger logger = LoggerFactory.getLogger(getClass());
private MongoTemplate mongoTemplate;
public QuerySideDependencyChecker(MongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
}
@PostConstruct
public void checkDependencies() {
try {
logger.info("Checking mongodb connectivity {}", System.getenv("SPRING_DATA_MONGODB_URI"));
Observable.<Object>create(new Observable.OnSubscribe<Object>() {
@Override
public void call(Subscriber<? super Object> subscriber) {
try {
subscriber.onNext(mongoTemplate.getDb().getCollectionNames());
subscriber.onCompleted();
} catch (Throwable t) {
subscriber.onError(t);
}
}
}).timeout(5, TimeUnit.SECONDS).toBlocking().first();
} catch (Throwable e) {
throw new RuntimeException("Error connecting to Mongo - have you set SPRING_DATA_MONGODB_URI or --spring.data.mongodb_uri?", e);
}
}
}

View File

@@ -0,0 +1,20 @@
apply plugin: VerifyMongoDBConfigurationPlugin
apply plugin: VerifyEventStoreEnvironmentPlugin
apply plugin: 'spring-boot'
dependencies {
compile project(":customers-query-side-web")
compile project(":common-swagger")
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_2.10:$eventStoreClientVersion"
testCompile "org.springframework.boot:spring-boot-starter-test"
}
test {
ignoreFailures true
}

View File

@@ -0,0 +1,27 @@
package net.chrisrichardson.eventstore.javaexamples.banking.web;
import net.chrisrichardson.eventstore.client.config.EventStoreHttpClientConfiguration;
import net.chrisrichardson.eventstore.javaexamples.banking.commonswagger.CommonSwaggerConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
@Configuration
@Import({CustomersQuerySideServiceConfiguration.class, EventStoreHttpClientConfiguration.class, CommonSwaggerConfiguration.class})
@EnableAutoConfiguration
@ComponentScan
public class CustomersQuerySideServiceConfiguration {
@Bean
public HttpMessageConverters customConverters() {
HttpMessageConverter<?> additional = new MappingJackson2HttpMessageConverter();
return new HttpMessageConverters(additional);
}
}

View File

@@ -0,0 +1,11 @@
package net.chrisrichardson.eventstore.javaexamples.banking.web.main;
import net.chrisrichardson.eventstore.javaexamples.banking.web.CustomersQuerySideServiceConfiguration;
import org.springframework.boot.SpringApplication;
public class CustomersQuerySideServiceMain {
public static void main(String[] args) {
SpringApplication.run(CustomersQuerySideServiceConfiguration.class, args);
}
}

View File

@@ -0,0 +1,9 @@
apply plugin: 'java'
dependencies {
compile project(":customers-query-side-backend")
compile project(":common-web")
compile "org.springframework.boot:spring-boot-starter-web:$springBootVersion"
compile "org.springframework.boot:spring-boot-starter-actuator:$springBootVersion"
}

View File

@@ -0,0 +1,33 @@
package net.chrisrichardson.eventstore.javaexamples.banking.web.queryside;
import net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.customers.QuerySideCustomerConfiguration;
import net.chrisrichardson.eventstore.javaexamples.banking.web.util.ObservableReturnValueHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import java.util.ArrayList;
import java.util.List;
@Configuration
@Import({QuerySideCustomerConfiguration.class})
@ComponentScan
public class CustomersQuerySideWebConfiguration extends WebMvcConfigurerAdapter {
class FakeThing {
}
@Bean
public FakeThing init(RequestMappingHandlerAdapter adapter) {
// https://jira.spring.io/browse/SPR-13083
List<HandlerMethodReturnValueHandler> handlers = new ArrayList<HandlerMethodReturnValueHandler>(adapter.getReturnValueHandlers());
handlers.add(0, new ObservableReturnValueHandler());
adapter.setReturnValueHandlers(handlers);
return new FakeThing();
}
}

View File

@@ -0,0 +1,69 @@
package net.chrisrichardson.eventstore.javaexamples.banking.web.queryside.customers;
import net.chrisrichardson.eventstore.EntityIdentifier;
import net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.customers.CustomerInfoWithId;
import net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.customers.CustomerNotFoundException;
import net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.customers.CustomerQueryService;
import net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.customers.CustomersNotFoundException;
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerInfo;
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import rx.Observable;
import java.util.List;
import java.util.stream.Collectors;
/**
* Created by Main on 05.02.2016.
*/
@RestController
public class CustomerQueryController {
private CustomerQueryService customerQueryService;
@Autowired
public CustomerQueryController(CustomerQueryService customerQueryService) {
this.customerQueryService = customerQueryService;
}
@RequestMapping(value="/customers/{customerId}", method = RequestMethod.GET)
public Observable<CustomerResponse> getCustomer(@PathVariable String customerId) {
return customerQueryService.findByCustomerId(new EntityIdentifier(customerId))
.map(this::getCustomerResponse);
}
@RequestMapping(value="/customers", method = RequestMethod.GET)
public Observable<CustomersQueryResponse> getCustomersByEmail(@RequestParam String email) {
return customerQueryService.findByEmail(email)
.map(this::getCustomersQueryResponse);
}
@ResponseStatus(value= HttpStatus.NOT_FOUND, reason="customer not found")
@ExceptionHandler(CustomerNotFoundException.class)
public void customerNotFound() {
}
@ResponseStatus(value= HttpStatus.NOT_FOUND, reason="customers not found")
@ExceptionHandler(CustomersNotFoundException.class)
public void customersNotFound() {
}
private CustomerResponse getCustomerResponse(CustomerInfoWithId customerInfoWithId) {
return new CustomerResponse(customerInfoWithId.getId(), new CustomerInfo(customerInfoWithId.getEmail(),
customerInfoWithId.getSsn(),
customerInfoWithId.getPhoneNumber(),
customerInfoWithId.getAddress()));
}
private CustomersQueryResponse getCustomersQueryResponse(List<CustomerInfoWithId> customersList) {
return new CustomersQueryResponse(customersList
.stream()
.map(this::getCustomerResponse)
.collect(Collectors.toList())
);
}
}

View File

@@ -0,0 +1,28 @@
package net.chrisrichardson.eventstore.javaexamples.banking.web.queryside.customers;
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerResponse;
import java.util.List;
/**
* Created by Main on 05.02.2016.
*/
public class CustomersQueryResponse {
private List<CustomerResponse> customers;
public CustomersQueryResponse() {
}
public CustomersQueryResponse(List<CustomerResponse> customers) {
this.customers = customers;
}
public List<CustomerResponse> getCustomers() {
return customers;
}
public void setCustomers(List<CustomerResponse> customers) {
this.customers = customers;
}
}

View File

@@ -6,7 +6,6 @@ include 'common-backend'
include 'accounts-command-side-backend'
include 'transactions-command-side-backend'
include 'customer-command-side-backend'
include 'accounts-command-side-web'
include 'transactions-command-side-web'
@@ -26,5 +25,11 @@ include 'e2e-test'
rootProject.name = 'java-spring-event-sourcing-example'
include 'common-auth'
include 'customer-command-side-web'
include 'customers-command-side-backend'
include 'customers-command-side-web'
include 'customers-query-side-backend'
include 'customers-query-side-web'
include 'common-customers'
include 'customers-command-side-service'
include 'customers-query-side-service'