Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
dmfrey committed Feb 21, 2018
0 parents commit 8580dc7
Show file tree
Hide file tree
Showing 68 changed files with 2,355 additions and 0 deletions.
28 changes: 28 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
.gradle
/build/
**/build/
/out/
**/out/*
!gradle/wrapper/gradle-wrapper.jar

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr

### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
.nb-gradle/
88 changes: 88 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
buildscript {
ext {
springBootVersion = '2.0.0.RC1'
}
repositories {
mavenCentral()
maven { url "https://repo.spring.io/snapshot" }
maven { url "https://repo.spring.io/milestone" }
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}

apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'eclipse'

group 'io.pivotal.dmfrey'
version '1.0-SNAPSHOT'

allprojects {

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

group = 'io.pivotal.dmfrey'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
mavenCentral()
maven { url "https://repo.spring.io/snapshot" }
maven { url "https://repo.spring.io/milestone" }
}

ext {
springCloudVersion = 'Finchley.M6'
}

dependencies {

// Kafka dependencies
// compile('org.apache.kafka:kafka-clients:1.0.0')
// compile('org.apache.kafka:kafka-streams:1.0.0')


// Spring dependencies
compile('org.springframework.kafka:spring-kafka:2.1.3.BUILD-SNAPSHOT')


// Spring Boot dependencies
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.boot:spring-boot-starter-web')


// Spring Cloud dependencies
compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
compile('org.springframework.cloud:spring-cloud-starter-openfeign')
compile('org.springframework.cloud:spring-cloud-stream')
compile('org.springframework.cloud:spring-cloud-stream-binder-kafka-streams:2.0.0.BUILD-SNAPSHOT')


// Third-party dependencies
compile('org.projectlombok:lombok:1.16.18')
compile('io.vavr:vavr:0.9.2')


// Test dependencies
testCompile('org.springframework.boot:spring-boot-starter-test')
testCompile('org.springframework.cloud:spring-cloud-stream-test-support')
testCompile('org.springframework.cloud:spring-cloud-stream-binder-test')
testCompile('org.springframework.kafka:spring-kafka-test')

}

dependencyManagement {

imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}

}

}
5 changes: 5 additions & 0 deletions command/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

dependencies {

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.pivotal.dmfrey.eventStoreDemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

public static void main( String[] args ) {

SpringApplication.run( Application.class, args );

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package io.pivotal.dmfrey.eventStoreDemo.config;
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.pivotal.dmfrey.eventStoreDemo.domain.client;

import io.pivotal.dmfrey.eventStoreDemo.domain.model.Board;

import java.util.UUID;

public interface BoardClient {

void save( final Board board );

Board find( final UUID boardUuid );

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.pivotal.dmfrey.eventStoreDemo.domain.client.eventStore.config;

import io.pivotal.dmfrey.eventStoreDemo.domain.client.BoardClient;
import io.pivotal.dmfrey.eventStoreDemo.domain.client.eventStore.service.EventStoreBoardClient;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;

@Profile( "event-store" )
@Configuration
public class EventStoreClientConfig {

@Bean
@Primary
public BoardClient boardClient(
@Qualifier( "io.pivotal.dmfrey.eventStoreDemo.domain.client.eventStore.config.RestConfig$EventStoreClient" ) final RestConfig.EventStoreClient eventStoreClient
) {

return new EventStoreBoardClient( eventStoreClient );
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package io.pivotal.dmfrey.eventStoreDemo.domain.client.eventStore.config;

import io.pivotal.dmfrey.eventStoreDemo.domain.events.DomainEvents;
import io.pivotal.dmfrey.eventStoreDemo.domain.events.DomainEvent;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.UUID;

import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;

@Profile( "event-store" )
@Configuration
@EnableFeignClients
public class RestConfig {

@FeignClient( value = "event-store" /*, fallback = HystrixFallbackEventStoreClient.class */ )
public interface EventStoreClient {

@PostMapping( path = "/" )
ResponseEntity addNewDomainEvent( @RequestBody DomainEvent event );

@GetMapping( path = "/{boardUuid}" )
DomainEvents getDomainEventsForBoardUuid( @PathVariable( "boardUuid" ) UUID boardId );

}

