{"id":19811113,"url":"https://github.com/accenture/openathon-2018-spring-boot-cloud","last_synced_at":"2025-05-01T08:32:30.479Z","repository":{"id":141762284,"uuid":"169755823","full_name":"Accenture/openathon-2018-spring-boot-cloud","owner":"Accenture","description":"Materials (detailed guideline and exemplar solution) for the first Openathon organized by Accenture Technology Custom Software Engineering practice in Spain, focused on learning the basic to microservice development with Spring Boot and Spring Cloud.","archived":false,"fork":false,"pushed_at":"2019-02-08T15:38:39.000Z","size":74,"stargazers_count":4,"open_issues_count":3,"forks_count":3,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-04-06T11:51:43.082Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Accenture.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-02-08T15:29:16.000Z","updated_at":"2022-12-30T11:16:54.000Z","dependencies_parsed_at":null,"dependency_job_id":"75e3b689-06aa-4047-9f93-eeb13690cbf5","html_url":"https://github.com/Accenture/openathon-2018-spring-boot-cloud","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Accenture%2Fopenathon-2018-spring-boot-cloud","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Accenture%2Fopenathon-2018-spring-boot-cloud/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Accenture%2Fopenathon-2018-spring-boot-cloud/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Accenture%2Fopenathon-2018-spring-boot-cloud/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Accenture","download_url":"https://codeload.github.com/Accenture/openathon-2018-spring-boot-cloud/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251847828,"owners_count":21653582,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-12T09:24:47.603Z","updated_at":"2025-05-01T08:32:30.472Z","avatar_url":"https://github.com/Accenture.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Openathon #1 - Accenture Technology Spain - Custom Software Engineering\n\n## Microservices with Spring Boot, Spring Cloud and Netflix OSS\n\nDemonstration of an exemplar microservices stack based in Spring Boot, Spring Cloud and Netflix OSS, including step-by-step instructions to recreate the demo stack and run it in different environments.\n\nThis demo is organised in iterations, starting from the basics and building up in complexity and features along the way.\n\nNOTE: The following instructions are created on a Windows machine, hence some commands may need slight adjustments when working on Linux/OSX, e.g. replace `%ENV_VAR%` by `${ENV_VAR}`, and replace back-slashes by forward-slashes.\n\nNOTE: This repo is adapted from https://github.com/deors/deors-demos-microservices and the exemplar solution files do not match the namespaces in the instructions below. (TBF)\n\n## Iteration 1) The basics\n\n### 1.1) Set up the configuration store\n\nThe configuration store is a repository where microservice settings are stored, and accessible for microservice initialisation at boot time.\n\nCreate and change to a directory for the project:\n\n    mkdir %HOME%\\microservices\\configstore\n    cd %HOME%\\microservices\\configstore\n\nCreate the file `application.properties`. This file will contain settings which are common to all microservices:\n\n    debug = true\n    spring.jpa.generate-ddl = true\n    management.security.enabled = false\n\nThe third configuration setting will disable security for actuator endpoints, which allows for remote operations on running applications. Disabling security in this manner should be done only when public access to those endpoints is restricted externally (for example through the web server or reverse proxy). Never expose actuator endpoints publicly and insecurely!\n\nNext, we will add the setting for all microservices. These settings may not be obvious now, but they will later once they are needed.\n\nCreate the file `eurekaservice.properties`:\n\n    server.port = ${PORT:7878}\n    eureka.client.register-with-eureka = false\n    eureka.client.fetch-registry = false\n    eureka.client.serviceUrl.defaultZone = http://${EUREKA_HOST:localhost}:${EUREKA_PORT:7878}/eureka/\n\nCreate the file `hystrixservice.properties`:\n\n    server.port = ${PORT:7979}\n    eureka.client.serviceUrl.defaultZone = http://${EUREKA_HOST:localhost}:${EUREKA_PORT:7878}/eureka/\n\nCreate the file `bookrecservice.properties`:\n\n    server.port = ${PORT:8080}\n    eureka.client.serviceUrl.defaultZone = http://${EUREKA_HOST:localhost}:${EUREKA_PORT:7878}/eureka/\n\nCreate the file `bookrecedgeservice.properties`:\n\n    server.port = ${PORT:8181}\n    eureka.client.serviceUrl.defaultZone = http://${EUREKA_HOST:localhost}:${EUREKA_PORT:7878}/eureka/\n    ribbon.eureka.enabled = true\n    defaultBookId = -1\n    defaultBookTitle = robots of dawn\n    defaultBookAuthor = isaac asimov\n\nInitialise the Git repository:\n\n    git init\n    git add .\n    git commit -m \"initial configuration\"\n\nPublish it to any remote repository online (replace the actual URL with your own online repository):\n\n    git remote add origin https://github.com/my-org/my-repo.git\n    git push origin master\n\nIt is also possible to use the local repository, without pushing it to a remote repository. A local repository is enough to test services locally (Iteration 1), but a remote repository will be needed later, as services are distributed across multiple nodes and hence the local repository might not be accessible to every service instance.\n\n### 1.2) Set up the configuration service\n\nThe configuration service, powered by Spring Cloud Config Server, is the microservice that will provide every other microservice in the system with the configuration settings they need at boot time.\n\nGo to `https://start.spring.io/` and create the project with the following settings:\n\n    group: cse.openathon.microservices\n    artifact: configservice\n    depedencies:\n        actuator\n        config server\n\nThe actuator depedency, when added, enables useful endpoints to facilitate application operations.\n\nExtract the generated zip to:\n\n    %HOME%\\microservices\n\nChange into extracted directory:\n\n    cd %HOME%\\microservices\\configservice\n\nNext, let's add the application name and set the configuration store location. Edit `src\\main\\resources\\application.properties`:\n\n    server.port = ${PORT:8888}\n    spring.application.name = configservice\n    spring.cloud.config.server.git.uri = ${CONFIG_REPO_URL:https://github.com/my-org/my-repo.git}\n    management.security.enabled = false\n\nIf the configuration store is local, leverage the File protocol in Git:\n\n    spring.cloud.config.server.git.uri = ${CONFIG_REPO_URL:file:///%HOME%/microservices/configstore}\n\nTo configure the configuration server to start automatically, edit `src\\main\\java\\cse\\openathon\\microservices\\configservice\\ConfigserviceApplication.java` and add the following class annotation:\n\n```java\n@org.springframework.cloud.config.server.EnableConfigServer\n```\n\n### 1.3) Set up the service registry and discovery service (Eureka)\n\nThe service registry and discovery service, powered by Spring Cloud and Netflix Eureka, is the microservice that will enable every other microservice in the system to register 'where' they are physically located, so others can discover them and interact with them.\n\nGo to `https://start.spring.io/` and create the project with the following settings:\n\n    group: cse.openathon.microservices\n    artifact: eurekaservice\n    depedencies:\n        actuator\n        config client\n        eureka server\n\nExtract the generated zip to:\n\n    %HOME%\\microservices\n\nChange into extracted directory:\n\n    cd %HOME%\\microservices\\eurekaservice\n\nTo ensure that the configuration service is used, properties should be moved to bootstrap phase:\n\n    ren src\\main\\resources\\application.properties bootstrap.properties\n\nEdit `src\\main\\resources\\bootstrap.properties`:\n\n    spring.application.name = eurekaservice\n    spring.cloud.config.uri = http://${CONFIG_HOST:localhost}:${CONFIG_PORT:8888}\n\nTo configure the Eureka server to start automatically, edit `src\\main\\java\\cse\\openathon\\microservices\\eurekaservice\\EurekaserviceApplication.java` and add the following class annotation:\n\n```java\n@org.springframework.cloud.netflix.eureka.server.EnableEurekaServer\n```\n\n### 1.4) Set up the circuit breaker dashboard service (Hystrix)\n\nThe circuit breaker dashboard, powered by Spring Cloud and Netflix Hystrix, will provide devs and ops teams with real-time views about service calls performance and failures including for example which of them are experimenting repeated failures. When that happens, Hystrix 'opens' the circuit and calls to a default safe method to keep the flow of information up and running smoothly, not causing cascading failures across services which may lead to major downtimes.\n\nGo to `https://start.spring.io/` and create the project with the following settings:\n\n    group: cse.openathon.microservices\n    artifact: hystrixservice\n    depedencies:\n        actuator\n        config client\n        eureka discovery\n        hystrix dashboard\n\nExtract the generated zip to:\n\n    %HOME%\\microservices\n\nChange into extracted directory:\n\n    cd %HOME%\\microservices\\hystrixservice\n\nTo ensure that the configuration service is used, properties should be moved to bootstrap phase:\n\n    ren src\\main\\resources\\application.properties bootstrap.properties\n\nEdit `src\\main\\resources\\bootstrap.properties`:\n\n    spring.application.name = hystrixservice\n    spring.cloud.config.uri = http://${CONFIG_HOST:localhost}:${CONFIG_PORT:8888}\n\nTo configure the Hystrix dashboard to start automatically, edit `src\\main\\java\\cse\\openathon\\microservices\\hystrixservice\\HystrixserviceApplication.java` and add the following class annotations:\n\n```java\n@org.springframework.cloud.client.discovery.EnableDiscoveryClient\n@org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard\n```\n\n### 1.5) Set up the book recommendation service\n\nThis is the first microservice with actual functionality on the application functional domain. bookrec service is the service which provides methods to query, create, update and remove Book entities from the data store.\n\nGo to `https://start.spring.io/` and create the project with the following settings:\n\n    group: cse.openathon.microservices\n    artifact: bookrecservice\n    depedencies:\n        actuator\n        config client\n        eureka discovery\n        web\n        rest repositories\n        rest repositories hal browser\n        jpa\n        h2\n\nExtract the generated zip to:\n\n    %HOME%\\microservices\n\nChange into extracted directory:\n\n    cd %HOME%\\microservices\\bookrecservice\n\nTo ensure that the configuration service is used, properties should be moved to bootstrap phase:\n\n    ren src\\main\\resources\\application.properties bootstrap.properties\n\nEdit `src\\main\\resources\\bootstrap.properties`:\n\n    spring.application.name = bookrecservice\n    spring.cloud.config.uri = http://${CONFIG_HOST:localhost}:${CONFIG_PORT:8888}\n\nTo configure the service to be discoverable, edit `src\\main\\java\\cse\\openathon\\microservices\\bookrecservice\\BookrecserviceApplication.java` and add the class annotation:\n\n```java\n@org.springframework.cloud.client.discovery.EnableDiscoveryClient\n```\n\nCreate the Book entity class:\n\n```java\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\n\n@Entity\npublic class Book {\n\n    @Id @GeneratedValue private Long id;\n    private String title;\n    private String author;\n}\n```\n\nAdd bean constructors (including the default constructor and one that initalizes the three properties), getters, setters and toString method, or generate them with your IDE!\n\nCreate the BookRepository data access interface:\n\n```java\nimport java.util.List;\nimport org.springframework.data.jpa.repository.Query;\nimport org.springframework.data.repository.CrudRepository;\nimport org.springframework.data.rest.core.annotation.RepositoryRestResource;\n\n@RepositoryRestResource\npublic interface BookRepository extends CrudRepository\u003cBook, Long\u003e {\n\n    @Query(\"select b from Book b order by RAND()\")\n    List\u003cBook\u003e getBooksRandomOrder();\n}\n```\n\nCreate the BookController controller class:\n\n```java\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\npublic class BookController {\n\n    @Autowired\n    private BookRepository bookRepository;\n\n    @RequestMapping(\"/bookrec\")\n    public Book getBookRecommendation() {\n        return bookRepository.getBooksRandomOrder().get(0);\n    }\n}\n```\n\nLet's add some test data. For that, create the file `src/main/resources/import.sql` and populate it with some test data for the bookrec service:\n\n```sql\ninsert into book(id, title, author) values (1, 'second foundation', 'isaac asimov')\ninsert into book(id, title, author) values (2, 'speaker for the dead', 'orson scott card')\ninsert into book(id, title, author) values (3, 'the player of games', 'iain m. banks')\ninsert into book(id, title, author) values (4, 'the lord of the rings', 'j.r.r. tolkien')\ninsert into book(id, title, author) values (5, 'the warrior apprentice', 'lois mcmaster bujold')\ninsert into book(id, title, author) values (6, 'blood of elves', 'andrzej sapkowski')\ninsert into book(id, title, author) values (7, 'harry potter and the prisoner of azkaban', 'j.k. rowling')\ninsert into book(id, title, author) values (8, '2010: odyssey two', 'arthur c. clarke')\ninsert into book(id, title, author) values (9, 'starship troopers', 'robert a. heinlein')\n```\n\n### 1.6) Set up the book recommendation edge service\n\nThe bookrec edge service is used by clients to interact with the bookrec service. As a general rule, services with business logic and access to data stores, should not be exposed directly to clients. Therefore, they are called inner services. Edge services will wrap access to inner services, as well as adding other non-functional capabilities, like routing, throttling, caching, data aggregation or fault tolerance.\n\nGo to `https://start.spring.io/` and create the project with the following settings:\n\n    group: cse.openathon.microservices\n    artifact: bookrecedgeservice\n    depedencies:\n        actuator\n        config client\n        eureka discovery\n        hystrix\n        ribbon\n        web\n\nExtract the generated zip to:\n\n    %HOME%\\microservices\n\nChange into extracted directory:\n\n    cd %HOME%\\microservices\\bookrecedgeservice\n\nTo ensure that the configuration service is used, properties should be moved to bootstrap phase:\n\n    ren src\\main\\resources\\application.properties bootstrap.properties\n\nEdit `src\\main\\resources\\bootstrap.properties`:\n\n    spring.application.name = bookrecedgeservice\n    spring.cloud.config.uri = http://${CONFIG_HOST:localhost}:${CONFIG_PORT:8888}\n\nTo configure the service to be discoverable (Eureka) and to use the circuit breaker (Hystrix), edit `src\\main\\java\\cse\\openathon\\microservices\\bookrecedgeservice\\BookrecedgeserviceApplication.java` and add the following class annotations:\n\n```java\n@org.springframework.cloud.client.discovery.EnableDiscoveryClient\n@org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker\n```\n\nNext, add the `restTemplate()` method to initalize the RestTemplate object which will be used to invoke bookrecservice. Client-side load balancing (Ribbon) is enabled just by adding the corresponding annotation:\n\n```java\n@org.springframework.context.annotation.Bean\n@org.springframework.cloud.client.loadbalancer.LoadBalanced\nRestTemplate restTemplate() {\n    return new RestTemplate();\n}\n```\n\nCreate the Book bean for the edge service, which is analogous to the Book bean for the inner service but without any persistence related code or configuration:\n\n```java\npublic class Book {\n\n    private Long id;\n    private String title;\n    private String author;\n}\n```\n\nAdd bean constructors (including the default constructor and one that initalizes the three properties), getters, setters and toString method, or generate them with your IDE!\n\nCreate the BookController controller for the edge service, including the call to bookrec through Hystrix and providing the default fallback method in case of problems with calls to bookrec:\n\n```java\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.client.RestTemplate;\n\n@RestController\npublic class BookController {\n\n    @Autowired\n    RestTemplate restTemplate;\n\n    @Value(\"${defaultBookId}\") private long defaultBookId;\n    @Value(\"${defaultBookTitle}\") private String defaultBookTitle;\n    @Value(\"${defaultBookAuthor}\") private String defaultBookAuthor;\n\n    @RequestMapping(\"/bookrecedge\")\n    @com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand(fallbackMethod = \"getDefaultBook\")\n    public Book getBookRecommendation() {\n        return restTemplate.getForObject(\"http://bookrecservice/bookrec\", Book.class);\n    }\n\n    public Book getDefaultBook() {\n        return new Book(defaultBookId, defaultBookTitle, defaultBookAuthor);\n    }\n}\n```\n\n### 1.7) Run the services locally\n\nServices are now ready to be executed locally, using the sensible default configuration settings and the embedded runtimes provided by Spring Boot.\n\nEach service will be run by executing this command in each folder:\n\n    mvnw spring-boot:run\n\nAlternatively, the Spring Boot fat Jar can be created and executed directly:\n\n    mvnw package\n    java -jar target/\u003cname-of-the-fat.jar\u003e\n\nWhen using Java 9+, Spring Boot does not add JAX-B module (java.xml.bind) to Tomcat module path automatically, causing some services to fail on startup. In that case, the missing module should be added to Tomcat module path. When using `spring-boot:run` Maven goal to run the application, use the `JDK_JAVA_OPTIONS` environment variable:\n\n    set JDK_JAVA_OPTIONS=--add-modules java.xml.bind\n    mvnw spring-boot:run\n\nWhen executing the fat Jar directly:\n\n    java -jar target/\u003cname-of-the-fat.jar\u003e --add-modules java.xml.bind\n\nThe module path might also be configured in `pom.xml` file.\n\nFollow the next sequence for running the services in order so they are able to leverage the configuration and registry services during startup:\n\n    - configservice\n    - eurekaservice\n    - hystrixservice\n    - bookrecservice\n    - bookrecedgeservice\n\n### 1.8) Test services locally\n\nOnce all the services are started, they will be available at the defined ports in the local host.\n\nAccess the configuration service through some of the actuator endpoints (remember they are currently unsecured):\n\n    http://localhost:8888/health\n    http://localhost:8888/env\n\nCheck that the configuration service is capable of returning the configuration for some of the services:\n\n    http://localhost:8888/bookrecservice/default\n    http://localhost:8888/eurekaservice/default\n\nCheck that Eureka service is up and the book recommendation service and edge service are registered:\n\n    http://localhost:7878/\n\nCheck that Hystrix service is up and running:\n\n    http://localhost:7979/hystrix\n\nAccess the HAL browser on the book recommendation service:\n\n    http://localhost:8080/\n\nAccess the book recommendation service itself:\n\n    http://localhost:8080/bookrec\n\nAccess the book recommendation edge service itself:\n\n    http://localhost:8181/bookrecedge\n\nTo verify that Hystrix fault tolerance mechanism is working as expected, stop the book recommendation service, and access the book recommendation edge service again. The default recommended book should be returned instead and the application keeps working.\n\nGo back to Hystrix dashboard and start monitoring the book recommendation edge service by registering the bookrec Hystrix stream in the dashboard (and optionally configuring the delay and page title):\n\n     http://localhost:8181/hystrix.stream\n\nOnce the Hystric stream is registered, try again to access the edge service, with and without the inner service up and running, and experiment how thresholds (number of errors in a short period of time) impact the opening and closing of the circuit between the inner and the edge service.\n\n## Iteration 2) Preparing for Docker and Swarm\n\n### 2.1) Set up Swarm\n\nThe following instructions will show how to create a simple one in VirtualBox, in the case that a swarm is not already available. In the case that a Docker Swarm is already available, skip to section 2.2.\n\nIn this setup, the swarm will be formed by three manager nodes, and three worker nodes, named:\n\n    docker-swarm-manager-1\n    docker-swarm-manager-2\n    docker-swarm-manager-3\n    docker-swarm-worker-1\n    docker-swarm-worker-2\n    docker-swarm-worker-3\n\nThe machines will be deployed in its own network:\n\n    192.168.66.1/24\n\nBeing the first IP in the DHCP pool:\n\n    192.168.66.100\n\nTo create each machine in VirtualBox, launch the following command setting the right machine name each time:\n\n    docker-machine create --driver virtualbox --virtualbox-cpu-count 1 --virtualbox-memory 1024 --virtualbox-hostonly-cidr \"192.168.66.1/24\" \u003cdocker-machine-name\u003e\n\nBefore beginning to configure the swarm, set the environment to point to the first machine. When in Windows, run this command:\n\n    @FOR /f \"tokens=*\" %i IN ('docker-machine env docker-swarm-manager-1') DO @%i\n\nWhen in Linux, run this command:\n\n    eval $(docker-machine env docker-swarm-manager-1)\n\nNext, to initialise a swarm the following command is used:\n\n    docker swarm init --advertise-addr 192.168.66.100\n\nUpon initialisation, the swarm exposes two tokens: one to add new manager nodes, one to add new worker nodes. The commands needed to get the tokens are:\n\n    docker swarm join-token manager -q\n    docker swarm join-token worker -q\n\nWith the tokens at hand, change the environment to point to each machine, every manager and worker nodes. When in Windows, run this command:\n\n    @FOR /f \"tokens=*\" %i IN ('docker-machine env \u003cdocker-machine-name\u003e') DO @%i\n\nWhen in Linux, run this command:\n\n    eval $(docker-machine env \u003cdocker-machine-name\u003e)\n\nAnd use the swarm join command in each node as it corresponds to a manager or a worker:\n\n    docker swarm join --token \u003cmanager-or-worker-token\u003e 192.168.66.100:2377\n\nOnce it is ready, the swarm can be stopped with the following command:\n\n    docker-machine stop docker-swarm-manager-1 docker-swarm-manager-2 docker-swarm-manager-3 docker-swarm-worker-1 docker-swarm-worker-2 docker-swarm-worker-3\n\nAnd to start it again, this command:\n\n    docker-machine start docker-swarm-manager-1 docker-swarm-manager-2 docker-swarm-manager-3 docker-swarm-worker-1 docker-swarm-worker-2 docker-swarm-worker-3\n\n### 2.2) Update Eureka configuration to leverage internal Swarm network\n\nWhen services are deployed inside Docker Swarm, there are multiple networks active in the running container. To be able to use correctly the client-side load balancing, each running instance must register in Eureka with the IP address corresponding to the internal network (and not the ingress network).\n\nMove to bookrecservice folder, edit bootstrap.properties and add the following configuration lines:\n\n    spring.cloud.inetutils.preferredNetworks[0] = 192.168\n    spring.cloud.inetutils.preferredNetworks[1] = 10.0\n\nAlso move to bookrecedgeservice folder, edit bootstrap.properties and add the same lines:\n\n    spring.cloud.inetutils.preferredNetworks[0] = 192.168\n    spring.cloud.inetutils.preferredNetworks[1] = 10.0\n\nFinally, do the same for eurekaservice and hystrixservice. In general, this configuration must be added in every service which is going to register in Eureka.\n\nWith these changes, the services will register in Eureka with the right IP address, both when they are running standalone (192.168 network) and when they are running inside Docker Swarm (10.0 network).\n\n### 2.3) Configure Docker image build in Maven and create the Dockerfiles\n\nIn this section, pom files will be configured with Spotify's Docker Maven plug-in, and Dockerfile files will be created, to allow each service to run as a Docker image. This process must be done for each of the microservices in the stack.\n\nLet's proceed with bookrec service as an example. Change to its directory:\n\n    cd %HOME%\\microservices\\bookrecservice\n\nEdit `pom.xml` and add inside `\u003cproperties\u003e` the following property:\n\n```xml\n    \u003cdocker.image.prefix\u003ecse\u003c/docker.image.prefix\u003e\n```\n\nAdd inside `\u003cbuild\u003e\u003cplugins\u003e` Spotify's Docker Maven plug-in configuration:\n\n```xml\n    \u003cplugin\u003e\n        \u003cgroupId\u003ecom.spotify\u003c/groupId\u003e\n        \u003cartifactId\u003edocker-maven-plugin\u003c/artifactId\u003e\n        \u003cversion\u003e1.0.0\u003c/version\u003e\n        \u003cconfiguration\u003e\n            \u003cimageName\u003e${docker.image.prefix}/${project.artifactId}\u003c/imageName\u003e\n            \u003cdockerDirectory\u003esrc/main/docker\u003c/dockerDirectory\u003e\n            \u003cimageTags\u003e\n                \u003cimageTag\u003e${project.version}\u003c/imageTag\u003e\n                \u003cimageTag\u003elatest\u003c/imageTag\u003e\n            \u003c/imageTags\u003e\n            \u003cserverId\u003edocker-hub\u003c/serverId\u003e\n            \u003cresources\u003e\n                \u003cresource\u003e\n                    \u003ctargetPath\u003e/\u003c/targetPath\u003e\n                    \u003cdirectory\u003e${project.build.directory}\u003c/directory\u003e\n                    \u003cinclude\u003e${project.build.finalName}.jar\u003c/include\u003e\n                \u003c/resource\u003e\n            \u003c/resources\u003e\n        \u003c/configuration\u003e\n    \u003c/plugin\u003e\n```\n\nCreate a new directory for the Dockerfile:\n\n    mkdir src\\main\\docker\n\nCreate the file `src\\main\\docker\\Dockerfile` and add the following content:\n\n    FROM frolvlad/alpine-oraclejdk8:slim\n    VOLUME /tmp\n    ADD cse-openathon-microservices-bookrecservice-0.0.1-SNAPSHOT.jar app.jar\n    ENTRYPOINT [\"java\",\"-Djava.security.egd=file:/dev/./urandom\",\"-jar\",\"/app.jar\"]\n\nRepeat for the other microservices (don't forget to update Jar file name in ADD command).\n\n### 2.4) Create the images\n\nTo create the images, a Docker host is needed. If using Docker for Windows, Linux or Mac, or boot2docker (VirtualBox), that Docker host is sufficient. It is also possible to use the swarm created before (one machine is enough). Let's start the swarm:\n\n    docker-machine start docker-swarm-manager-1 docker-swarm-manager-2 docker-swarm-manager-3 docker-swarm-worker-1 docker-swarm-worker-2 docker-swarm-worker-3\n\nConfigure Docker client to work with one of the machines. Wwhen in Windows, run this command:\n\n    @FOR /f \"tokens=*\" %i IN ('docker-machine env docker-swarm-manager-1') DO @%i\n\nWhen in Linux, run this command:\n\n    eval $(docker-machine env docker-swarm-manager-1)\n\nBuild and push images by running this command for each microservice:\n\n    mvn package docker:build -DpushImage\n\nImages must be pushed so they are available to all machines in the swarm, and not only in the machine used to build the image.\n\n### 2.5) Run the images as services in Swarm\n\nThe first step is to create an overlay network for all the services:\n\n    docker network create -d overlay microdemonet\n\nOnce the network is ready, launch configservice and check the status:\n\n    docker service create -p 8888:8888 --name configservice --network microdemonet cse/cse-openathon-microservices-configservice:latest\n    docker service ps configservice\n\nNext, launch eurekaservice and check the status:\n\n    docker service create -p 7878:7878 --name eurekaservice --network microdemonet -e \"CONFIG_HOST=configservice\" cse/cse-openathon-microservices-eurekaservice:latest\n    docker service ps eurekaservice\n\nOnce eurekaservice is ready to accept other service registrations, launch hystrixservice and check the status:\n\n    docker service create -p 7979:7979 --name hystrixservice --network microdemonet -e \"CONFIG_HOST=configservice\" -e \"EUREKA_HOST=eurekaservice\" cse/cse-openathon-microservices-hystrixservice:latest\n    docker service ps hystrixservice\n\nLaunch bookrecservice and check the status:\n\n    docker service create -p 8080:8080 --name bookrecservice --network microdemonet -e \"CONFIG_HOST=configservice\" -e \"EUREKA_HOST=eurekaservice\" cse/cse-openathon-microservices-bookrecservice:latest\n    docker service ps bookrecservice\n\nAnd, finally, launch bookrecedgeservice and check the status:\n\n    docker service create -p 8181:8181 --name bookrecedgeservice --network microdemonet -e \"CONFIG_HOST=configservice\" -e \"EUREKA_HOST=eurekaservice\" cse/cse-openathon-microservices-bookrecedgeservice:latest\n    docker service ps bookrecedgeservice\n\nTo quickly check whether all services are up and their configuration, use this command:\n\n    docker service ls\n\n### 2.6) Test services in Swarm\n\nOnce all the services are started, they will be available at the defined ports in the local host.\n\nAccess the configuration service through some of the actuator endpoints (remember they are currently unsecured):\n\n    http://192.168.66.100:8888/health\n    http://192.168.66.100:8888/env\n\nCheck that the configuration service is capable of returning the configuration for some of the services:\n\n    http://192.168.66.100:8888/bookrecservice/default\n    http://192.168.66.100:8888/eurekaservice/default\n\nCheck that Eureka service is up and the book recommendation service and edge service are registered:\n\n    http://192.168.66.100:7878/\n\nCheck that Hystrix service is up and running:\n\n    http://192.168.66.100:7979/hystrix\n\nAccess the HAL browser on the book recommendation service:\n\n    http://192.168.66.100:8080/\n\nAccess the book recommendation service iself:\n\n    http://192.168.66.100:8080/bookrec\n\nAccess the book recommendation edge service itself:\n\n    http://192.168.66.100:8181/bookrecedge\n\nTo verify that Hystrix fault tolerance mechanism is working as expected, stop the book recommendation service, and access the book recommendation edge service again. The default recommended book should be returned instead and the application keeps working.\n\nGo back to Hystrix dashboard and start monitoring the book recommendation edge service by registering the bookrec Hystrix stream in the dashboard (and optionally configuring the delay and page title):\n\n     http://192.168.66.100:8181/hystrix.stream\n\nOnce the Hystric stream is registered, try again to access the edge service, with and without the inner service up and running, and experiment how thresholds (number of errors in a short period of time) impact the opening and closing of the circuit between the inner and the edge service.\n\n### 2.7) Scale out the book recommendation service\n\nAsk Docker to scale out the book recommendation service\n\n    docker service scale bookrecservice=3\n\n### 2.8) Make and update and roll out the changes without service downtime\n\nMake some change and deploy a rolling update. For example change the text string returned by BookController class in file `src\\main\\java\\cse\\openathon\\microservices\\BookController.java`:\n\nRebuild and push the new image to the registry:\n\n    mvn package docker:build -DpushImage\n\nNext, the change is deployed. A label is needed to ensure the new version of 'latest' image is downloaded from registry:\n\n    docker service update --container-label-add update_cause=\"change\" --update-delay 30s --image cse/cse-openathon-microservices-bookrecservice:latest bookrecservice\n\nTo check how the change is being deployed, issue this command repeatedly:\n\n    docker service ps bookrecservice\n\n## Appendixes\n\n### Clean up the swarm\n\nTo remove running services:\n\n    docker service rm configservice eurekaservice hystrixservice bookrecservice bookrecedgeservice\n\nTo verify they are all removed:\n\n    docker service ls\n\nTo remove all stored images (this must be done in every machine if more than one was used), when in Windows, run these commands:\n\n    for /F %f in ('docker ps -a -q') do (docker rm %f)\n    for /F %f in ('docker images -q') do (docker rmi --force %f)\n\nWhen in Linux, use these commands:\n\n    docker rm $(docker ps -a -q)\n    docker rmi --force $(docker images -q)\n\nTo remove the nework inside swarm:\n\n    docker network rm microdemonet\n\nFinally, stop the machines:\n\n    docker-machine stop docker-swarm-manager-1 docker-swarm-manager-2 docker-swarm-manager-3 docker-swarm-worker-1 docker-swarm-worker-2 docker-swarm-worker-3\n\nIf desired, the swarm can be disposed, too, by removing all the machines included in it:\n\n    docker-machine rm docker-swarm-manager-1 docker-swarm-manager-2 docker-swarm-manager-3 docker-swarm-worker-1 docker-swarm-worker-2 docker-swarm-worker-3\n\n### Troubleshooting\n\nIf using more than one machine in the swarm, images must be published to Docker Hub or another registry (for example a local registry) so they are accessible to all hosts in the swarm.\n\nTo troubleshoot connectivity with curl in alpine-based images, install and use it in this way:\n\n    docker exec \u003ccontainer-id\u003e apk add --update curl \u0026\u0026 curl \u003curl\u003e\n\nTo check wich IP addresses are active in a container:\n\n    docker exec \u003ccontainer-id\u003e ifconfig -a\n\nTo check the environment variables in a container:\n\n    docker exec \u003ccontainer-id\u003e env\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faccenture%2Fopenathon-2018-spring-boot-cloud","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faccenture%2Fopenathon-2018-spring-boot-cloud","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faccenture%2Fopenathon-2018-spring-boot-cloud/lists"}