├── spring-boot-webapp ├── src │ ├── main │ │ ├── resources │ │ │ ├── static │ │ │ │ ├── styles │ │ │ │ │ └── main.css │ │ │ │ ├── index.html │ │ │ │ └── js │ │ │ │ │ └── registration.js │ │ │ ├── config │ │ │ │ └── application.yml │ │ │ ├── logback.xml │ │ │ ├── dustjs │ │ │ │ └── dust-wrapper.js │ │ │ ├── dustjsviews │ │ │ │ ├── registrationconfirmation.dust │ │ │ │ └── register.dust │ │ │ └── dustjstemplates │ │ │ │ └── main_template.dust │ │ └── scala │ │ │ └── net │ │ │ └── chrisrichardson │ │ │ └── microservices │ │ │ └── restfulspringboot │ │ │ ├── backend │ │ │ ├── RegistrationError.scala │ │ │ ├── RegistrationBackendResponse.scala │ │ │ ├── RegistrationBackendRequest.scala │ │ │ ├── RegistrationService.scala │ │ │ ├── ScalaObjectMapper.scala │ │ │ ├── DiscoveryHealthIndicator.scala │ │ │ └── RegistrationServiceProxy.scala │ │ │ ├── dustview │ │ │ ├── DustViewResolver.scala │ │ │ ├── DustView.scala │ │ │ └── DustTemplateRenderer.scala │ │ │ ├── main │ │ │ └── UserRegistrationMain.scala │ │ │ ├── controllers │ │ │ └── UserRegistrationController.scala │ │ │ └── UserRegistrationConfiguration.scala │ └── test │ │ └── scala │ │ └── net │ │ └── chrisrichardson │ │ └── microservices │ │ └── restfulspringboot │ │ ├── UserRegistrationTestConfiguration.scala │ │ ├── MyPages.scala │ │ └── UserRegistrationWebIntegrationTest.scala ├── build-docker.sh ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── Dockerfile ├── README.md ├── build.gradle ├── gradlew.bat ├── pom.xml └── gradlew ├── spring-boot-restful-service ├── build-docker.sh ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── src │ ├── main │ │ ├── resources │ │ │ ├── config │ │ │ │ └── application.yml │ │ │ └── logback.xml │ │ └── scala │ │ │ └── net │ │ │ └── chrisrichardson │ │ │ └── microservices │ │ │ └── restfulspringboot │ │ │ ├── backend │ │ │ ├── RegisteredUserRepository.scala │ │ │ ├── ScalaObjectMapper.scala │ │ │ └── RegisteredUser.scala │ │ │ ├── main │ │ │ └── UserRegistrationMain.scala │ │ │ ├── UserRegistrationConfiguration.scala │ │ │ ├── SwaggerConfig.scala │ │ │ └── controllers │ │ │ └── UserRegistrationController.scala │ └── test │ │ └── scala │ │ └── net │ │ └── chrisrichardson │ │ └── microservices │ │ └── restfulspringboot │ │ ├── UserRegistrationTestConfiguration.scala │ │ └── UserRegistrationWebIntegrationTest.scala ├── Dockerfile ├── README.md ├── build.gradle ├── gradlew.bat └── gradlew ├── e2e-test ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── build.gradle ├── gradlew.bat ├── src │ └── test │ │ └── scala │ │ └── net │ │ └── chrisrichardson │ │ └── microservices │ │ └── e2etest │ │ └── EndToEndTest.scala └── gradlew ├── mongodb-cli.sh ├── eureka-server ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── Dockerfile ├── src │ └── main │ │ ├── resources │ │ └── application.yml │ │ └── java │ │ └── net │ │ └── chrisrichardson │ │ └── microservices │ │ └── eurekaserver │ │ └── EurekaServer.java ├── build.gradle ├── gradlew.bat └── gradlew ├── gradle-all.sh ├── zipkin-server ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── src │ └── main │ │ ├── resources │ │ ├── logback.xml │ │ └── application.yml │ │ └── java │ │ └── net │ │ └── chrisrichardson │ │ └── microservices │ │ └── zipkinserver │ │ └── ZipkinServer.java ├── Dockerfile ├── build.gradle ├── gradlew.bat └── gradlew ├── clean-all.sh ├── wait-for-running-system.sh ├── register-user.sh ├── .gitignore ├── set-env.sh ├── run-e2e-test-images.sh ├── show-urls.sh ├── run-e2e-test.sh ├── LICENSE.txt ├── wait-for-services.sh ├── docker-compose-images.yml ├── Vagrantfile ├── docker-compose.yml └── README.md /spring-boot-webapp/src/main/resources/static/styles/main.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spring-boot-webapp/src/main/resources/static/index.html: -------------------------------------------------------------------------------- 1 | Hello There -------------------------------------------------------------------------------- /spring-boot-webapp/build-docker.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -e 2 | 3 | ./gradlew assemble 4 | docker build -t spring-boot-webapp . 5 | -------------------------------------------------------------------------------- /spring-boot-restful-service/build-docker.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -e 2 | 3 | ./gradlew assemble 4 | docker build -t spring-boot-restful-service . 5 | -------------------------------------------------------------------------------- /e2e-test/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cer/microservices-examples/HEAD/e2e-test/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /mongodb-cli.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | docker run --rm --network microservices-examples_default -i -t mongo:3.0.4 /usr/bin/mongo --host mongodb 4 | -------------------------------------------------------------------------------- /eureka-server/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cer/microservices-examples/HEAD/eureka-server/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle-all.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -e 2 | 3 | for dir in spring-boot-* zipkin-server eureka-server ; do 4 | (cd $dir ; ./gradlew -b build.gradle $*) 5 | done 6 | -------------------------------------------------------------------------------- /zipkin-server/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cer/microservices-examples/HEAD/zipkin-server/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /spring-boot-webapp/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cer/microservices-examples/HEAD/spring-boot-webapp/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /clean-all.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | set -e 4 | 5 | cd spring-boot-restful-service 6 | 7 | ./gradlew clean 8 | 9 | cd ../spring-boot-webapp 10 | 11 | ./gradlew clean 12 | -------------------------------------------------------------------------------- /spring-boot-restful-service/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cer/microservices-examples/HEAD/spring-boot-restful-service/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /wait-for-running-system.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -e 2 | 3 | ./wait-for-services.sh ${DOCKER_HOST_IP?} /health 8080 8081 4 | ./wait-for-services.sh ${DOCKER_HOST_IP?} /eureka/apps/REGISTRATION-SERVICE 8761 5 | -------------------------------------------------------------------------------- /register-user.sh: -------------------------------------------------------------------------------- 1 | curl -v -d "$(echo '{"emailAddress": "fooSUFFIX@bar.com", "password" : "secret1234"}' | sed -e "s/SUFFIX/$(date +%s)/")" -H "content-type: application/json" http://${DOCKER_HOST_IP}:8081/user 2 | -------------------------------------------------------------------------------- /spring-boot-webapp/src/main/resources/config/application.yml: -------------------------------------------------------------------------------- 1 | user_registration_url: http://localhost:8081/user 2 | 3 | eureka: 4 | client: 5 | registryFetchIntervalSeconds: 5 6 | serviceUrl: 7 | defaultZone: http://localhost:8761/eureka/ 8 | 9 | 10 | -------------------------------------------------------------------------------- /zipkin-server/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /spring-boot-webapp/src/main/scala/net/chrisrichardson/microservices/restfulspringboot/backend/RegistrationError.scala: -------------------------------------------------------------------------------- 1 | package net.chrisrichardson.microservices.restfulspringboot.backend 2 | 3 | trait RegistrationError 4 | case object DuplicateRegistrationError extends RegistrationError 5 | 6 | -------------------------------------------------------------------------------- /zipkin-server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8u171-jre-alpine 2 | RUN apk --no-cache add curl 3 | HEALTHCHECK --start-period=30s --interval=5s CMD curl -f http://localhost:9411 || exit 1 4 | CMD java -jar zipkin-server.jar --server.port=9411 5 | EXPOSE 9411 6 | COPY build/libs/zipkin-server.jar . 7 | -------------------------------------------------------------------------------- /e2e-test/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Mar 03 01:04:28 PST 2016 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=http\://services.gradle.org/distributions/gradle-2.11-all.zip 7 | -------------------------------------------------------------------------------- /eureka-server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8u171-jre-alpine 2 | RUN apk --no-cache add curl 3 | HEALTHCHECK --start-period=30s --interval=5s CMD curl -f http://localhost:8761/health || exit 1 4 | CMD java -jar eureka-server.jar --server.port=8761 5 | EXPOSE 8761 6 | COPY build/libs/eureka-server.jar . 7 | -------------------------------------------------------------------------------- /eureka-server/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Mar 20 10:11:32 PDT 2014 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=http\://services.gradle.org/distributions/gradle-2.11-bin.zip 7 | -------------------------------------------------------------------------------- /zipkin-server/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Mar 20 10:11:32 PDT 2014 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=http\://services.gradle.org/distributions/gradle-2.11-bin.zip 7 | -------------------------------------------------------------------------------- /spring-boot-webapp/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Mar 03 01:04:28 PST 2016 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=http\://services.gradle.org/distributions/gradle-2.11-all.zip 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | *.ipr 3 | *.iws 4 | .DS_Store 5 | .cache 6 | .classpath 7 | .gradle 8 | .idea 9 | .project 10 | .scala_dependencies 11 | .settings 12 | .springBeans 13 | bin 14 | build 15 | build.log 16 | classes 17 | genjs 18 | node_modules 19 | npm-debug.log 20 | target 21 | out 22 | .vagrant 23 | -------------------------------------------------------------------------------- /spring-boot-restful-service/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Sep 05 20:39:18 PDT 2016 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=http\://services.gradle.org/distributions/gradle-2.11-all.zip 7 | -------------------------------------------------------------------------------- /eureka-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8761 3 | 4 | eureka: 5 | instance: 6 | hostname: localhost 7 | client: 8 | registerWithEureka: false 9 | fetchRegistry: false 10 | serviceUrl: 11 | defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ 12 | -------------------------------------------------------------------------------- /spring-boot-restful-service/src/main/resources/config/application.yml: -------------------------------------------------------------------------------- 1 | eureka: 2 | client: 3 | serviceUrl: 4 | defaultZone: http://localhost:8761/eureka/ 5 | 6 | spring: 7 | application: 8 | name: registration-service 9 | data: 10 | mongodb: 11 | uri: mongodb://localhost/userregistration 12 | -------------------------------------------------------------------------------- /spring-boot-webapp/src/main/scala/net/chrisrichardson/microservices/restfulspringboot/backend/RegistrationBackendResponse.scala: -------------------------------------------------------------------------------- 1 | package net.chrisrichardson.microservices.restfulspringboot.backend 2 | 3 | /** 4 | * Created by cer on 5/30/16. 5 | */ 6 | case class RegistrationBackendResponse(id: String, emailAddress: String) 7 | -------------------------------------------------------------------------------- /spring-boot-webapp/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8u171-jre-alpine 2 | RUN apk --no-cache add curl 3 | MAINTAINER chris@chrisrichardson.net 4 | EXPOSE 8080 5 | HEALTHCHECK --start-period=30s --interval=5s CMD curl -f http://localhost:8080/health || exit 1 6 | CMD java -jar spring-boot-webapp.jar 7 | COPY build/libs/spring-boot-webapp.jar . 8 | -------------------------------------------------------------------------------- /spring-boot-webapp/src/main/scala/net/chrisrichardson/microservices/restfulspringboot/backend/RegistrationBackendRequest.scala: -------------------------------------------------------------------------------- 1 | package net.chrisrichardson.microservices.restfulspringboot.backend 2 | 3 | /** 4 | * Created by cer on 5/30/16. 5 | */ 6 | case class RegistrationBackendRequest(emailAddress: String, password: String) 7 | -------------------------------------------------------------------------------- /spring-boot-webapp/src/main/scala/net/chrisrichardson/microservices/restfulspringboot/backend/RegistrationService.scala: -------------------------------------------------------------------------------- 1 | package net.chrisrichardson.microservices.restfulspringboot.backend 2 | 3 | trait RegistrationService { 4 | 5 | def registerUser(emailAddress: String, password : String) : Either[RegistrationError, String] 6 | 7 | } 8 | -------------------------------------------------------------------------------- /zipkin-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring.application.name: zipkin 2 | 3 | logging: 4 | level.org.springframework.cloud: DEBUG 5 | 6 | server: 7 | port: 9411 8 | 9 | spring: 10 | rabbitmq: 11 | host: ${RABBIT_HOST:localhost} 12 | sleuth: 13 | enabled: false 14 | zipkin: 15 | store: 16 | type: mem -------------------------------------------------------------------------------- /spring-boot-webapp/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /spring-boot-restful-service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8u171-jre-alpine 2 | RUN apk --no-cache add curl 3 | MAINTAINER chris@chrisrichardson.net 4 | EXPOSE 8080 5 | HEALTHCHECK --start-period=30s --interval=5s CMD curl -f http://localhost:8080/health || exit 1 6 | CMD java -jar spring-boot-restful-service.jar 7 | COPY build/libs/spring-boot-restful-service.jar . 8 | -------------------------------------------------------------------------------- /spring-boot-restful-service/src/main/scala/net/chrisrichardson/microservices/restfulspringboot/backend/RegisteredUserRepository.scala: -------------------------------------------------------------------------------- 1 | package net.chrisrichardson.microservices.restfulspringboot.backend 2 | 3 | import org.springframework.data.mongodb.repository.MongoRepository 4 | 5 | trait RegisteredUserRepository extends MongoRepository[RegisteredUser, String] -------------------------------------------------------------------------------- /spring-boot-webapp/src/main/resources/dustjs/dust-wrapper.js: -------------------------------------------------------------------------------- 1 | outputHolder = { 2 | setDone: function (javaCallback) { 3 | this.javaCallback = javaCallback; 4 | } 5 | }; 6 | 7 | myDustCallback = function (err, out) { 8 | outputHolder.err = err; 9 | outputHolder.out = out; 10 | outputHolder.javaCallback.done(err, out); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /spring-boot-webapp/src/main/resources/dustjsviews/registrationconfirmation.dust: -------------------------------------------------------------------------------- 1 | {>"main_template" title="Registration Complete"/} 2 | 3 | {Thanks for signing up to have your world changed! 6 | 7 | An email has been sent to {emailAddress} 8 | 9 | 10 | {/bodyContent} 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /spring-boot-restful-service/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /spring-boot-webapp/src/main/scala/net/chrisrichardson/microservices/restfulspringboot/backend/ScalaObjectMapper.scala: -------------------------------------------------------------------------------- 1 | package net.chrisrichardson.microservices.restfulspringboot.backend 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper 4 | import com.fasterxml.jackson.module.scala.DefaultScalaModule 5 | 6 | class ScalaObjectMapper extends ObjectMapper { 7 | 8 | registerModule(DefaultScalaModule) 9 | } -------------------------------------------------------------------------------- /spring-boot-webapp/README.md: -------------------------------------------------------------------------------- 1 | This project is a web application implemented using [Spring Boot](http://projects.spring.io/spring-boot/). 2 | It's the example code for the article [Building microservices with Spring Boot - part 2](http://plainoldobjects.com/2014/05/05/building-microservices-with-spring-boot-part-2/). 3 | 4 | To build and test this web application, please see the instructions in the parent README.md. 5 | -------------------------------------------------------------------------------- /spring-boot-restful-service/src/main/scala/net/chrisrichardson/microservices/restfulspringboot/backend/ScalaObjectMapper.scala: -------------------------------------------------------------------------------- 1 | package net.chrisrichardson.microservices.restfulspringboot.backend 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper 4 | import com.fasterxml.jackson.module.scala.DefaultScalaModule 5 | 6 | class ScalaObjectMapper extends ObjectMapper { 7 | 8 | registerModule(DefaultScalaModule) 9 | } -------------------------------------------------------------------------------- /spring-boot-restful-service/README.md: -------------------------------------------------------------------------------- 1 | This project is a RESTful web service implemented using [Spring Boot](http://projects.spring.io/spring-boot/). 2 | It is the example code for the article [Building microservices with Spring Boot - part 1](http://plainoldobjects.com/2014/04/01/building-microservices-with-spring-boot-part1/). 3 | 4 | To build and test this web application, please see the instructions in the parent README.md. 5 | -------------------------------------------------------------------------------- /e2e-test/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | apply plugin: 'scala' 3 | dependencies { 4 | compile "org.scala-lang:scala-library:2.10.2" 5 | 6 | testCompile "junit:junit:4.11" 7 | testCompile "org.scalatest:scalatest_2.10:2.1.0" 8 | testCompile "org.seleniumhq.selenium:selenium-java:2.45.0" 9 | } 10 | 11 | 12 | repositories { 13 | mavenCentral() 14 | } 15 | 16 | task wrapper(type: Wrapper) { 17 | gradleVersion = '2.11' 18 | } 19 | -------------------------------------------------------------------------------- /set-env.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -e 2 | 3 | if [ -z "$DOCKER_HOST_IP" ] ; then 4 | if [ -z "$DOCKER_HOST" ] ; then 5 | export DOCKER_HOST_IP=`hostname` 6 | else 7 | echo using ${DOCKER_HOST?} 8 | XX=${DOCKER_HOST%\:*} 9 | export DOCKER_HOST_IP=${XX#tcp\:\/\/} 10 | fi 11 | fi 12 | 13 | export SPRING_RABBITMQ_HOST=${DOCKER_HOST_IP?} 14 | export SPRING_DATA_MONGODB_URI=mongodb://${DOCKER_HOST_IP?}/userregistration 15 | -------------------------------------------------------------------------------- /spring-boot-webapp/src/main/scala/net/chrisrichardson/microservices/restfulspringboot/dustview/DustViewResolver.scala: -------------------------------------------------------------------------------- 1 | package net.chrisrichardson.microservices.restfulspringboot.dustview 2 | 3 | import org.springframework.web.servlet.view.AbstractTemplateViewResolver 4 | 5 | class DustViewResolver extends AbstractTemplateViewResolver { 6 | 7 | setViewClass(requiredViewClass()) 8 | 9 | override def requiredViewClass = classOf[DustView] 10 | 11 | } 12 | -------------------------------------------------------------------------------- /run-e2e-test-images.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | set -e 4 | 5 | ./build-docker-images.sh 6 | 7 | docker-compose -f docker-compose-images.yml up -d 8 | 9 | ./wait-for-running-system.sh 10 | 11 | #echo -n Sleeping for service discovery ... 12 | #sleep 30 13 | #echo ... running 14 | 15 | set +e 16 | (cd e2e-test ; ./gradlew cleanTest test) 17 | set -e 18 | (cd e2e-test ; ./gradlew cleanTest test) 19 | 20 | docker-compose stop 21 | docker-compose rm -v --force 22 | -------------------------------------------------------------------------------- /show-urls.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -e 2 | 3 | ./wait-for-running-system.sh 4 | 5 | echo The microservices are running 6 | echo You can visit these URLS 7 | echo http://${DOCKER_HOST_IP?}:8080/register.html - registration UI 8 | echo http://${DOCKER_HOST_IP?}:8761 - Eureka console 9 | echo http://${DOCKER_HOST_IP?}:8081/swagger-ui.html - the Backend Swagger UI 10 | echo http://${DOCKER_HOST_IP?}:9411 - Zipkin 11 | echo http://${DOCKER_HOST_IP?}:15672 - RabbitMQ admin - guest/guest login 12 | -------------------------------------------------------------------------------- /run-e2e-test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | set -e 4 | 5 | docker-compose stop 6 | docker-compose rm -v --force 7 | 8 | docker-compose up -d 9 | 10 | ./wait-for-running-system.sh 11 | 12 | #echo -n Sleeping for service discovery ... 13 | #sleep 30 14 | #echo ... running 15 | 16 | ./register-user.sh 17 | 18 | set +e 19 | (cd e2e-test ; ./gradlew cleanTest test) 20 | set -e 21 | (cd e2e-test ; ./gradlew cleanTest test) 22 | 23 | docker-compose stop 24 | docker-compose rm -v --force 25 | -------------------------------------------------------------------------------- /spring-boot-restful-service/src/main/scala/net/chrisrichardson/microservices/restfulspringboot/main/UserRegistrationMain.scala: -------------------------------------------------------------------------------- 1 | package net.chrisrichardson.microservices.restfulspringboot.main 2 | 3 | import org.springframework.boot.SpringApplication 4 | import net.chrisrichardson.microservices.restfulspringboot.UserRegistrationConfiguration 5 | 6 | object UserRegistrationMain extends App { 7 | 8 | SpringApplication.run(classOf[UserRegistrationConfiguration], args: _ *) 9 | 10 | } 11 | -------------------------------------------------------------------------------- /spring-boot-restful-service/src/main/scala/net/chrisrichardson/microservices/restfulspringboot/backend/RegisteredUser.scala: -------------------------------------------------------------------------------- 1 | package net.chrisrichardson.microservices.restfulspringboot.backend 2 | 3 | import org.springframework.data.mongodb.core.index.Indexed 4 | import org.springframework.data.mongodb.core.mapping.Document 5 | import scala.annotation.meta.field 6 | 7 | @Document 8 | case class RegisteredUser(id : String, @(Indexed@field)(unique = true) emailAddress : String, password : String) 9 | 10 | -------------------------------------------------------------------------------- /spring-boot-webapp/src/main/scala/net/chrisrichardson/microservices/restfulspringboot/main/UserRegistrationMain.scala: -------------------------------------------------------------------------------- 1 | package net.chrisrichardson.microservices.restfulspringboot.main 2 | 3 | import org.springframework.boot.SpringApplication 4 | import net.chrisrichardson.microservices.restfulspringboot.UserRegistrationConfiguration 5 | 6 | object UserRegistrationMain { 7 | 8 | def main(args: Array[String]) : Unit = SpringApplication.run(classOf[UserRegistrationConfiguration], args :_ *) 9 | 10 | } 11 | -------------------------------------------------------------------------------- /zipkin-server/src/main/java/net/chrisrichardson/microservices/zipkinserver/ZipkinServer.java: -------------------------------------------------------------------------------- 1 | package net.chrisrichardson.microservices.zipkinserver; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.sleuth.zipkin.stream.EnableZipkinStreamServer; 6 | 7 | @SpringBootApplication 8 | @EnableZipkinStreamServer 9 | public class ZipkinServer { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(ZipkinServer.class, args); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2014 Chris Richardson 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. -------------------------------------------------------------------------------- /eureka-server/src/main/java/net/chrisrichardson/microservices/eurekaserver/EurekaServer.java: -------------------------------------------------------------------------------- 1 | package net.chrisrichardson.microservices.eurekaserver; 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication; 4 | import org.springframework.boot.builder.SpringApplicationBuilder; 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 6 | 7 | @SpringBootApplication 8 | @EnableEurekaServer 9 | public class EurekaServer { 10 | 11 | public static void main(String[] args) { 12 | new SpringApplicationBuilder(EurekaServer.class).web(true).run(args); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /wait-for-services.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | set +e 3 | 4 | done=false 5 | 6 | host=$1 7 | shift 8 | path=$1 9 | shift 10 | ports=$* 11 | 12 | while [[ "$done" = false ]]; do 13 | for port in $ports; do 14 | curl -q http://${host}:${port}${path} >& /dev/null 15 | if [[ "$?" -eq "0" ]]; then 16 | done=true 17 | else 18 | done=false 19 | break 20 | fi 21 | done 22 | if [[ "$done" = true ]]; then 23 | echo $path is available 24 | break; 25 | fi 26 | echo -n . 27 | sleep 1 28 | done 29 | 30 | set -e 31 | -------------------------------------------------------------------------------- /spring-boot-webapp/src/test/scala/net/chrisrichardson/microservices/restfulspringboot/UserRegistrationTestConfiguration.scala: -------------------------------------------------------------------------------- 1 | package net.chrisrichardson.microservices.restfulspringboot 2 | 3 | import org.springframework.context.annotation.{Bean, Import, Configuration} 4 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter 5 | import org.springframework.web.client.RestTemplate 6 | import net.chrisrichardson.microservices.restfulspringboot.backend.ScalaObjectMapper 7 | import scala.collection.JavaConversions._ 8 | import java.util.concurrent.LinkedBlockingQueue 9 | 10 | @Configuration 11 | @Import(Array(classOf[UserRegistrationConfiguration])) 12 | class UserRegistrationTestConfiguration { 13 | 14 | } 15 | 16 | 17 | -------------------------------------------------------------------------------- /spring-boot-webapp/src/main/resources/static/js/registration.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | $("#registration-form").validate({ 4 | 5 | rules: { 6 | email: { 7 | required: true, 8 | email: true 9 | }, 10 | password: { 11 | required: true, 12 | minlength: 5 13 | } 14 | }, 15 | 16 | messages: { 17 | password: { 18 | required: "Please provide a password", 19 | minlength: "Your password must be at least 5 characters long" 20 | }, 21 | email: "Please enter a valid email address" 22 | }, 23 | 24 | submitHandler: function(form) { 25 | form.submit(); 26 | } 27 | }); 28 | 29 | }); 30 | 31 | -------------------------------------------------------------------------------- /eureka-server/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | buildscript { 3 | ext { 4 | springBootVersion = '1.4.0.RELEASE' 5 | } 6 | repositories { 7 | mavenCentral() 8 | } 9 | dependencies { 10 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 11 | } 12 | } 13 | 14 | apply plugin: 'spring-boot' 15 | 16 | dependencyManagement { 17 | imports { 18 | mavenBom 'org.springframework.cloud:spring-cloud-starter-parent:Brixton.SR4' 19 | } 20 | } 21 | 22 | dependencies { 23 | compile 'org.springframework.cloud:spring-cloud-starter-eureka-server' 24 | } 25 | 26 | test { 27 | forkEvery 1 28 | } 29 | 30 | repositories { 31 | mavenCentral() 32 | maven { url 'http://repo.spring.io/milestone' } 33 | } 34 | 35 | task wrapper(type: Wrapper) { 36 | gradleVersion = '2.11' 37 | } 38 | -------------------------------------------------------------------------------- /spring-boot-webapp/src/main/scala/net/chrisrichardson/microservices/restfulspringboot/backend/DiscoveryHealthIndicator.scala: -------------------------------------------------------------------------------- 1 | package net.chrisrichardson.microservices.restfulspringboot.backend 2 | 3 | import java.net.URL 4 | 5 | import com.netflix.discovery.EurekaClient 6 | import org.springframework.beans.factory.annotation.Value 7 | import org.springframework.boot.actuate.health.{Health, HealthIndicator} 8 | 9 | class DiscoveryHealthIndicator(discoveryClient: EurekaClient) extends HealthIndicator{ 10 | 11 | @Value("${user_registration_url}") 12 | var userRegistrationUrl: String = _ 13 | 14 | def health() = { 15 | val virtualHost = new URL(userRegistrationUrl).getHost 16 | try { 17 | val instance = discoveryClient.getNextServerFromEureka(virtualHost, false) 18 | println("HealthCheckInstance=", instance) 19 | Health.up().withDetail("description", s"$virtualHost discovery").build() 20 | } catch { 21 | case e : RuntimeException => 22 | Health.down(e).withDetail("description", s"$virtualHost discovery").build() 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /spring-boot-webapp/src/main/resources/dustjsviews/register.dust: -------------------------------------------------------------------------------- 1 | {>"main_template" title="Registration"/} 2 | 3 | {{.}{/globalErrors} 7 | 8 | 9 | 10 | Email address 11 | 13 | {#fieldErrors.emailAddress}{.}{/fieldErrors.emailAddress} 14 | 15 | 16 | 17 | Password 18 | 20 | {#fieldErrors.password}{.}{/fieldErrors.password} 21 | 22 | 23 | Register 24 | 25 | 26 | 27 | 28 | 29 | {/bodyContent} 30 | 31 | 32 | -------------------------------------------------------------------------------- /spring-boot-webapp/src/main/resources/dustjstemplates/main_template.dust: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {title} 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | Disrptr 19 | Changing what we think is the world - hell yeah!! 20 | 21 | 22 | 23 | 24 | {+bodyContent/} 25 | 26 | 27 | 28 | 29 |