// @Bean
// public HystrixFallbackEventStoreClient hystrixFallbackEventStoreClient() {
//
// return new HystrixFallbackEventStoreClient();
// }

// @Component
// static class HystrixFallbackEventStoreClient implements EventStoreClient {
//
// @Override
// public ResponseEntity addNewDomainEvent( final DomainEvent event ) {
//
// return ResponseEntity
// .status( INTERNAL_SERVER_ERROR )
// .build();
// }
//
// @Override
// public DomainEvents getDomainEventsForBoardUuid( final UUID boardUuid) {
//
// return new DomainEvents();
// }
//
// }

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package io.pivotal.dmfrey.eventStoreDemo.domain.client.eventStore.config;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package io.pivotal.dmfrey.eventStoreDemo.domain.client.eventStore;
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package io.pivotal.dmfrey.eventStoreDemo.domain.client.eventStore.service;

import io.pivotal.dmfrey.eventStoreDemo.domain.client.BoardClient;
import io.pivotal.dmfrey.eventStoreDemo.domain.client.eventStore.config.RestConfig;
import io.pivotal.dmfrey.eventStoreDemo.domain.events.DomainEvents;
import io.pivotal.dmfrey.eventStoreDemo.domain.events.DomainEvent;
import io.pivotal.dmfrey.eventStoreDemo.domain.model.Board;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import java.util.List;
import java.util.UUID;

@Slf4j
public class EventStoreBoardClient implements BoardClient {

private final RestConfig.EventStoreClient eventStoreClient;

public EventStoreBoardClient( final RestConfig.EventStoreClient eventStoreClient ) {

this.eventStoreClient = eventStoreClient;

}

@Override
public void save( final Board board ) {
log.debug( "save : enter" );

List<DomainEvent> newChanges = board.changes();

newChanges.forEach( domainEvent -> {
log.debug( "save : domainEvent=" + domainEvent );

ResponseEntity accepted = this.eventStoreClient.addNewDomainEvent( domainEvent );
if( !accepted.getStatusCode().equals( HttpStatus.ACCEPTED ) ) {

throw new IllegalStateException( "could not add DomainEvent to the Event Store" );
}
});
board.flushChanges();

log.debug( "save : exit" );
}

@Override
public Board find( final UUID boardUuid ) {
log.debug( "find : enter" );

DomainEvents domainEvents = this.eventStoreClient.getDomainEventsForBoardUuid( boardUuid );
if( domainEvents.getDomainEvents().isEmpty() ) {

log.warn( "find : exit, target[" + boardUuid.toString() + "] not found" );
throw new IllegalArgumentException( "board[" + boardUuid.toString() + "] not found" );
}

Board board = Board.createFrom( boardUuid, domainEvents.getDomainEvents() );
board.flushChanges();

log.debug( "find : exit" );
return board;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package io.pivotal.dmfrey.eventStoreDemo.domain.client.eventStore.service;
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package io.pivotal.dmfrey.eventStoreDemo.domain.client.kafka.config;

import io.pivotal.dmfrey.eventStoreDemo.domain.client.BoardClient;
import io.pivotal.dmfrey.eventStoreDemo.domain.client.kafka.service.DomainEventSource;
import io.pivotal.dmfrey.eventStoreDemo.domain.client.kafka.service.DomainEventSourceImpl;
import io.pivotal.dmfrey.eventStoreDemo.domain.client.kafka.service.KafkaBoardClient;
import org.apache.kafka.streams.KafkaStreams;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cloud.stream.binder.kafka.streams.QueryableStoreRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;
import org.springframework.kafka.core.StreamsBuilderFactoryBean;

@Profile( "kafka" )
@Configuration
@EnableAutoConfiguration
public class KafkaClientConfig {

@Bean
@Primary
public BoardClient boardClient(
final DomainEventSource domainEventSource,
final QueryableStoreRegistry queryableStoreRegistry
) {

return new KafkaBoardClient( domainEventSource, queryableStoreRegistry );
}

}
Loading

0 comments on commit 8580dc7

Please sign in to comment.