├── .gitignore
├── LICENSE
├── README.md
├── admin
├── .gitignore
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── packtpub
│ │ │ └── yummy
│ │ │ └── admin
│ │ │ └── AdminApplication.java
│ └── resources
│ │ ├── application.yaml
│ │ └── bootstrap.yaml
│ └── test
│ └── java
│ └── com
│ └── packtpub
│ └── yummy
│ └── admin
│ └── AdminApplicationTests.java
├── baselayout
├── pom.xml
└── src
│ └── main
│ └── resources
│ └── templates
│ └── layout.html
├── bookmarks
├── .bowerrc
├── Dockerfile
├── SERVICE.marker
├── bower.json
├── mvnw
├── mvnw.cmd
├── pom.xml
├── seleniumdriver
│ └── chromedriver
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── packtpub
│ │ │ └── yummy
│ │ │ ├── BookmarksApplication.java
│ │ │ ├── config
│ │ │ ├── AmqpConfig.java
│ │ │ ├── DataInitialization.java
│ │ │ ├── ErrorAdvice.java
│ │ │ ├── SecurityConfig.java
│ │ │ └── WebConfig.java
│ │ │ ├── model
│ │ │ ├── Bookmark.java
│ │ │ └── BookmarkResourceAssembler.java
│ │ │ ├── rest
│ │ │ ├── BookmarkController.java
│ │ │ ├── BookmarksController.java
│ │ │ └── ServiceDocumentController.java
│ │ │ ├── service
│ │ │ ├── BookmarkRowMapper.java
│ │ │ └── BookmarkService.java
│ │ │ └── ui
│ │ │ ├── BookmarkUiController.java
│ │ │ └── HomeController.java
│ └── resources
│ │ ├── META-INF
│ │ └── spring.factories
│ │ ├── application.yaml
│ │ ├── bootstrap.yaml
│ │ ├── db
│ │ └── migration
│ │ │ ├── V1.1__init.sql
│ │ │ ├── V1.2__add_more_fields.sql
│ │ │ └── V1.3__create_user_tables.sql
│ │ ├── static
│ │ └── components
│ │ │ ├── bookmark-form.html
│ │ │ ├── bookmarks-view.html
│ │ │ └── elements.html
│ │ └── templates
│ │ ├── bookmark
│ │ └── details.html
│ │ └── index.html
│ └── test
│ ├── java
│ └── com
│ │ └── packtpub
│ │ └── yummy
│ │ ├── MessagingTest.java
│ │ ├── YummyApplicationTests.java
│ │ └── rest
│ │ ├── BookmarkControllerTest.java
│ │ ├── BookmarksControllerTest.java
│ │ └── ServiceDocumentControllerTest.java
│ └── resources
│ ├── application.properties
│ └── bootstrap.yaml
├── configserver
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── packtpub
│ │ │ └── yummy
│ │ │ └── configserver
│ │ │ └── ConfigServerApplication.java
│ └── resources
│ │ ├── META-INF
│ │ └── spring.factories
│ │ ├── bootstrap.yaml
│ │ └── configs
│ │ ├── application-dev.yaml
│ │ ├── application-docker.yaml
│ │ └── application.yaml
│ └── test
│ ├── java
│ └── com
│ │ └── packtpub
│ │ └── yummy
│ │ └── configserver
│ │ └── ConfigServerApplicationTests.java
│ └── resources
│ └── application.properties
├── hystrixdashboard
├── .gitignore
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── packtpub
│ │ │ └── yummy
│ │ │ └── hystrixdashboard
│ │ │ └── HystrixdashboardApplication.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── packtpub
│ └── yummy
│ └── hystrixdashboard
│ └── HystrixdashboardApplicationTests.java
├── ratings
├── .bowerrc
├── .gitignore
├── Dockerfile
├── bower.json
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── packtpub
│ │ │ └── yummy
│ │ │ └── ratings
│ │ │ ├── EventService.java
│ │ │ ├── RatingController.java
│ │ │ ├── RatingRepository.java
│ │ │ ├── RatingResult.java
│ │ │ ├── RatingVote.java
│ │ │ ├── RatingsApplication.java
│ │ │ └── config
│ │ │ ├── AmqpConfig.java
│ │ │ ├── ErrorAdvice.java
│ │ │ ├── SecurityConfig.java
│ │ │ └── WebConfig.java
│ └── resources
│ │ ├── application.yaml
│ │ ├── bootstrap.yaml
│ │ ├── db
│ │ └── migration
│ │ │ └── V1.1__initial.sql
│ │ └── static
│ │ └── components
│ │ └── rating-ctrl.html
│ └── test
│ ├── java
│ └── com
│ │ └── packtpub
│ │ └── yummy
│ │ └── ratings
│ │ ├── MessagingTests.java
│ │ └── RatingsApplicationTests.java
│ └── resources
│ ├── application.properties
│ └── bootstrap.yaml
├── reverseproxy
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── packtpub
│ │ │ └── yummy
│ │ │ └── reverseproxy
│ │ │ ├── CorrelationIdZuulFilter.java
│ │ │ ├── ErrorPageController.java
│ │ │ ├── ReverseProxyApplication.java
│ │ │ └── ZuulLoginFilter.java
│ └── resources
│ │ ├── META-INF
│ │ └── spring.factories
│ │ ├── application.yaml
│ │ └── bootstrap.yaml
│ └── test
│ ├── java
│ └── com
│ │ └── packtpub
│ │ └── yummy
│ │ └── reverseproxy
│ │ └── ReverseProxyApplicationTests.java
│ └── resources
│ └── bootstrap.yaml
├── serviceregistry
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── packtpub
│ │ │ └── yummy
│ │ │ └── serviceregistry
│ │ │ └── ServiceRegistryApplication.java
│ └── resources
│ │ ├── META-INF
│ │ └── spring.factories
│ │ ├── application.yaml
│ │ └── bootstrap.yaml
│ └── test
│ ├── java
│ └── com
│ │ └── packtpub
│ │ └── yummy
│ │ └── serviceregistry
│ │ └── ServiceRegistryApplicationTests.java
│ └── resources
│ └── bootstrap.yaml
├── setup
├── buildAll.sh
├── dc-common.yaml
├── docker-compose.yaml
├── helper_buildIn.sh
├── kubernetes
│ ├── admin-pod.yaml
│ ├── bookmarks-service-pod.yaml
│ ├── configserver-pod.yaml
│ ├── hystrixdashboard-pod.yaml
│ ├── kubernetes-dashboard.yaml
│ ├── mysqlbm-pod.yaml
│ ├── mysqlra-pod.yaml
│ ├── mysqlus-pod.yaml
│ ├── nginx-ingress.yaml
│ ├── rabbitmq-pod.yaml
│ ├── ratings-service-pod.yaml
│ ├── redis-pod.yaml
│ ├── redisCommander-pod.yaml
│ ├── reverseproxy-pod.yaml
│ ├── serviceregistry-pod.yaml
│ ├── turbine-pod.yaml
│ ├── users-service-pod.yaml
│ └── zipkin-pod.yaml
├── runAll.sh
├── startInfraServices.sh
├── stopAll.sh
└── stopService.sh
├── turbine
├── .gitignore
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── packtpub
│ │ │ └── yummy
│ │ │ └── turbine
│ │ │ └── TurbineApplication.java
│ └── resources
│ │ ├── application.yaml
│ │ └── bootstrap.yaml
│ └── test
│ └── java
│ └── com
│ └── packtpub
│ └── yummy
│ └── turbine
│ └── TurbineApplicationTests.java
└── users
├── .gitignore
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── packtpub
│ │ └── yummy
│ │ └── users
│ │ ├── UsersApplication.java
│ │ ├── config
│ │ ├── DataInitialization.java
│ │ ├── SecurityConfig.java
│ │ └── WebConfig.java
│ │ └── service
│ │ └── UserService.java
└── resources
│ ├── META-INF
│ └── spring.factories
│ ├── application.yaml
│ ├── bootstrap.yaml
│ ├── db
│ └── migration
│ │ └── V1.0__init.sql
│ └── templates
│ └── login.html
└── test
├── java
└── com
│ └── packtpub
│ └── yummy
│ └── users
│ └── UsersApplicationTests.java
└── resources
├── application.properties
└── bootstrap.yaml
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .mvn/
3 | *.iml
4 | .DS_Store
5 | rabbitmq
6 | target/
7 | !.mvn/wrapper/maven-wrapper.jar
8 | application.pid
9 |
10 | ### STS ###
11 | .apt_generated
12 | .classpath
13 | .factorypath
14 | .project
15 | .settings
16 | .springBeans
17 |
18 | ### IntelliJ IDEA ###
19 | .idea
20 | *.iws
21 | *.ipr
22 |
23 | ### NetBeans ###
24 | nbproject/private/
25 | build/
26 | nbbuild/
27 | dist/
28 | nbdist/
29 | .nb-gradle/
30 |
31 | bower_components
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Packt
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | # Microservices with Spring Cloud [Integrated Course]
5 | This is the code repository for [Microservices with Spring Cloud [Integrated Course]](https://www.packtpub.com/virtualization-and-cloud/microservices-spring-cloud-integrated-course?utm_source=github&utm_medium=repository&utm_campaign=9781788392426), published by [Packt](https://www.packtpub.com/?utm_source=github). It contains all the supporting project files necessary to work through the video course from start to finish.
6 | ## About the Video Course
7 | In this course, you will learn how to split an existing application into smaller services and what you need to build, deploy, and run it. You will learn how you can use Docker to support your local development and how you can utilize it to run your application in the cloud. To work with multiple services, you will need (for example) service discovery and reverse proxies. To be able to maintain the development pace, you also need to break up your user interface, so every service can serve its own UI, and you need to learn how to communicate with these services synchronously using REST and asynchronously using events. To run your application, you need to know what is going on in your distributed application, so monitoring and tracing calls is an important topic as well, and one that you'll learn about. So overall, this course will give you valuable insights and recipes with which to create your own distributed application, for deployment to the cloud.
8 |
9 | You will also see what needs to be done to upgrade a spring boot 1.x service to spring boot 2 with the recent spring cloud release.
10 |
11 |
What You Will Learn
12 |
13 |
14 | Understanding and learning microservices.
15 | Setting up microservices.
16 | Making a bookmark application cloud-ready.
17 | Combining independent microservice UIs to a coherent user interface.
18 |
19 | ## Instructions and Navigation
20 | ### Assumed Knowledge
21 | To fully benefit from the coverage included in this course, you will need:
22 |
23 | Spring Framework knowledge
24 |
25 | Spring Boot knowledge, ideally from lesson 1-2 of this course
26 |
27 | An understanding of basic HTML and CSS syntax
28 |
29 | (Optional) Experience with deployment of java services
30 |
31 | ### Technical Requirements
32 | This course has the following software requirements:
33 | IntelliJ IDEA (ideally ultimate, there is a trial version for 30 days!)
34 |
35 | Java 8+
36 |
37 | Maven 3,x (also included in intelliJ)
38 |
39 | This course has been tested on the following system configuration:
40 |
41 | OS: Windows 7, MacOS
42 |
43 | Processor: Quad Core 3.0 Ghz
44 |
45 | Memory: 16GB
46 |
47 | Hard Disk Space: 500MB
48 |
49 |
50 | ## Related Products
51 | * [Spring Boot - Getting Started [Integrated Course]](https://www.packtpub.com/web-development/spring-boot-getting-started-integrated-course?utm_source=github&utm_medium=repository&utm_campaign=9781788298636)
52 |
53 | * [Advanced Spring Boot [Integrated Course]](https://www.packtpub.com/web-development/advanced-spring-boot-integrated-course?utm_source=github&utm_medium=repository&utm_campaign=9781788392297)
54 |
55 | * [Hands-on Application Development with Spring Boot 2.0 [Video]](https://www.packtpub.com/application-development/hands-application-development-spring-boot-20-video?utm_source=github&utm_medium=repository&utm_campaign=9781789137712)
56 |
57 | ### Download a free PDF
58 |
59 | If you have already purchased a print or Kindle version of this book, you can get a DRM-free PDF version at no cost. Simply click on the link to claim your free PDF.
60 | https://packt.link/free-ebook/9781788392426
--------------------------------------------------------------------------------
/admin/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 |
4 | ### STS ###
5 | .apt_generated
6 | .classpath
7 | .factorypath
8 | .project
9 | .settings
10 | .springBeans
11 | .sts4-cache
12 |
13 | ### IntelliJ IDEA ###
14 | .idea
15 | *.iws
16 | *.iml
17 | *.ipr
18 |
19 | ### NetBeans ###
20 | /nbproject/private/
21 | /build/
22 | /nbbuild/
23 | /dist/
24 | /nbdist/
25 | /.nb-gradle/
--------------------------------------------------------------------------------
/admin/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jre-alpine3.8
2 | RUN apk --update add curl
3 | HEALTHCHECK CMD curl -v --fail http://localhost:11111/actuator/info || exit 1
4 |
5 | COPY target/service.jar /usr/app/service.jar
6 | EXPOSE 8080 11111
7 | ENV ENVIRONMENT="local"
8 | # do not use ENTRYPOINT ["java", "-XX..."] it doesn't use environment variables for parameters!
9 | ENTRYPOINT java -Djava.net.preferIPv4Stack=true -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -jar /usr/app/service.jar --spring.profiles.active=$ENVIRONMENT,docker --spring.cloud.config.uri=http://configserver:8888
--------------------------------------------------------------------------------
/admin/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM http://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
40 |
41 | @REM set %HOME% to equivalent of $HOME
42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
43 |
44 | @REM Execute a user defined script before this one
45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
49 | :skipRcPre
50 |
51 | @setlocal
52 |
53 | set ERROR_CODE=0
54 |
55 | @REM To isolate internal variables from possible post scripts, we use another setlocal
56 | @setlocal
57 |
58 | @REM ==== START VALIDATION ====
59 | if not "%JAVA_HOME%" == "" goto OkJHome
60 |
61 | echo.
62 | echo Error: JAVA_HOME not found in your environment. >&2
63 | echo Please set the JAVA_HOME variable in your environment to match the >&2
64 | echo location of your Java installation. >&2
65 | echo.
66 | goto error
67 |
68 | :OkJHome
69 | if exist "%JAVA_HOME%\bin\java.exe" goto init
70 |
71 | echo.
72 | echo Error: JAVA_HOME is set to an invalid directory. >&2
73 | echo JAVA_HOME = "%JAVA_HOME%" >&2
74 | echo Please set the JAVA_HOME variable in your environment to match the >&2
75 | echo location of your Java installation. >&2
76 | echo.
77 | goto error
78 |
79 | @REM ==== END VALIDATION ====
80 |
81 | :init
82 |
83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
84 | @REM Fallback to current working directory if not found.
85 |
86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
88 |
89 | set EXEC_DIR=%CD%
90 | set WDIR=%EXEC_DIR%
91 | :findBaseDir
92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
93 | cd ..
94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
95 | set WDIR=%CD%
96 | goto findBaseDir
97 |
98 | :baseDirFound
99 | set MAVEN_PROJECTBASEDIR=%WDIR%
100 | cd "%EXEC_DIR%"
101 | goto endDetectBaseDir
102 |
103 | :baseDirNotFound
104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
105 | cd "%EXEC_DIR%"
106 |
107 | :endDetectBaseDir
108 |
109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
110 |
111 | @setlocal EnableExtensions EnableDelayedExpansion
112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
114 |
115 | :endReadAdditionalConfig
116 |
117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
118 |
119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
121 |
122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
123 | if ERRORLEVEL 1 goto error
124 | goto end
125 |
126 | :error
127 | set ERROR_CODE=1
128 |
129 | :end
130 | @endlocal & set ERROR_CODE=%ERROR_CODE%
131 |
132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
136 | :skipRcPost
137 |
138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
140 |
141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
142 |
143 | exit /B %ERROR_CODE%
144 |
--------------------------------------------------------------------------------
/admin/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.packtpub.yummy
7 | admin
8 | 0.0.1-SNAPSHOT
9 | jar
10 |
11 | admin
12 | Admin project for Spring Boot
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-parent
17 | 2.0.3.RELEASE
18 |
19 |
20 |
21 |
22 | UTF-8
23 | UTF-8
24 | 1.8
25 | 2.0.1
26 | Finchley.RELEASE
27 |
28 |
29 |
30 |
31 | org.springframework.boot
32 | spring-boot-starter-actuator
33 |
34 |
35 | org.springframework.boot
36 | spring-boot-starter-web
37 |
38 |
39 | de.codecentric
40 | spring-boot-admin-starter-server
41 |
42 |
43 | org.springframework.cloud
44 | spring-cloud-starter-bus-amqp
45 |
46 |
47 | org.springframework.cloud
48 | spring-cloud-starter-config
49 |
50 |
51 | org.springframework.cloud
52 | spring-cloud-starter-netflix-eureka-client
53 |
54 |
55 |
56 | org.springframework.boot
57 | spring-boot-starter-test
58 | test
59 |
60 |
61 |
62 |
63 |
64 |
65 | org.springframework.cloud
66 | spring-cloud-dependencies
67 | ${spring-cloud.version}
68 | pom
69 | import
70 |
71 |
72 | de.codecentric
73 | spring-boot-admin-dependencies
74 | ${spring-boot-admin.version}
75 | pom
76 | import
77 |
78 |
79 |
80 |
81 |
82 | service
83 |
84 |
85 | org.springframework.boot
86 | spring-boot-maven-plugin
87 |
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/admin/src/main/java/com/packtpub/yummy/admin/AdminApplication.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.admin;
2 |
3 | import de.codecentric.boot.admin.server.config.EnableAdminServer;
4 | import org.springframework.boot.SpringApplication;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 |
7 | @SpringBootApplication
8 | @EnableAdminServer
9 | public class AdminApplication {
10 |
11 | public static void main(String[] args) {
12 | SpringApplication.run(AdminApplication.class, args);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/admin/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 |
2 | server.port: 6060
3 |
--------------------------------------------------------------------------------
/admin/src/main/resources/bootstrap.yaml:
--------------------------------------------------------------------------------
1 | spring:
2 | application.name: 'admin'
3 | cloud:
4 | config:
5 | enabled: true
6 | failFast: true
7 | retry:
8 | max-attempts: 60
9 | discovery:
10 | enabled: false
11 | uri: 'http://localhost:8888'
12 |
13 |
--------------------------------------------------------------------------------
/admin/src/test/java/com/packtpub/yummy/admin/AdminApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.admin;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class AdminApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/baselayout/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.packtpub.yummy
8 | baselayout
9 | 1.0-SNAPSHOT
10 |
11 |
12 |
13 |
14 | org.springframework.boot
15 | spring-boot-dependencies
16 | 2.0.3.RELEASE
17 | pom
18 | import
19 |
20 |
21 |
22 |
23 |
24 | org.springframework.boot
25 | spring-boot-starter-thymeleaf
26 |
27 |
28 | org.thymeleaf.extras
29 | thymeleaf-extras-springsecurity4
30 |
31 |
32 | org.thymeleaf.extras
33 | thymeleaf-extras-java8time
34 |
35 |
36 | org.webjars
37 | bootstrap
38 | 3.3.7-1
39 |
40 |
41 | org.webjars
42 | webjars-locator
43 | 0.34
44 |
45 |
46 |
--------------------------------------------------------------------------------
/baselayout/src/main/resources/templates/layout.html:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 | List of all bookmarks
9 |
11 |
12 |
13 |
14 |
30 |
31 |
38 |
39 |
--------------------------------------------------------------------------------
/bookmarks/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "src/main/resources/static/components/bower_components"
3 | }
--------------------------------------------------------------------------------
/bookmarks/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jre-alpine3.8
2 | RUN apk --update add curl
3 | HEALTHCHECK CMD curl -v --fail http://localhost:11111/actuator/info || exit 1
4 |
5 | COPY target/service.jar /usr/app/service.jar
6 | EXPOSE 8080 11111
7 | ENV ENVIRONMENT="local"
8 | ENV DB_NAME="db"
9 | ENTRYPOINT java -Djava.net.preferIPv4Stack=true -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -jar /usr/app/service.jar --spring.profiles.active=$ENVIRONMENT,docker --db.name=$DB_NAME --spring.cloud.config.uri=http://configserver:8888
--------------------------------------------------------------------------------
/bookmarks/SERVICE.marker:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Microservices-with-Spring-Cloud/948b1efd780fd1c20bca134f98395882df976c5c/bookmarks/SERVICE.marker
--------------------------------------------------------------------------------
/bookmarks/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bookmarks",
3 | "dependencies": {
4 | "polymer": "Polymer/polymer#^2.0.0",
5 | "bower": "*",
6 | "iron-ajax": "PolymerElements/iron-ajax#^2.1.3",
7 | "install": "^1.0.4",
8 | "paper-input": "polymerelements/paper-input#^2.2.3",
9 | "paper-button": "polymerelements/paper-button#^2.1.1",
10 | "paper-dialog": "polymerelements/paper-dialog#^2.1.1",
11 | "iron-star-rating": "chadweimer/iron-star-rating#^2.0.1"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/bookmarks/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM http://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
40 |
41 | @REM set %HOME% to equivalent of $HOME
42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
43 |
44 | @REM Execute a user defined script before this one
45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
49 | :skipRcPre
50 |
51 | @setlocal
52 |
53 | set ERROR_CODE=0
54 |
55 | @REM To isolate internal variables from possible post scripts, we use another setlocal
56 | @setlocal
57 |
58 | @REM ==== START VALIDATION ====
59 | if not "%JAVA_HOME%" == "" goto OkJHome
60 |
61 | echo.
62 | echo Error: JAVA_HOME not found in your environment. >&2
63 | echo Please set the JAVA_HOME variable in your environment to match the >&2
64 | echo location of your Java installation. >&2
65 | echo.
66 | goto error
67 |
68 | :OkJHome
69 | if exist "%JAVA_HOME%\bin\java.exe" goto init
70 |
71 | echo.
72 | echo Error: JAVA_HOME is set to an invalid directory. >&2
73 | echo JAVA_HOME = "%JAVA_HOME%" >&2
74 | echo Please set the JAVA_HOME variable in your environment to match the >&2
75 | echo location of your Java installation. >&2
76 | echo.
77 | goto error
78 |
79 | @REM ==== END VALIDATION ====
80 |
81 | :init
82 |
83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
84 | @REM Fallback to current working directory if not found.
85 |
86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
88 |
89 | set EXEC_DIR=%CD%
90 | set WDIR=%EXEC_DIR%
91 | :findBaseDir
92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
93 | cd ..
94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
95 | set WDIR=%CD%
96 | goto findBaseDir
97 |
98 | :baseDirFound
99 | set MAVEN_PROJECTBASEDIR=%WDIR%
100 | cd "%EXEC_DIR%"
101 | goto endDetectBaseDir
102 |
103 | :baseDirNotFound
104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
105 | cd "%EXEC_DIR%"
106 |
107 | :endDetectBaseDir
108 |
109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
110 |
111 | @setlocal EnableExtensions EnableDelayedExpansion
112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
114 |
115 | :endReadAdditionalConfig
116 |
117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
118 |
119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
121 |
122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
123 | if ERRORLEVEL 1 goto error
124 | goto end
125 |
126 | :error
127 | set ERROR_CODE=1
128 |
129 | :end
130 | @endlocal & set ERROR_CODE=%ERROR_CODE%
131 |
132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
136 | :skipRcPost
137 |
138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
140 |
141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
142 |
143 | exit /B %ERROR_CODE%
144 |
--------------------------------------------------------------------------------
/bookmarks/seleniumdriver/chromedriver:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Microservices-with-Spring-Cloud/948b1efd780fd1c20bca134f98395882df976c5c/bookmarks/seleniumdriver/chromedriver
--------------------------------------------------------------------------------
/bookmarks/src/main/java/com/packtpub/yummy/BookmarksApplication.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.springframework.boot.SpringApplication;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 | import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
7 | import org.springframework.context.ConfigurableApplicationContext;
8 | import org.springframework.retry.annotation.EnableRetry;
9 | import org.springframework.web.context.support.StandardServletEnvironment;
10 |
11 | import java.util.Arrays;
12 |
13 | @SpringBootApplication
14 | @EnableCircuitBreaker
15 | @EnableRetry
16 | @Slf4j
17 | public class BookmarksApplication {
18 |
19 | public static void main(String[] args) {
20 | SpringApplication app = new SpringApplication(BookmarksApplication.class);
21 | if (noActiveProfiles(args)) {
22 | app.setAdditionalProfiles("dev", System.getProperty("user.name"));
23 | }
24 | ConfigurableApplicationContext context = app.run(args);
25 |
26 | log.info("");
27 | log.info("#######################");
28 | log.info("##### Initialized! ####");
29 | log.info("#######################");
30 | log.info(" go to: http://localhost:8080");
31 | }
32 |
33 | private static boolean noActiveProfiles(String[] args) {
34 | return new StandardServletEnvironment().getActiveProfiles().length == 0
35 | && Arrays.stream(args)
36 | .noneMatch(param -> param.startsWith("--spring.profiles.active"));
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/bookmarks/src/main/java/com/packtpub/yummy/config/AmqpConfig.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.config;
2 |
3 | import org.springframework.cloud.stream.annotation.EnableBinding;
4 | import org.springframework.cloud.stream.annotation.Output;
5 | import org.springframework.context.annotation.Configuration;
6 | import org.springframework.messaging.MessageChannel;
7 |
8 | @Configuration
9 | @EnableBinding(AmqpConfig.EventSource.class)
10 | public class AmqpConfig {
11 | public interface EventSource {
12 | String BOOKMARK_DELETIONS = "bookmarkDeletions";
13 |
14 | @Output(BOOKMARK_DELETIONS)
15 | MessageChannel bookmarkDeletions();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/bookmarks/src/main/java/com/packtpub/yummy/config/DataInitialization.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.config;
2 |
3 | import com.packtpub.yummy.model.Bookmark;
4 | import com.packtpub.yummy.service.BookmarkService;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.boot.context.event.ApplicationReadyEvent;
7 | import org.springframework.context.ApplicationListener;
8 | import org.springframework.stereotype.Component;
9 |
10 | @Component
11 | public class DataInitialization implements ApplicationListener {
12 |
13 | @Autowired
14 | BookmarkService bookmarkService;
15 |
16 | @Override
17 | public void onApplicationEvent(ApplicationReadyEvent event) {
18 | if (!bookmarkService.findAll().iterator().hasNext()) {
19 | bookmarkService.addBookmark(new Bookmark("Packt publishing", "http://packtpub.com"));
20 | bookmarkService.addBookmark(new Bookmark("orchit GmbH", "http://orchit.de"));
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/bookmarks/src/main/java/com/packtpub/yummy/config/ErrorAdvice.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.config;
2 |
3 | import lombok.Getter;
4 | import lombok.ToString;
5 | import org.springframework.dao.IncorrectResultSizeDataAccessException;
6 | import org.springframework.dao.OptimisticLockingFailureException;
7 | import org.springframework.http.HttpStatus;
8 | import org.springframework.validation.FieldError;
9 | import org.springframework.validation.ObjectError;
10 | import org.springframework.web.bind.MethodArgumentNotValidException;
11 | import org.springframework.web.bind.annotation.ControllerAdvice;
12 | import org.springframework.web.bind.annotation.ExceptionHandler;
13 | import org.springframework.web.bind.annotation.ResponseBody;
14 | import org.springframework.web.bind.annotation.ResponseStatus;
15 |
16 | import java.util.List;
17 | import java.util.stream.Collectors;
18 |
19 | @ControllerAdvice
20 | public class ErrorAdvice {
21 |
22 | @ExceptionHandler(IncorrectResultSizeDataAccessException.class)
23 | @ResponseStatus(HttpStatus.NOT_FOUND)
24 | public @ResponseBody
25 | String elementNotFound(IncorrectResultSizeDataAccessException e) {
26 | return "Could not find element! " + e.getMessage();
27 | }
28 |
29 | @ExceptionHandler(OptimisticLockingFailureException.class)
30 | @ResponseStatus(HttpStatus.CONFLICT)
31 | public @ResponseBody
32 | String elementNotFound(OptimisticLockingFailureException e) {
33 | return "Conflict! " + e.getMessage();
34 | }
35 |
36 | @ExceptionHandler(MethodArgumentNotValidException.class)
37 | @ResponseStatus(HttpStatus.BAD_REQUEST)
38 | public @ResponseBody
39 | List badRequest(MethodArgumentNotValidException e) {
40 | return e.getBindingResult().getAllErrors().stream()
41 | .map(err -> new ErrorMessage(err))
42 | .collect(Collectors.toList());
43 |
44 | }
45 |
46 | @Getter @ToString
47 | public static class ErrorMessage {
48 | String message, code, field, objectName;
49 |
50 | public ErrorMessage(ObjectError objectError) {
51 | message = objectError.getDefaultMessage();
52 | code = objectError.getCode();
53 | objectName = objectError.getObjectName();
54 | if (objectError instanceof FieldError) {
55 | field = ((FieldError) objectError).getField();
56 | }
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/bookmarks/src/main/java/com/packtpub/yummy/config/SecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.config;
2 |
3 | import lombok.AllArgsConstructor;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
7 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
8 |
9 | @Configuration
10 | @AllArgsConstructor
11 | @EnableGlobalMethodSecurity(prePostEnabled = true)
12 | public class SecurityConfig extends WebSecurityConfigurerAdapter {
13 |
14 | @Override
15 | protected void configure(HttpSecurity http) throws Exception {
16 | http
17 | .authorizeRequests()
18 | .antMatchers("/", "/actuator/**").permitAll()
19 | .anyRequest().authenticated()
20 | .and().httpBasic()
21 | .and().csrf().disable();
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/bookmarks/src/main/java/com/packtpub/yummy/config/WebConfig.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.config;
2 |
3 | import org.springframework.cloud.client.loadbalancer.LoadBalanced;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 | import org.springframework.http.MediaType;
7 | import org.springframework.http.converter.HttpMessageConverter;
8 | import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
9 | import org.springframework.web.client.RestTemplate;
10 | import org.springframework.web.servlet.LocaleResolver;
11 | import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
12 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
13 | import org.springframework.web.servlet.i18n.SessionLocaleResolver;
14 |
15 | import java.util.List;
16 | import java.util.Locale;
17 |
18 | @Configuration
19 | public class WebConfig implements WebMvcConfigurer {
20 |
21 | @Override
22 | public void extendMessageConverters(List> converters) {
23 | converters.removeIf(c -> c instanceof Jaxb2RootElementHttpMessageConverter);
24 | }
25 |
26 | @Override
27 | public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
28 | configurer.defaultContentType(MediaType.APPLICATION_JSON_UTF8);
29 | }
30 |
31 | @Bean
32 | public LocaleResolver localeResolver() {
33 | SessionLocaleResolver slr = new SessionLocaleResolver();
34 | slr.setDefaultLocale(Locale.GERMANY);
35 | return slr;
36 | }
37 |
38 | @Bean
39 | @LoadBalanced
40 | public RestTemplate restTemplate() {
41 | return new RestTemplate();
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/bookmarks/src/main/java/com/packtpub/yummy/model/Bookmark.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonCreator;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import lombok.Data;
6 | import org.hibernate.validator.constraints.Length;
7 | import org.hibernate.validator.constraints.URL;
8 |
9 | import javax.validation.constraints.NotEmpty;
10 | import javax.validation.constraints.NotNull;
11 | import java.time.LocalDateTime;
12 | import java.util.UUID;
13 |
14 | @Data
15 | public class Bookmark {
16 | @Length(max=255)
17 | @NotEmpty @NotNull
18 | private String description;
19 | private LocalDateTime createdOn;
20 | private LocalDateTime updatedOn;
21 | @Length(max=255)
22 | @NotEmpty @NotNull
23 | @URL
24 | private String url;
25 | private UUID uuid;
26 | private int version;
27 |
28 | @SuppressWarnings("unused")
29 | public Bookmark() {
30 |
31 | }
32 |
33 | public Bookmark(String description, String url) {
34 | this.url = url;
35 | uuid = null;
36 | this.description = description;
37 | }
38 |
39 | @JsonCreator
40 | public Bookmark(@JsonProperty("uuid") UUID uuid,
41 | @JsonProperty("description") String description,
42 | @JsonProperty("url") String url,
43 | @JsonProperty("version") int version,
44 | @JsonProperty("createdOn") LocalDateTime createdOn,
45 | @JsonProperty("updatedOn") LocalDateTime updatedOn) {
46 | this.description = description;
47 | this.createdOn = createdOn;
48 | this.updatedOn = updatedOn;
49 | this.url = url;
50 | this.uuid = uuid;
51 | this.version = version;
52 | }
53 | public Bookmark withUuid(UUID uuid) {
54 | return new Bookmark(uuid, description, url, version, createdOn, updatedOn);
55 | }
56 |
57 | public Bookmark withUrl(String newUrl) {
58 | return new Bookmark(uuid, description, newUrl, version, createdOn, updatedOn);
59 | }
60 | }
--------------------------------------------------------------------------------
/bookmarks/src/main/java/com/packtpub/yummy/model/BookmarkResourceAssembler.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.model;
2 |
3 | import com.packtpub.yummy.rest.BookmarkController;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.hateoas.Resource;
6 | import org.springframework.hateoas.ResourceAssembler;
7 | import org.springframework.stereotype.Component;
8 |
9 | import javax.servlet.http.HttpServletRequest;
10 | import java.util.List;
11 | import java.util.stream.Collectors;
12 | import java.util.stream.StreamSupport;
13 |
14 | import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
15 | import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
16 |
17 | @Component
18 | public class BookmarkResourceAssembler implements ResourceAssembler> {
19 |
20 | @Autowired
21 | HttpServletRequest request;
22 |
23 | @Override
24 | public Resource toResource(Bookmark entity) {
25 | Resource resource = new Resource<>(entity,
26 | linkTo(methodOn(BookmarkController.class).getBookmark(entity.getUuid())).withSelfRel());
27 | if(request.isUserInRole("ADMIN")){
28 | resource.add(
29 | linkTo(methodOn(BookmarkController.class).getBookmark(entity.getUuid())).withRel("update"),
30 | linkTo(methodOn(BookmarkController.class).getBookmark(entity.getUuid())).withRel("delete")
31 | );
32 | }
33 | return resource;
34 | }
35 |
36 | public List> toResourceList(Iterable list){
37 | return StreamSupport.stream(list.spliterator(),false)
38 | .map(this::toResource)
39 | .collect(Collectors.toList());
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/bookmarks/src/main/java/com/packtpub/yummy/rest/BookmarkController.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.rest;
2 |
3 | import com.packtpub.yummy.model.BookmarkResourceAssembler;
4 | import com.packtpub.yummy.model.Bookmark;
5 | import com.packtpub.yummy.service.BookmarkService;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.hateoas.Resource;
8 | import org.springframework.http.HttpStatus;
9 | import org.springframework.http.MediaType;
10 | import org.springframework.http.ResponseEntity;
11 | import org.springframework.security.access.prepost.PreAuthorize;
12 | import org.springframework.web.bind.annotation.*;
13 |
14 | import javax.validation.Valid;
15 | import java.util.NoSuchElementException;
16 | import java.util.UUID;
17 |
18 | @RestController
19 | @PreAuthorize("hasRole('USER')")
20 | @RequestMapping(value = "bookmark", produces = {"application/hal+json;charset=UTF-8", MediaType.APPLICATION_JSON_UTF8_VALUE})
21 | public class BookmarkController {
22 | @Autowired
23 | BookmarkResourceAssembler assembler;
24 | @Autowired
25 | BookmarkService bookmarkService;
26 |
27 | @GetMapping("template")
28 | public Resource getBookmarkTemplate() {
29 | return assembler.toResource(new Bookmark("describe me","http://fix.me"));
30 | }
31 |
32 | @GetMapping("{id}")
33 | public Resource getBookmark(@PathVariable UUID id) {
34 | return assembler.toResource(bookmarkService.find(id));
35 | }
36 |
37 | @PutMapping("{id}")
38 | @PreAuthorize("hasRole('ADMIN')")
39 | public Resource updateBookmark(@PathVariable UUID id, @RequestBody @Valid Bookmark bookmark) {
40 | return assembler.toResource(bookmarkService.update(bookmark.withUuid(id)));
41 | }
42 |
43 | @DeleteMapping("{id}")
44 | @PreAuthorize("hasRole('ADMIN')")
45 | public ResponseEntity deleteBookmark(@PathVariable UUID id) {
46 | try {
47 | bookmarkService.delete(id);
48 | return ResponseEntity.status(HttpStatus.OK).build();
49 | } catch (NoSuchElementException e) {
50 | return ResponseEntity.status(HttpStatus.NOT_MODIFIED).build();
51 | }
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/bookmarks/src/main/java/com/packtpub/yummy/rest/BookmarksController.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.rest;
2 |
3 | import com.packtpub.yummy.model.Bookmark;
4 | import com.packtpub.yummy.model.BookmarkResourceAssembler;
5 | import com.packtpub.yummy.service.BookmarkService;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.hateoas.Resource;
8 | import org.springframework.hateoas.Resources;
9 | import org.springframework.hateoas.mvc.BasicLinkBuilder;
10 | import org.springframework.http.MediaType;
11 | import org.springframework.http.ResponseEntity;
12 | import org.springframework.security.access.prepost.PreAuthorize;
13 | import org.springframework.web.bind.annotation.*;
14 |
15 | import javax.servlet.http.HttpServletRequest;
16 | import javax.validation.Valid;
17 | import java.util.UUID;
18 |
19 | import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
20 | import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
21 |
22 | @RestController
23 | @RequestMapping(value = "bookmarks", produces = {"application/hal+json;charset=UTF-8", MediaType.APPLICATION_JSON_UTF8_VALUE})
24 | @PreAuthorize("hasRole('USER')")
25 | public class BookmarksController {
26 | @Autowired
27 | BookmarkResourceAssembler resourceAssembler;
28 | @Autowired
29 | BookmarkService bookmarkService;
30 |
31 | @PostMapping
32 | @PreAuthorize("hasRole('ADMIN')")
33 | public ResponseEntity addBookmark(@RequestBody @Valid Bookmark bookmark){
34 | UUID uuid = bookmarkService.addBookmark(bookmark);
35 | return ResponseEntity.created(
36 | BasicLinkBuilder.linkToCurrentMapping()
37 | .slash("bookmark")
38 | .slash(uuid)
39 | .toUri())
40 | .build();
41 | }
42 |
43 | @GetMapping
44 | public Resources> findAllBookmarks(HttpServletRequest request){
45 | Resources> bookmarks = new Resources<>(
46 | resourceAssembler.toResourceList(bookmarkService.findAll()),
47 | BasicLinkBuilder.linkToCurrentMapping()
48 | .slash("bookmarks").withSelfRel()
49 | );
50 | if(request.isUserInRole("ADMIN")){
51 | bookmarks.add(
52 | linkTo(methodOn(BookmarksController.class).addBookmark(null)).withRel("add"),
53 | linkTo(methodOn(BookmarkController.class).getBookmarkTemplate()).withRel("template")
54 | );
55 | }
56 | return bookmarks;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/bookmarks/src/main/java/com/packtpub/yummy/rest/ServiceDocumentController.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.rest;
2 |
3 | import org.springframework.hateoas.Resource;
4 | import org.springframework.hateoas.mvc.BasicLinkBuilder;
5 | import org.springframework.web.bind.annotation.GetMapping;
6 | import org.springframework.web.bind.annotation.RequestMapping;
7 | import org.springframework.web.bind.annotation.RestController;
8 |
9 | import java.net.URISyntaxException;
10 |
11 | import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
12 | import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
13 |
14 | @RestController
15 | @RequestMapping(produces = "application/hal+json;charset=UTF-8")
16 | public class ServiceDocumentController {
17 | @GetMapping("/")
18 | public Resource getServiceDocument() throws URISyntaxException {
19 | return new Resource<>("Yummy is the best service",
20 | BasicLinkBuilder.linkToCurrentMapping().withSelfRel(),
21 | linkTo(methodOn(BookmarksController.class).addBookmark(null)).withRel("bookmarks")
22 | );
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/bookmarks/src/main/java/com/packtpub/yummy/service/BookmarkRowMapper.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.service;
2 |
3 | import com.packtpub.yummy.model.Bookmark;
4 | import org.springframework.jdbc.core.RowMapper;
5 |
6 | import java.sql.ResultSet;
7 | import java.sql.SQLException;
8 | import java.util.UUID;
9 |
10 | class BookmarkRowMapper implements RowMapper {
11 | @Override
12 | public Bookmark mapRow(ResultSet rs, int rowNum) throws SQLException {
13 | return new Bookmark(
14 | UUID.fromString(rs.getString("uuid")),
15 | rs.getString("description"),
16 | rs.getString("url"),
17 | rs.getInt("version"),
18 | rs.getTimestamp("createdon").toLocalDateTime(),
19 | rs.getTimestamp("updatedon").toLocalDateTime()
20 | );
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/bookmarks/src/main/java/com/packtpub/yummy/service/BookmarkService.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.service;
2 |
3 | import com.packtpub.yummy.config.AmqpConfig;
4 | import com.packtpub.yummy.model.Bookmark;
5 | import lombok.AllArgsConstructor;
6 | import lombok.Data;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.cloud.context.config.annotation.RefreshScope;
9 | import org.springframework.dao.DataAccessException;
10 | import org.springframework.dao.OptimisticLockingFailureException;
11 | import org.springframework.http.HttpStatus;
12 | import org.springframework.jdbc.core.JdbcTemplate;
13 | import org.springframework.messaging.support.MessageBuilder;
14 | import org.springframework.stereotype.Service;
15 | import org.springframework.transaction.annotation.Transactional;
16 | import org.springframework.web.bind.annotation.ResponseStatus;
17 |
18 | import java.util.UUID;
19 |
20 | @Service
21 | @Transactional
22 | @RefreshScope
23 | public class BookmarkService {
24 |
25 | @Autowired
26 | AmqpConfig.EventSource source;
27 |
28 | @Autowired
29 | JdbcTemplate jdbcTemplate;
30 |
31 | public UUID addBookmark(Bookmark bookmark) {
32 | UUID uuid = UUID.randomUUID();
33 | jdbcTemplate.update("INSERT INTO bookmark (url, uuid, version, description)" +
34 | " VALUES (?,?,1,?)", bookmark.getUrl(), uuid.toString(), bookmark.getDescription());
35 | System.out.println("http://localhost:8080/bookmark/" + uuid);
36 | return uuid;
37 | }
38 |
39 | public Bookmark find(UUID id) {
40 | return jdbcTemplate.queryForObject("SELECT * FROM bookmark WHERE uuid=?",
41 | new BookmarkRowMapper(), id.toString());
42 |
43 | }
44 |
45 | public Iterable findAll() {
46 | return jdbcTemplate.query("SELECT * FROM bookmark",
47 | new BookmarkRowMapper());
48 | }
49 |
50 | public Bookmark update(Bookmark bookmark) {
51 | find(bookmark.getUuid());
52 | int update = jdbcTemplate.update(
53 | "UPDATE bookmark SET url=?, description=?, " +
54 | " updatedon=current_timestamp(), version=version+1 " +
55 | " WHERE uuid=? AND version =?",
56 | bookmark.getUrl(), bookmark.getDescription(), bookmark.getUuid().toString(), bookmark.getVersion()
57 | );
58 | if (update != 1) throw new OptimisticLockingFailureException("Stale update detected for " + bookmark.getUuid());
59 | return find(bookmark.getUuid());
60 | }
61 |
62 | public void delete(UUID id) {
63 | if (jdbcTemplate.update("DELETE FROM bookmark WHERE uuid=?", id.toString()) != 1)
64 | throw new NotModifiedDataAccessException("Bookmark already gone");
65 | source.bookmarkDeletions().send(MessageBuilder
66 | .withPayload(
67 | new DeletionEvent("bookmark", id.toString()))
68 | .build());
69 | }
70 |
71 | @ResponseStatus(HttpStatus.NOT_MODIFIED)
72 | public static class NotModifiedDataAccessException extends DataAccessException {
73 |
74 | public NotModifiedDataAccessException(String msg) {
75 | super(msg);
76 | }
77 | }
78 |
79 | @Data
80 | @AllArgsConstructor
81 | public static class DeletionEvent {
82 | String type;
83 | String entityId;
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/bookmarks/src/main/java/com/packtpub/yummy/ui/BookmarkUiController.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.ui;
2 |
3 | import com.packtpub.yummy.model.Bookmark;
4 | import com.packtpub.yummy.service.BookmarkService;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.dao.IncorrectResultSizeDataAccessException;
7 | import org.springframework.security.access.prepost.PreAuthorize;
8 | import org.springframework.stereotype.Controller;
9 | import org.springframework.ui.Model;
10 | import org.springframework.web.bind.annotation.GetMapping;
11 | import org.springframework.web.bind.annotation.ModelAttribute;
12 | import org.springframework.web.bind.annotation.PathVariable;
13 | import org.springframework.web.bind.annotation.RequestMapping;
14 |
15 | import java.util.Optional;
16 | import java.util.UUID;
17 |
18 | @Controller
19 | @PreAuthorize("hasRole('USER')")
20 | @RequestMapping("/bookmark/")
21 | public class BookmarkUiController {
22 | @Autowired
23 | BookmarkService bookmarkService;
24 |
25 | @ModelAttribute
26 | public Bookmark bookmark(@PathVariable Optional id){
27 | return id
28 | .map(uuid -> bookmarkService.find(uuid))
29 | .orElseThrow(()-> new IncorrectResultSizeDataAccessException(1));
30 | }
31 |
32 | @GetMapping("{id}")
33 | public String details(@PathVariable UUID id, Model model) {
34 | return "bookmark/details";
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/bookmarks/src/main/java/com/packtpub/yummy/ui/HomeController.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.ui;
2 |
3 | import org.springframework.security.access.prepost.PreAuthorize;
4 | import org.springframework.stereotype.Controller;
5 | import org.springframework.web.bind.annotation.GetMapping;
6 | import org.springframework.web.bind.annotation.RequestMapping;
7 |
8 | @Controller
9 | @RequestMapping("/")
10 | public class HomeController {
11 |
12 | @GetMapping
13 | @PreAuthorize("isAuthenticated()")
14 | public String displayHome() {
15 | return "index";
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/bookmarks/src/main/resources/META-INF/spring.factories:
--------------------------------------------------------------------------------
1 | org.springframework.context.ApplicationListener=\
2 | org.springframework.boot.context.ApplicationPidFileWriter
--------------------------------------------------------------------------------
/bookmarks/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 | spring:
2 | datasource:
3 | url: "jdbc:mysql://localhost:3306/packtdb"
4 | username: "packt"
5 | password: "superSecret"
6 |
7 |
--------------------------------------------------------------------------------
/bookmarks/src/main/resources/bootstrap.yaml:
--------------------------------------------------------------------------------
1 | spring:
2 | application.name: 'bookmarks'
3 | cloud:
4 | config:
5 | failFast: true
6 | retry:
7 | max-attempts: 60
8 | discovery:
9 | enabled: false
10 | uri: 'http://localhost:8888'
11 |
--------------------------------------------------------------------------------
/bookmarks/src/main/resources/db/migration/V1.1__init.sql:
--------------------------------------------------------------------------------
1 | create table bookmark(
2 | uuid CHAR(36) not null,
3 | url VARCHAR(255),
4 | version int not null default 1,
5 | PRIMARY KEY (uuid)
6 | )
--------------------------------------------------------------------------------
/bookmarks/src/main/resources/db/migration/V1.2__add_more_fields.sql:
--------------------------------------------------------------------------------
1 |
2 | ALTER TABLE bookmark ADD description VARCHAR(255) NULL;
3 | ALTER TABLE bookmark ADD createdon TIMESTAMP DEFAULT current_timestamp() NULL;
4 | ALTER TABLE bookmark ADD updatedon TIMESTAMP DEFAULT current_timestamp() NULL;
--------------------------------------------------------------------------------
/bookmarks/src/main/resources/db/migration/V1.3__create_user_tables.sql:
--------------------------------------------------------------------------------
1 |
2 |
3 | CREATE TABLE users (
4 | username VARCHAR(255) NOT NULL,
5 | password VARCHAR(255) NOT NULL,
6 | enabled TINYINT NOT NULL DEFAULT 1,
7 | PRIMARY KEY (username)
8 | );
9 |
10 | CREATE TABLE user_roles (
11 | user_role_id INT(11) NOT NULL AUTO_INCREMENT,
12 | username VARCHAR(255) NOT NULL,
13 | role VARCHAR(255) NOT NULL,
14 | PRIMARY KEY (user_role_id),
15 | CONSTRAINT uni_username_role UNIQUE (role, username),
16 | CONSTRAINT fk_username FOREIGN KEY (username) REFERENCES users (username)
17 | ON DELETE CASCADE ON UPDATE CASCADE
18 | );
19 |
--------------------------------------------------------------------------------
/bookmarks/src/main/resources/static/components/bookmark-form.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
21 |
23 |
26 |
27 | Edit Bookmark [[_bookmark.id]]
28 |
29 |
30 |
34 |
35 |
36 |
80 |
--------------------------------------------------------------------------------
/bookmarks/src/main/resources/static/components/bookmarks-view.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
22 |
24 |
25 |
26 |
27 |
28 | Add Bookmark
29 |
30 |
31 |
32 |
33 |
34 |
35 | [[_displayIndex(index)]]
36 |
37 | [[bookmark.description]]
38 |
39 |
40 | {{bookmark.url}}
41 |
42 |
43 | Delete
44 | Edit
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
99 |
--------------------------------------------------------------------------------
/bookmarks/src/main/resources/static/components/elements.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/bookmarks/src/main/resources/templates/bookmark/details.html:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 | Bookmark details view
9 |
10 |
11 |
12 | Bookmark Details
13 |
14 | Hello Username
15 |
16 |
17 |
18 |
19 | Bookmark
20 |
23 |
24 | Created on: now
25 |
26 |
27 | Last update on: now
28 |
29 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/bookmarks/src/main/resources/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 | List of all bookmarks
10 |
11 |
12 |
16 |
17 |
18 |
19 |
20 |
List of all bookmarks
21 |
22 | Hello Username
23 |
24 |
27 |
28 |
29 |
30 |
31 |
35 |
36 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/bookmarks/src/test/java/com/packtpub/yummy/MessagingTest.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy;
2 |
3 | import com.fasterxml.jackson.core.JsonProcessingException;
4 | import com.fasterxml.jackson.databind.ObjectMapper;
5 | import com.packtpub.yummy.config.AmqpConfig;
6 | import com.packtpub.yummy.service.BookmarkService;
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.boot.test.context.SpringBootTest;
11 | import org.springframework.boot.test.mock.mockito.MockBean;
12 | import org.springframework.cloud.stream.test.binder.MessageCollector;
13 | import org.springframework.jdbc.core.JdbcTemplate;
14 | import org.springframework.messaging.Message;
15 | import org.springframework.test.context.junit4.SpringRunner;
16 |
17 | import java.util.UUID;
18 |
19 | import static org.assertj.core.api.Assertions.assertThat;
20 | import static org.mockito.ArgumentMatchers.anyString;
21 | import static org.mockito.ArgumentMatchers.eq;
22 | import static org.mockito.Mockito.when;
23 |
24 | @RunWith(SpringRunner.class)
25 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
26 | public class MessagingTest {
27 | @Autowired
28 | BookmarkService service;
29 | @MockBean
30 | JdbcTemplate jdbcTemplate;
31 | @Autowired
32 | AmqpConfig.EventSource source;
33 | @Autowired
34 | ObjectMapper mapper;
35 | @Autowired
36 | MessageCollector collector;
37 |
38 | @Test
39 | public void messageIsSent() throws JsonProcessingException {
40 | UUID id = UUID.randomUUID();
41 | when(jdbcTemplate.update(anyString(), eq(id.toString()))).thenReturn(1);
42 |
43 | service.delete(id);
44 |
45 | Message received =
46 | (Message) collector.forChannel(source.bookmarkDeletions()).poll();
47 | assertThat(received.getPayload()).isEqualTo(
48 | mapper.writer().writeValueAsString(
49 | new BookmarkService.DeletionEvent("bookmark", id.toString())
50 | )
51 | );
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/bookmarks/src/test/java/com/packtpub/yummy/YummyApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class YummyApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/bookmarks/src/test/java/com/packtpub/yummy/rest/BookmarksControllerTest.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.rest;
2 |
3 | import com.fasterxml.jackson.core.type.TypeReference;
4 | import com.fasterxml.jackson.databind.ObjectMapper;
5 | import com.packtpub.yummy.model.Bookmark;
6 | import com.packtpub.yummy.service.BookmarkService;
7 | import org.junit.Before;
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 | import org.mockito.Mockito;
11 | import org.springframework.beans.factory.annotation.Autowired;
12 | import org.springframework.beans.factory.annotation.Qualifier;
13 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
14 | import org.springframework.boot.test.context.SpringBootTest;
15 | import org.springframework.boot.test.mock.mockito.MockBean;
16 | import org.springframework.hateoas.Resources;
17 | import org.springframework.http.MediaType;
18 | import org.springframework.security.test.context.support.WithMockUser;
19 | import org.springframework.test.context.junit4.SpringRunner;
20 | import org.springframework.test.web.servlet.MockMvc;
21 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
22 |
23 | import java.util.Arrays;
24 |
25 | import static org.hamcrest.CoreMatchers.is;
26 | import static org.hamcrest.MatcherAssert.assertThat;
27 | import static org.hamcrest.Matchers.greaterThanOrEqualTo;
28 | import static org.junit.Assert.assertTrue;
29 | import static org.mockito.Mockito.never;
30 | import static org.mockito.Mockito.when;
31 | import static org.mockito.internal.verification.VerificationModeFactory.atLeastOnce;
32 | import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
33 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
34 | import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
35 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
36 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
37 |
38 | @RunWith(SpringRunner.class)
39 | @SpringBootTest
40 | @AutoConfigureMockMvc
41 | @WithMockUser(username = "admin", roles = {"ADMIN", "USER"})
42 | public class BookmarksControllerTest {
43 | @Autowired
44 | MockMvc mvc;
45 | @MockBean
46 | BookmarkService bookmarkService;
47 | @Autowired
48 | @Qualifier("_halObjectMapper")
49 | ObjectMapper mapper;
50 |
51 | @Before
52 | public void setup() {
53 | Mockito.reset(bookmarkService);
54 | }
55 |
56 | @Test
57 | public void addABookmark() throws Exception {
58 | Bookmark value = new Bookmark("Packt publishing", "http://packtpub.com");
59 | addBookmark(value);
60 | Mockito.verify(bookmarkService, atLeastOnce()).addBookmark(Mockito.any(Bookmark.class));
61 | }
62 |
63 | @Test
64 | public void addABookmarkFailsBecauseDescriptionIsNull() throws Exception {
65 | Bookmark value = new Bookmark(null, "http://packtpub.com");
66 | mvc.perform(
67 | post("/bookmarks")
68 | .contentType(MediaType.APPLICATION_JSON_UTF8)
69 | .content(mapper.writeValueAsString(value))
70 | .with(csrf())
71 | ).andDo(print())
72 | .andExpect(status().isBadRequest())
73 | .andExpect(jsonPath("$[0].field").value("description"));
74 | Mockito.verify(bookmarkService, never()).addBookmark(Mockito.any(Bookmark.class));
75 | }
76 |
77 | @Test
78 | public void addABookmarkFailsBecauseUrlIsNull() throws Exception {
79 | Bookmark value = new Bookmark("testtest", "broken://url.com");
80 | mvc.perform(
81 | post("/bookmarks")
82 | .contentType(MediaType.APPLICATION_JSON_UTF8)
83 | .content(mapper.writeValueAsString(value))
84 | .with(csrf())
85 | ).andDo(print())
86 | .andExpect(status().isBadRequest())
87 | .andExpect(jsonPath("$[0].field").value("url"));
88 | Mockito.verify(bookmarkService, never()).addBookmark(Mockito.any(Bookmark.class));
89 | }
90 |
91 | @Test
92 | public void getAllBookmarks() throws Exception {
93 |
94 | when(bookmarkService.findAll()).thenReturn(Arrays.asList(
95 | new Bookmark("Packt publishing", "http://packtpub.com"),
96 | new Bookmark("orchit GmbH homepage", "http://orchit.de")));
97 | String result = mvc.perform(
98 | MockMvcRequestBuilders.get("/bookmarks")
99 | .accept("application/hal+json;charset=UTF-8", "application/json;charset=UTF-8")
100 | ).andDo(print())
101 | .andReturn().getResponse().getContentAsString();
102 | Resources output = mapper.readValue(result, new TypeReference>() {
103 | });
104 |
105 | assertThat(output.getContent().size(), is(greaterThanOrEqualTo(2)));
106 | assertTrue(output.getContent().stream()
107 | .anyMatch(bookmark ->
108 | bookmark.getUrl().equals("http://orchit.de")));
109 | assertTrue(output.getContent().stream()
110 | .anyMatch(bookmark ->
111 | bookmark.getUrl().equals("http://packtpub.com")));
112 | }
113 |
114 | private void addBookmark(Bookmark value) throws Exception {
115 | mvc.perform(
116 | post("/bookmarks")
117 | .contentType(MediaType.APPLICATION_JSON_UTF8)
118 | .content(mapper.writeValueAsString(value))
119 | .with(csrf())
120 | ).andExpect(status().isCreated());
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/bookmarks/src/test/java/com/packtpub/yummy/rest/ServiceDocumentControllerTest.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.rest;
2 |
3 | import com.fasterxml.jackson.core.type.TypeReference;
4 | import com.fasterxml.jackson.databind.ObjectMapper;
5 | import org.hamcrest.Matchers;
6 | import org.junit.Test;
7 | import org.junit.runner.RunWith;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.beans.factory.annotation.Qualifier;
10 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
11 | import org.springframework.boot.test.context.SpringBootTest;
12 | import org.springframework.hateoas.Resource;
13 | import org.springframework.security.test.context.support.WithMockUser;
14 | import org.springframework.test.context.junit4.SpringRunner;
15 | import org.springframework.test.web.servlet.MockMvc;
16 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
17 |
18 | import java.util.List;
19 | import java.util.stream.Collectors;
20 |
21 | import static junit.framework.TestCase.assertEquals;
22 | import static org.hamcrest.MatcherAssert.assertThat;
23 | import static org.junit.Assert.assertTrue;
24 | import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
25 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
26 |
27 | @RunWith(SpringRunner.class)
28 | @SpringBootTest
29 | @AutoConfigureMockMvc
30 | @WithMockUser(username = "user", roles = "USER")
31 | public class ServiceDocumentControllerTest {
32 | @Autowired
33 | MockMvc mvc;
34 | @Autowired @Qualifier("_halObjectMapper")
35 | ObjectMapper mapper;
36 |
37 | @Test
38 | public void getServiceDocument() throws Exception {
39 | String result = mvc.perform(
40 | MockMvcRequestBuilders.get("/")
41 | .accept("application/hal+json;charset=UTF-8")
42 | ).andDo(print())
43 | .andExpect(content()
44 | .contentTypeCompatibleWith("application/hal+json;charset=UTF-8"))
45 | .andReturn().getResponse().getContentAsString();
46 |
47 | Resource value = mapper.readValue(result, new TypeReference>() {
48 | });
49 |
50 | List linkRels = value.getLinks().stream().map(link -> link.getRel()).collect(Collectors.toList());
51 | assertThat(linkRels, Matchers.hasItem("self"));
52 | assertEquals(value.getLink("self"), value.getId());
53 |
54 | assertTrue(value.hasLink("bookmarks"));
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/bookmarks/src/test/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.datasource.driver-class-name=org.h2.Driver
2 | spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
3 | spring.datasource.username=sa
4 | spring.datasource.password=sa
5 | #Disable discovery
6 | eureka.client.enabled=false
7 | spring.jpa.show-sql=true
8 | spring.profiles.active=test
9 | spring.data.redis.repositories.enabled=false
10 | spring.session.store-type=none
11 |
12 |
--------------------------------------------------------------------------------
/bookmarks/src/test/resources/bootstrap.yaml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | config:
4 | enabled: false
5 |
--------------------------------------------------------------------------------
/configserver/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jre-alpine3.8
2 | RUN apk --update add curl
3 | HEALTHCHECK CMD curl -v --fail http://localhost:11111/actuator/info || exit 1
4 |
5 | COPY target/service.jar /usr/app/service.jar
6 | EXPOSE 8888 11111
7 |
8 | ENTRYPOINT java -Djava.net.preferIPv4Stack=true -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -jar /usr/app/service.jar --spring.rabbitmq.host=rabbitmq
--------------------------------------------------------------------------------
/configserver/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM http://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
40 |
41 | @REM set %HOME% to equivalent of $HOME
42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
43 |
44 | @REM Execute a user defined script before this one
45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
49 | :skipRcPre
50 |
51 | @setlocal
52 |
53 | set ERROR_CODE=0
54 |
55 | @REM To isolate internal variables from possible post scripts, we use another setlocal
56 | @setlocal
57 |
58 | @REM ==== START VALIDATION ====
59 | if not "%JAVA_HOME%" == "" goto OkJHome
60 |
61 | echo.
62 | echo Error: JAVA_HOME not found in your environment. >&2
63 | echo Please set the JAVA_HOME variable in your environment to match the >&2
64 | echo location of your Java installation. >&2
65 | echo.
66 | goto error
67 |
68 | :OkJHome
69 | if exist "%JAVA_HOME%\bin\java.exe" goto init
70 |
71 | echo.
72 | echo Error: JAVA_HOME is set to an invalid directory. >&2
73 | echo JAVA_HOME = "%JAVA_HOME%" >&2
74 | echo Please set the JAVA_HOME variable in your environment to match the >&2
75 | echo location of your Java installation. >&2
76 | echo.
77 | goto error
78 |
79 | @REM ==== END VALIDATION ====
80 |
81 | :init
82 |
83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
84 | @REM Fallback to current working directory if not found.
85 |
86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
88 |
89 | set EXEC_DIR=%CD%
90 | set WDIR=%EXEC_DIR%
91 | :findBaseDir
92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
93 | cd ..
94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
95 | set WDIR=%CD%
96 | goto findBaseDir
97 |
98 | :baseDirFound
99 | set MAVEN_PROJECTBASEDIR=%WDIR%
100 | cd "%EXEC_DIR%"
101 | goto endDetectBaseDir
102 |
103 | :baseDirNotFound
104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
105 | cd "%EXEC_DIR%"
106 |
107 | :endDetectBaseDir
108 |
109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
110 |
111 | @setlocal EnableExtensions EnableDelayedExpansion
112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
114 |
115 | :endReadAdditionalConfig
116 |
117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
118 |
119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
121 |
122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
123 | if ERRORLEVEL 1 goto error
124 | goto end
125 |
126 | :error
127 | set ERROR_CODE=1
128 |
129 | :end
130 | @endlocal & set ERROR_CODE=%ERROR_CODE%
131 |
132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
136 | :skipRcPost
137 |
138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
140 |
141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
142 |
143 | exit /B %ERROR_CODE%
144 |
--------------------------------------------------------------------------------
/configserver/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.packtpub.yummy
7 | configserver
8 | 0.0.1-SNAPSHOT
9 | jar
10 |
11 | ConfigServer
12 | Serving your configs
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-parent
17 | 2.0.3.RELEASE
18 |
19 |
20 |
21 |
22 | UTF-8
23 | UTF-8
24 | 1.8
25 | Finchley.RELEASE
26 |
27 |
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-properties-migrator
32 | runtime
33 |
34 |
35 | org.springframework.cloud
36 | spring-cloud-config-server
37 |
38 |
39 | org.springframework.cloud
40 | spring-cloud-starter-bus-amqp
41 |
42 |
43 |
44 | org.springframework.boot
45 | spring-boot-starter-test
46 | test
47 |
48 |
49 |
50 |
51 |
52 |
53 | org.springframework.cloud
54 | spring-cloud-dependencies
55 | ${spring-cloud.version}
56 | pom
57 | import
58 |
59 |
60 |
61 |
62 |
63 | service
64 |
65 |
66 | org.springframework.boot
67 | spring-boot-maven-plugin
68 |
69 | true
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | spring-milestones
78 | Spring milestones
79 | https://repo.spring.io/libs-milestones
80 |
81 | false
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/configserver/src/main/java/com/packtpub/yummy/configserver/ConfigServerApplication.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.configserver;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.config.server.EnableConfigServer;
6 |
7 | @SpringBootApplication @EnableConfigServer
8 | public class ConfigServerApplication {
9 |
10 | public static void main(String[] args) {
11 | SpringApplication.run(ConfigServerApplication.class, args);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/configserver/src/main/resources/META-INF/spring.factories:
--------------------------------------------------------------------------------
1 | org.springframework.context.ApplicationListener=\
2 | org.springframework.boot.context.ApplicationPidFileWriter
--------------------------------------------------------------------------------
/configserver/src/main/resources/bootstrap.yaml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: configserver
4 | profiles:
5 | active: native
6 | cloud:
7 | config:
8 | server:
9 | native:
10 | search-locations: classpath:/configs
11 | rabbitmq:
12 | username: 'packt'
13 | password: 'publishing'
14 |
15 | server.port: 8888
16 |
17 | management:
18 | server:
19 | port: 11111
20 |
21 |
22 |
--------------------------------------------------------------------------------
/configserver/src/main/resources/configs/application-dev.yaml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #logging.level:
4 | # org.springframework.web: DEBUG
5 | # com.packtpub: DEBUG
6 |
7 | eureka:
8 | instance:
9 | instance-id: '${spring.application.name}:${random.value}'
10 |
--------------------------------------------------------------------------------
/configserver/src/main/resources/configs/application-docker.yaml:
--------------------------------------------------------------------------------
1 | spring:
2 | datasource:
3 | url: "jdbc:mysql://${db.name:db}:3306/packtdb"
4 | redis:
5 | host: "redis"
6 | rabbitmq:
7 | host: "rabbitmq"
8 | eureka:
9 | client:
10 | service-url:
11 | defaultZone: 'http://serviceregistry:8761/eureka/'
12 | management:
13 | server:
14 | port: 11111
15 | server:
16 | port: 8080
--------------------------------------------------------------------------------
/configserver/src/main/resources/configs/application.yaml:
--------------------------------------------------------------------------------
1 |
2 | management:
3 | endpoints:
4 | web:
5 | exposure:
6 | include: "*"
7 | eureka:
8 | instance:
9 | preferIpAddress: true
10 | client:
11 | service-url:
12 | defaultZone: 'http://localhost:8761/eureka/'
13 | spring:
14 | jackson:
15 | serialization:
16 | indent-output: true
17 | redis:
18 | host: localhost
19 | port: 6379
20 | session:
21 | store-type: redis
22 | rabbitmq:
23 | username: 'packt'
24 | password: 'publishing'
25 | sleuth.sampler.probability: 0.9
26 | cloud:
27 | config:
28 | #otherwise the clients would lead to a lot of logging and load on the configserver
29 | server.health.enabled: false
30 | #otherwise we can't override the port via command line args
31 | overrideSystemProperties: false
32 |
33 |
34 | server:
35 | use-forward-headers: true
36 |
--------------------------------------------------------------------------------
/configserver/src/test/java/com/packtpub/yummy/configserver/ConfigServerApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.configserver;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class ConfigServerApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/configserver/src/test/resources/application.properties:
--------------------------------------------------------------------------------
1 | management.server.port=0
--------------------------------------------------------------------------------
/hystrixdashboard/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 |
4 | ### STS ###
5 | .apt_generated
6 | .classpath
7 | .factorypath
8 | .project
9 | .settings
10 | .springBeans
11 | .sts4-cache
12 |
13 | ### IntelliJ IDEA ###
14 | .idea
15 | *.iws
16 | *.iml
17 | *.ipr
18 |
19 | ### NetBeans ###
20 | /nbproject/private/
21 | /build/
22 | /nbbuild/
23 | /dist/
24 | /nbdist/
25 | /.nb-gradle/
--------------------------------------------------------------------------------
/hystrixdashboard/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jre-alpine3.8
2 | RUN apk --update add curl
3 | HEALTHCHECK CMD curl -v --fail http://localhost:11111/actuator/info || exit 1
4 |
5 | COPY target/service.jar /usr/app/service.jar
6 | EXPOSE 8080 11111
7 | ENTRYPOINT java -Djava.net.preferIPv4Stack=true -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -jar /usr/app/service.jar --server.port=8080 --management.server.port=11111
--------------------------------------------------------------------------------
/hystrixdashboard/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM http://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
40 |
41 | @REM set %HOME% to equivalent of $HOME
42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
43 |
44 | @REM Execute a user defined script before this one
45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
49 | :skipRcPre
50 |
51 | @setlocal
52 |
53 | set ERROR_CODE=0
54 |
55 | @REM To isolate internal variables from possible post scripts, we use another setlocal
56 | @setlocal
57 |
58 | @REM ==== START VALIDATION ====
59 | if not "%JAVA_HOME%" == "" goto OkJHome
60 |
61 | echo.
62 | echo Error: JAVA_HOME not found in your environment. >&2
63 | echo Please set the JAVA_HOME variable in your environment to match the >&2
64 | echo location of your Java installation. >&2
65 | echo.
66 | goto error
67 |
68 | :OkJHome
69 | if exist "%JAVA_HOME%\bin\java.exe" goto init
70 |
71 | echo.
72 | echo Error: JAVA_HOME is set to an invalid directory. >&2
73 | echo JAVA_HOME = "%JAVA_HOME%" >&2
74 | echo Please set the JAVA_HOME variable in your environment to match the >&2
75 | echo location of your Java installation. >&2
76 | echo.
77 | goto error
78 |
79 | @REM ==== END VALIDATION ====
80 |
81 | :init
82 |
83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
84 | @REM Fallback to current working directory if not found.
85 |
86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
88 |
89 | set EXEC_DIR=%CD%
90 | set WDIR=%EXEC_DIR%
91 | :findBaseDir
92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
93 | cd ..
94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
95 | set WDIR=%CD%
96 | goto findBaseDir
97 |
98 | :baseDirFound
99 | set MAVEN_PROJECTBASEDIR=%WDIR%
100 | cd "%EXEC_DIR%"
101 | goto endDetectBaseDir
102 |
103 | :baseDirNotFound
104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
105 | cd "%EXEC_DIR%"
106 |
107 | :endDetectBaseDir
108 |
109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
110 |
111 | @setlocal EnableExtensions EnableDelayedExpansion
112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
114 |
115 | :endReadAdditionalConfig
116 |
117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
118 |
119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
121 |
122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
123 | if ERRORLEVEL 1 goto error
124 | goto end
125 |
126 | :error
127 | set ERROR_CODE=1
128 |
129 | :end
130 | @endlocal & set ERROR_CODE=%ERROR_CODE%
131 |
132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
136 | :skipRcPost
137 |
138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
140 |
141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
142 |
143 | exit /B %ERROR_CODE%
144 |
--------------------------------------------------------------------------------
/hystrixdashboard/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.packtpub.yummy
7 | hystrixdashboard
8 | 0.0.1-SNAPSHOT
9 | jar
10 |
11 | hystrixdashboard
12 | A dashing board
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-parent
17 | 2.0.3.RELEASE
18 |
19 |
20 |
21 |
22 | UTF-8
23 | UTF-8
24 | 1.8
25 | Finchley.RELEASE
26 |
27 |
28 |
29 |
30 | org.springframework.cloud
31 | spring-cloud-starter-netflix-hystrix-dashboard
32 |
33 |
34 | org.springframework.boot
35 | spring-boot-starter-actuator
36 |
37 |
38 | org.springframework.boot
39 | spring-boot-starter-test
40 | test
41 |
42 |
43 |
44 |
45 |
46 |
47 | org.springframework.cloud
48 | spring-cloud-dependencies
49 | ${spring-cloud.version}
50 | pom
51 | import
52 |
53 |
54 |
55 |
56 |
57 | service
58 |
59 |
60 | org.springframework.boot
61 | spring-boot-maven-plugin
62 |
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/hystrixdashboard/src/main/java/com/packtpub/yummy/hystrixdashboard/HystrixdashboardApplication.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.hystrixdashboard;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
6 |
7 | @SpringBootApplication
8 | @EnableHystrixDashboard
9 | public class HystrixdashboardApplication {
10 |
11 | public static void main(String[] args) {
12 | SpringApplication.run(HystrixdashboardApplication.class, args);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/hystrixdashboard/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.port=9998
--------------------------------------------------------------------------------
/hystrixdashboard/src/test/java/com/packtpub/yummy/hystrixdashboard/HystrixdashboardApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.hystrixdashboard;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class HystrixdashboardApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/ratings/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "src/main/resources/static/components/bower_components"
3 | }
--------------------------------------------------------------------------------
/ratings/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 |
4 | ### STS ###
5 | .apt_generated
6 | .classpath
7 | .factorypath
8 | .project
9 | .settings
10 | .springBeans
11 | .sts4-cache
12 |
13 | ### IntelliJ IDEA ###
14 | .idea
15 | *.iws
16 | *.iml
17 | *.ipr
18 |
19 | ### NetBeans ###
20 | /nbproject/private/
21 | /build/
22 | /nbbuild/
23 | /dist/
24 | /nbdist/
25 | /.nb-gradle/
--------------------------------------------------------------------------------
/ratings/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jre-alpine3.8
2 | RUN apk --update add curl
3 | HEALTHCHECK CMD curl -v --fail http://localhost:11111/actuator/info || exit 1
4 |
5 | COPY target/service.jar /usr/app/service.jar
6 | EXPOSE 8080 11111
7 | ENV DB_NAME="db"
8 | ENTRYPOINT java -Djava.net.preferIPv4Stack=true -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -jar /usr/app/service.jar --spring.profiles.active=$ENVIRONMENT,docker --db.name=$DB_NAME --spring.cloud.config.uri=http://configserver:8888
--------------------------------------------------------------------------------
/ratings/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ratings",
3 | "dependencies": {
4 | "polymer": "Polymer/polymer#^2.0.0",
5 | "bower": "*",
6 | "iron-ajax": "PolymerElements/iron-ajax#^2.1.3",
7 | "install": "^1.0.4",
8 | "iron-star-rating": "chadweimer/iron-star-rating#^2.0.1"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/ratings/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM http://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
40 |
41 | @REM set %HOME% to equivalent of $HOME
42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
43 |
44 | @REM Execute a user defined script before this one
45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
49 | :skipRcPre
50 |
51 | @setlocal
52 |
53 | set ERROR_CODE=0
54 |
55 | @REM To isolate internal variables from possible post scripts, we use another setlocal
56 | @setlocal
57 |
58 | @REM ==== START VALIDATION ====
59 | if not "%JAVA_HOME%" == "" goto OkJHome
60 |
61 | echo.
62 | echo Error: JAVA_HOME not found in your environment. >&2
63 | echo Please set the JAVA_HOME variable in your environment to match the >&2
64 | echo location of your Java installation. >&2
65 | echo.
66 | goto error
67 |
68 | :OkJHome
69 | if exist "%JAVA_HOME%\bin\java.exe" goto init
70 |
71 | echo.
72 | echo Error: JAVA_HOME is set to an invalid directory. >&2
73 | echo JAVA_HOME = "%JAVA_HOME%" >&2
74 | echo Please set the JAVA_HOME variable in your environment to match the >&2
75 | echo location of your Java installation. >&2
76 | echo.
77 | goto error
78 |
79 | @REM ==== END VALIDATION ====
80 |
81 | :init
82 |
83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
84 | @REM Fallback to current working directory if not found.
85 |
86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
88 |
89 | set EXEC_DIR=%CD%
90 | set WDIR=%EXEC_DIR%
91 | :findBaseDir
92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
93 | cd ..
94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
95 | set WDIR=%CD%
96 | goto findBaseDir
97 |
98 | :baseDirFound
99 | set MAVEN_PROJECTBASEDIR=%WDIR%
100 | cd "%EXEC_DIR%"
101 | goto endDetectBaseDir
102 |
103 | :baseDirNotFound
104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
105 | cd "%EXEC_DIR%"
106 |
107 | :endDetectBaseDir
108 |
109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
110 |
111 | @setlocal EnableExtensions EnableDelayedExpansion
112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
114 |
115 | :endReadAdditionalConfig
116 |
117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
118 |
119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
121 |
122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
123 | if ERRORLEVEL 1 goto error
124 | goto end
125 |
126 | :error
127 | set ERROR_CODE=1
128 |
129 | :end
130 | @endlocal & set ERROR_CODE=%ERROR_CODE%
131 |
132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
136 | :skipRcPost
137 |
138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
140 |
141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
142 |
143 | exit /B %ERROR_CODE%
144 |
--------------------------------------------------------------------------------
/ratings/src/main/java/com/packtpub/yummy/ratings/EventService.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.ratings;
2 |
3 | import com.packtpub.yummy.ratings.config.AmqpConfig;
4 | import lombok.AllArgsConstructor;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 | import lombok.extern.slf4j.Slf4j;
8 | import org.springframework.cloud.stream.annotation.StreamListener;
9 | import org.springframework.stereotype.Service;
10 |
11 | @Service
12 | @AllArgsConstructor
13 | @Slf4j
14 | public class EventService {
15 | private RatingRepository ratingRepository;
16 |
17 | @StreamListener(AmqpConfig.MessageSink.BOOKMARK_DELETIONS)
18 | public void processDelete(BookmarkDeleteEvent event) {
19 | log.info("Received Delete event for {}", event);
20 | ratingRepository.remove(event.getType(), event.getEntityId());
21 | }
22 |
23 | @Data
24 | @AllArgsConstructor
25 | @NoArgsConstructor
26 | public static class BookmarkDeleteEvent {
27 | String type, entityId;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/ratings/src/main/java/com/packtpub/yummy/ratings/RatingController.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.ratings;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.web.bind.annotation.*;
6 |
7 | import javax.validation.Valid;
8 |
9 | @RestController
10 | @RequestMapping("/votes/{type}/{entityId}")
11 | @AllArgsConstructor
12 | @Slf4j
13 | public class RatingController {
14 | private RatingRepository ratingRepository;
15 |
16 | @PostMapping
17 | public void addRating(@RequestBody @Valid RatingVote ratingVote,
18 | @PathVariable String type,
19 | @PathVariable String entityId) {
20 | log.info("Got rating {} for {} with entity {}", ratingVote, type, entityId);
21 | ratingRepository.persist(type, entityId, ratingVote.getRating());
22 | }
23 |
24 | @DeleteMapping
25 | public void deleteRating(@PathVariable String type,
26 | @PathVariable String entityId) {
27 | log.info("Remove rating for {} with entity {}", type, entityId);
28 | ratingRepository.remove(type, entityId);
29 | }
30 |
31 | @GetMapping
32 | public RatingResult getRating(@PathVariable String type,
33 | @PathVariable String entityId) {
34 | return ratingRepository.calculateRating(type, entityId);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/ratings/src/main/java/com/packtpub/yummy/ratings/RatingRepository.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.ratings;
2 |
3 | import lombok.AllArgsConstructor;
4 | import org.springframework.dao.EmptyResultDataAccessException;
5 | import org.springframework.jdbc.core.BeanPropertyRowMapper;
6 | import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
7 | import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
8 | import org.springframework.stereotype.Repository;
9 |
10 | import java.math.BigDecimal;
11 |
12 | @Repository
13 | @AllArgsConstructor
14 | public class RatingRepository {
15 | private NamedParameterJdbcTemplate jdbcTemplate;
16 |
17 |
18 | public void persist(String type, String entityId, BigDecimal rating) {
19 | jdbcTemplate.update(" insert into ratings (type, entity_id, rating)" +
20 | " values (:type, :entity_id, :rating)",
21 | new MapSqlParameterSource()
22 | .addValue("type", type)
23 | .addValue("entity_id", entityId)
24 | .addValue("rating", rating));
25 | }
26 |
27 | public RatingResult calculateRating(String type, String entityId) {
28 | try {
29 | return jdbcTemplate.queryForObject("select type, entity_id as entityId," +
30 | " avg(rating) as rating, count(*) as ratingCount" +
31 | " from ratings" +
32 | " where type=:type and entity_id=:entity_id" +
33 | " group by type, entity_id",
34 | new MapSqlParameterSource()
35 | .addValue("type", type)
36 | .addValue("entity_id", entityId),
37 | new BeanPropertyRowMapper<>(RatingResult.class));
38 | } catch (EmptyResultDataAccessException ex) {
39 | return new RatingResult(type, entityId, BigDecimal.ZERO, 0);
40 | }
41 | }
42 |
43 | public void remove(String type, String entityId) {
44 | jdbcTemplate.update("delete from ratings" +
45 | " where type=:type and entity_id=:entity_id",
46 | new MapSqlParameterSource()
47 | .addValue("type", type)
48 | .addValue("entity_id", entityId));
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/ratings/src/main/java/com/packtpub/yummy/ratings/RatingResult.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.ratings;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 |
7 | import java.math.BigDecimal;
8 |
9 | @Data
10 | @AllArgsConstructor
11 | @NoArgsConstructor
12 | public class RatingResult {
13 | private String type, entityId;
14 | private BigDecimal rating;
15 | private int ratingCount;
16 | }
17 |
--------------------------------------------------------------------------------
/ratings/src/main/java/com/packtpub/yummy/ratings/RatingVote.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.ratings;
2 |
3 | import lombok.Data;
4 |
5 | import javax.validation.constraints.DecimalMax;
6 | import javax.validation.constraints.DecimalMin;
7 | import java.math.BigDecimal;
8 |
9 | @Data
10 | public class RatingVote {
11 | @DecimalMin("0.5") @DecimalMax("5")
12 | BigDecimal rating;
13 | }
14 |
--------------------------------------------------------------------------------
/ratings/src/main/java/com/packtpub/yummy/ratings/RatingsApplication.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.ratings;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class RatingsApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(RatingsApplication.class, args);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/ratings/src/main/java/com/packtpub/yummy/ratings/config/AmqpConfig.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.ratings.config;
2 |
3 | import org.springframework.cloud.stream.annotation.EnableBinding;
4 | import org.springframework.cloud.stream.annotation.Input;
5 | import org.springframework.context.annotation.Configuration;
6 | import org.springframework.messaging.SubscribableChannel;
7 |
8 | @Configuration
9 | @EnableBinding(AmqpConfig.MessageSink.class)
10 | public class AmqpConfig {
11 | public interface MessageSink {
12 | String BOOKMARK_DELETIONS = "bookmarkDeletions";
13 |
14 | @Input
15 | SubscribableChannel bookmarkDeletions();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/ratings/src/main/java/com/packtpub/yummy/ratings/config/ErrorAdvice.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.ratings.config;
2 |
3 | import lombok.Getter;
4 | import lombok.ToString;
5 | import org.springframework.dao.IncorrectResultSizeDataAccessException;
6 | import org.springframework.dao.OptimisticLockingFailureException;
7 | import org.springframework.http.HttpStatus;
8 | import org.springframework.validation.FieldError;
9 | import org.springframework.validation.ObjectError;
10 | import org.springframework.web.bind.MethodArgumentNotValidException;
11 | import org.springframework.web.bind.annotation.ControllerAdvice;
12 | import org.springframework.web.bind.annotation.ExceptionHandler;
13 | import org.springframework.web.bind.annotation.ResponseBody;
14 | import org.springframework.web.bind.annotation.ResponseStatus;
15 |
16 | import java.util.List;
17 | import java.util.stream.Collectors;
18 |
19 | @ControllerAdvice
20 | public class ErrorAdvice {
21 |
22 | @ExceptionHandler(IncorrectResultSizeDataAccessException.class)
23 | @ResponseStatus(HttpStatus.NOT_FOUND)
24 | public @ResponseBody
25 | String elementNotFound(IncorrectResultSizeDataAccessException e) {
26 | return "Could not find element! " + e.getMessage();
27 | }
28 |
29 | @ExceptionHandler(OptimisticLockingFailureException.class)
30 | @ResponseStatus(HttpStatus.CONFLICT)
31 | public @ResponseBody
32 | String elementNotFound(OptimisticLockingFailureException e) {
33 | return "Conflict! " + e.getMessage();
34 | }
35 |
36 | @ExceptionHandler(MethodArgumentNotValidException.class)
37 | @ResponseStatus(HttpStatus.BAD_REQUEST)
38 | public @ResponseBody
39 | List badRequest(MethodArgumentNotValidException e) {
40 | return e.getBindingResult().getAllErrors().stream()
41 | .map(err -> new ErrorMessage(err))
42 | .collect(Collectors.toList());
43 |
44 | }
45 |
46 | @Getter
47 | @ToString
48 | public static class ErrorMessage {
49 | String message, code, field, objectName;
50 |
51 | public ErrorMessage(ObjectError objectError) {
52 | message = objectError.getDefaultMessage();
53 | code = objectError.getCode();
54 | objectName = objectError.getObjectName();
55 | if (objectError instanceof FieldError) {
56 | field = ((FieldError) objectError).getField();
57 | }
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/ratings/src/main/java/com/packtpub/yummy/ratings/config/SecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.ratings.config;
2 |
3 | import lombok.AllArgsConstructor;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
7 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
8 |
9 | @Configuration
10 | @AllArgsConstructor
11 | @EnableGlobalMethodSecurity(prePostEnabled = true)
12 | public class SecurityConfig extends WebSecurityConfigurerAdapter {
13 |
14 | @Override
15 | protected void configure(HttpSecurity http) throws Exception {
16 | http
17 | .authorizeRequests()
18 | .antMatchers("/actuator/**").permitAll()
19 | .anyRequest().authenticated()
20 | .and().csrf().disable();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/ratings/src/main/java/com/packtpub/yummy/ratings/config/WebConfig.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.ratings.config;
2 |
3 | import org.springframework.context.annotation.Configuration;
4 | import org.springframework.http.MediaType;
5 | import org.springframework.http.converter.HttpMessageConverter;
6 | import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
7 | import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
8 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
9 |
10 | import java.util.List;
11 |
12 | @Configuration
13 | public class WebConfig implements WebMvcConfigurer {
14 |
15 | @Override
16 | public void extendMessageConverters(List> converters) {
17 | converters.removeIf(c -> c instanceof Jaxb2RootElementHttpMessageConverter);
18 | }
19 |
20 | @Override
21 | public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
22 | configurer.defaultContentType(MediaType.APPLICATION_JSON_UTF8);
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/ratings/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 | spring:
2 | datasource:
3 | url: "jdbc:mysql://localhost:3308/packtdb"
4 | username: "packt"
5 | password: "superSecret"
6 | cloud:
7 | stream:
8 | bindings:
9 | bookmarkDeletions:
10 | group: ratings
11 | server.port: 9095
12 |
--------------------------------------------------------------------------------
/ratings/src/main/resources/bootstrap.yaml:
--------------------------------------------------------------------------------
1 | spring:
2 | application.name: 'ratings'
3 | cloud:
4 | config:
5 | failFast: true
6 | retry:
7 | max-attempts: 60
8 | discovery:
9 | enabled: false
10 | uri: 'http://localhost:8888'
11 |
12 |
--------------------------------------------------------------------------------
/ratings/src/main/resources/db/migration/V1.1__initial.sql:
--------------------------------------------------------------------------------
1 | create table ratings (
2 | type varchar(255) not null,
3 | entity_id varchar(255) not null,
4 | rating double not null,
5 | created_on timestamp default now() not null
6 | );
7 | create index ratings_idx
8 | on ratings (type, entity_id);
--------------------------------------------------------------------------------
/ratings/src/main/resources/static/components/rating-ctrl.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
10 |
12 |
13 |
14 |
54 |
--------------------------------------------------------------------------------
/ratings/src/test/java/com/packtpub/yummy/ratings/MessagingTests.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.ratings;
2 |
3 | import com.fasterxml.jackson.core.JsonProcessingException;
4 | import com.fasterxml.jackson.databind.ObjectMapper;
5 | import com.packtpub.yummy.ratings.config.AmqpConfig;
6 | import org.junit.Test;
7 | import org.junit.runner.RunWith;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.boot.test.context.SpringBootTest;
10 | import org.springframework.boot.test.mock.mockito.MockBean;
11 | import org.springframework.messaging.support.MessageBuilder;
12 | import org.springframework.test.context.junit4.SpringRunner;
13 |
14 | import static org.mockito.Mockito.verify;
15 |
16 | @RunWith(SpringRunner.class)
17 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
18 | public class MessagingTests {
19 | @MockBean
20 | RatingRepository ratingRepository;
21 | @Autowired
22 | AmqpConfig.MessageSink sink;
23 | @Autowired
24 | ObjectMapper mapper;
25 |
26 | @Test
27 | public void messageIsProcessed() throws JsonProcessingException {
28 | String payload = mapper.writer().writeValueAsString(
29 | new EventService.BookmarkDeleteEvent("1", "2")
30 | );
31 |
32 | sink.bookmarkDeletions().send(MessageBuilder.withPayload(payload).build());
33 |
34 | verify(ratingRepository).remove("1", "2");
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/ratings/src/test/java/com/packtpub/yummy/ratings/RatingsApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.ratings;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class RatingsApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/ratings/src/test/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.profiles.active=test
2 | spring.data.redis.repositories.enabled=false
3 | spring.session.store-type=none
4 |
5 |
--------------------------------------------------------------------------------
/ratings/src/test/resources/bootstrap.yaml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | config:
4 | enabled: false
5 |
--------------------------------------------------------------------------------
/reverseproxy/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jre-alpine3.8
2 | RUN apk --update add curl
3 | HEALTHCHECK CMD curl -v --fail http://localhost:11111/actuator/info || exit 1
4 |
5 | COPY target/service.jar /usr/app/service.jar
6 | EXPOSE 8080 11111
7 | ENV ENVIRONMENT="local"
8 | ENTRYPOINT java -Djava.net.preferIPv4Stack=true -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -jar /usr/app/service.jar --spring.profiles.active=$ENVIRONMENT,docker --spring.cloud.config.uri=http://configserver:8888
--------------------------------------------------------------------------------
/reverseproxy/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM http://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
40 |
41 | @REM set %HOME% to equivalent of $HOME
42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
43 |
44 | @REM Execute a user defined script before this one
45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
49 | :skipRcPre
50 |
51 | @setlocal
52 |
53 | set ERROR_CODE=0
54 |
55 | @REM To isolate internal variables from possible post scripts, we use another setlocal
56 | @setlocal
57 |
58 | @REM ==== START VALIDATION ====
59 | if not "%JAVA_HOME%" == "" goto OkJHome
60 |
61 | echo.
62 | echo Error: JAVA_HOME not found in your environment. >&2
63 | echo Please set the JAVA_HOME variable in your environment to match the >&2
64 | echo location of your Java installation. >&2
65 | echo.
66 | goto error
67 |
68 | :OkJHome
69 | if exist "%JAVA_HOME%\bin\java.exe" goto init
70 |
71 | echo.
72 | echo Error: JAVA_HOME is set to an invalid directory. >&2
73 | echo JAVA_HOME = "%JAVA_HOME%" >&2
74 | echo Please set the JAVA_HOME variable in your environment to match the >&2
75 | echo location of your Java installation. >&2
76 | echo.
77 | goto error
78 |
79 | @REM ==== END VALIDATION ====
80 |
81 | :init
82 |
83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
84 | @REM Fallback to current working directory if not found.
85 |
86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
88 |
89 | set EXEC_DIR=%CD%
90 | set WDIR=%EXEC_DIR%
91 | :findBaseDir
92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
93 | cd ..
94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
95 | set WDIR=%CD%
96 | goto findBaseDir
97 |
98 | :baseDirFound
99 | set MAVEN_PROJECTBASEDIR=%WDIR%
100 | cd "%EXEC_DIR%"
101 | goto endDetectBaseDir
102 |
103 | :baseDirNotFound
104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
105 | cd "%EXEC_DIR%"
106 |
107 | :endDetectBaseDir
108 |
109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
110 |
111 | @setlocal EnableExtensions EnableDelayedExpansion
112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
114 |
115 | :endReadAdditionalConfig
116 |
117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
118 |
119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
121 |
122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
123 | if ERRORLEVEL 1 goto error
124 | goto end
125 |
126 | :error
127 | set ERROR_CODE=1
128 |
129 | :end
130 | @endlocal & set ERROR_CODE=%ERROR_CODE%
131 |
132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
136 | :skipRcPost
137 |
138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
140 |
141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
142 |
143 | exit /B %ERROR_CODE%
144 |
--------------------------------------------------------------------------------
/reverseproxy/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.packtpub.yummy
7 | reverseproxy
8 | 0.0.1-SNAPSHOT
9 | jar
10 |
11 | ReverseProxy
12 | Reversing your proxy
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-parent
17 | 2.0.3.RELEASE
18 |
19 |
20 |
21 |
22 | UTF-8
23 | UTF-8
24 | 1.8
25 | Finchley.RELEASE
26 |
27 |
28 |
29 |
30 | org.springframework.cloud
31 | spring-cloud-starter-netflix-zuul
32 |
33 |
34 | org.projectlombok
35 | lombok
36 |
37 |
38 | org.springframework.cloud
39 | spring-cloud-starter-netflix-eureka-client
40 |
41 |
42 | org.springframework.cloud
43 | spring-cloud-config-client
44 |
45 |
46 | org.springframework.cloud
47 | spring-cloud-starter-bus-amqp
48 |
49 |
50 | org.springframework.cloud
51 | spring-cloud-netflix-hystrix-stream
52 |
53 |
54 | org.springframework.cloud
55 | spring-cloud-starter-zipkin
56 |
57 |
58 |
59 | org.springframework.boot
60 | spring-boot-starter-test
61 | test
62 |
63 |
64 |
65 |
66 |
67 |
68 | org.springframework.cloud
69 | spring-cloud-dependencies
70 | ${spring-cloud.version}
71 | pom
72 | import
73 |
74 |
75 |
76 |
77 |
78 | service
79 |
80 |
81 | org.springframework.boot
82 | spring-boot-maven-plugin
83 |
84 | true
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 | spring-milestones
93 | Spring milestones
94 | https://repo.spring.io/libs-milestones
95 |
96 | false
97 |
98 |
99 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/reverseproxy/src/main/java/com/packtpub/yummy/reverseproxy/CorrelationIdZuulFilter.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.reverseproxy;
2 |
3 | import com.netflix.zuul.ZuulFilter;
4 | import com.netflix.zuul.context.RequestContext;
5 | import com.netflix.zuul.exception.ZuulException;
6 | import org.slf4j.MDC;
7 | import org.springframework.stereotype.Component;
8 |
9 | import java.util.UUID;
10 |
11 | import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
12 | import static org.springframework.integration.IntegrationMessageHeaderAccessor.CORRELATION_ID;
13 |
14 | @Component
15 | public class CorrelationIdZuulFilter extends ZuulFilter {
16 | @Override
17 | public String filterType() {
18 | return PRE_TYPE;
19 | }
20 |
21 | @Override
22 | public int filterOrder() {
23 | return 0;
24 | }
25 |
26 | @Override
27 | public boolean shouldFilter() {
28 | return true;
29 | }
30 |
31 | @Override
32 | public Object run() throws ZuulException {
33 | String id = UUID.randomUUID().toString();
34 | RequestContext.getCurrentContext().addZuulRequestHeader(CORRELATION_ID, id);
35 | MDC.put(CORRELATION_ID, id);
36 | return null;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/reverseproxy/src/main/java/com/packtpub/yummy/reverseproxy/ErrorPageController.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.reverseproxy;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import org.springframework.boot.autoconfigure.web.servlet.error.AbstractErrorController;
6 | import org.springframework.boot.autoconfigure.web.servlet.error.ErrorViewResolver;
7 | import org.springframework.boot.web.servlet.error.ErrorAttributes;
8 | import org.springframework.stereotype.Controller;
9 | import org.springframework.web.bind.annotation.RequestMapping;
10 |
11 | import javax.servlet.http.HttpServletRequest;
12 | import javax.servlet.http.HttpServletResponse;
13 | import java.io.IOException;
14 | import java.util.List;
15 | import java.util.Map;
16 |
17 | @Controller
18 | @RequestMapping
19 | public class ErrorPageController extends AbstractErrorController {
20 | private static final Logger LOG = LoggerFactory.getLogger("error");
21 | private static final String PATH = "/error";
22 |
23 | public ErrorPageController(ErrorAttributes errorAttributes, List errorViewResolvers) {
24 | super(errorAttributes, errorViewResolvers);
25 | }
26 |
27 | @RequestMapping(value = PATH)
28 | public void error(HttpServletRequest request, HttpServletResponse response) throws IOException {
29 | Map errorAttributes = this.getErrorAttributes(request, false);
30 | LOG.info("ERROR-PAGE:{}, IP:{}:{}, MESSAGE: {}, QUERY:{}", response.getStatus(), request.getRemoteAddr(), request.getRemotePort(), errorAttributes.get("message"), request.getAttribute("javax.servlet.error.request_uri"));
31 | response.sendError(501, String.valueOf(errorAttributes.get("message")));
32 | }
33 |
34 | @Override
35 | public String getErrorPath() {
36 | return PATH;
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/reverseproxy/src/main/java/com/packtpub/yummy/reverseproxy/ReverseProxyApplication.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.reverseproxy;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
6 |
7 | @SpringBootApplication
8 | @EnableZuulProxy
9 | public class ReverseProxyApplication {
10 | public static void main(String[] args) {
11 | SpringApplication.run(ReverseProxyApplication.class, args);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/reverseproxy/src/main/java/com/packtpub/yummy/reverseproxy/ZuulLoginFilter.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.reverseproxy;
2 |
3 | import com.netflix.zuul.ZuulFilter;
4 | import com.netflix.zuul.context.RequestContext;
5 | import com.netflix.zuul.exception.ZuulException;
6 | import org.springframework.stereotype.Component;
7 |
8 | import java.io.IOException;
9 |
10 | import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.POST_TYPE;
11 |
12 | @Component
13 | public class ZuulLoginFilter extends ZuulFilter {
14 | @Override
15 | public String filterType() {
16 | return POST_TYPE;
17 | }
18 |
19 | @Override
20 | public int filterOrder() {
21 | return 0;
22 | }
23 |
24 | @Override
25 | public boolean shouldFilter() {
26 | int statusCode = RequestContext.getCurrentContext().getResponseStatusCode();
27 | return statusCode == 401 || statusCode == 403;
28 | }
29 | @Override
30 | public Object run() throws ZuulException {
31 | try {
32 | RequestContext.getCurrentContext()
33 | .getResponse()
34 | .sendRedirect("/user/login");
35 | } catch (IOException e) {
36 | e.printStackTrace();
37 | }
38 | return null;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/reverseproxy/src/main/resources/META-INF/spring.factories:
--------------------------------------------------------------------------------
1 | org.springframework.context.ApplicationListener=\
2 | org.springframework.boot.context.ApplicationPidFileWriter
--------------------------------------------------------------------------------
/reverseproxy/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 | zuul:
2 | ignored-services: '*'
3 | routes:
4 | bookmarks: '/**'
5 | users: '/user/**'
6 | ratings: '/ratings/**'
7 | sensitive-headers:
8 | add-host-header: true
9 |
10 |
--------------------------------------------------------------------------------
/reverseproxy/src/main/resources/bootstrap.yaml:
--------------------------------------------------------------------------------
1 | spring:
2 | application.name: 'reverseproxy'
3 | cloud:
4 | config:
5 | failFast: true
6 | retry:
7 | max-attempts: 60
8 | discovery:
9 | enabled: false
10 | uri: 'http://localhost:8888'
11 |
12 |
--------------------------------------------------------------------------------
/reverseproxy/src/test/java/com/packtpub/yummy/reverseproxy/ReverseProxyApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.reverseproxy;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class ReverseProxyApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/reverseproxy/src/test/resources/bootstrap.yaml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | config:
4 | enabled: false
5 |
--------------------------------------------------------------------------------
/serviceregistry/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jre-alpine3.8
2 | RUN apk --update add curl
3 | HEALTHCHECK CMD curl -v --fail http://localhost:11111/actuator/info || exit 1
4 |
5 | COPY target/service.jar /usr/app/service.jar
6 | EXPOSE 8761 11111
7 | ENV ENVIRONMENT="local"
8 | ENTRYPOINT java -Djava.net.preferIPv4Stack=true -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -jar /usr/app/service.jar --server.port=8761 --management.server.port=11111 --spring.profiles.active=$ENVIRONMENT,docker --spring.cloud.config.uri=http://configserver:8888
--------------------------------------------------------------------------------
/serviceregistry/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM http://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
40 |
41 | @REM set %HOME% to equivalent of $HOME
42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
43 |
44 | @REM Execute a user defined script before this one
45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
49 | :skipRcPre
50 |
51 | @setlocal
52 |
53 | set ERROR_CODE=0
54 |
55 | @REM To isolate internal variables from possible post scripts, we use another setlocal
56 | @setlocal
57 |
58 | @REM ==== START VALIDATION ====
59 | if not "%JAVA_HOME%" == "" goto OkJHome
60 |
61 | echo.
62 | echo Error: JAVA_HOME not found in your environment. >&2
63 | echo Please set the JAVA_HOME variable in your environment to match the >&2
64 | echo location of your Java installation. >&2
65 | echo.
66 | goto error
67 |
68 | :OkJHome
69 | if exist "%JAVA_HOME%\bin\java.exe" goto init
70 |
71 | echo.
72 | echo Error: JAVA_HOME is set to an invalid directory. >&2
73 | echo JAVA_HOME = "%JAVA_HOME%" >&2
74 | echo Please set the JAVA_HOME variable in your environment to match the >&2
75 | echo location of your Java installation. >&2
76 | echo.
77 | goto error
78 |
79 | @REM ==== END VALIDATION ====
80 |
81 | :init
82 |
83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
84 | @REM Fallback to current working directory if not found.
85 |
86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
88 |
89 | set EXEC_DIR=%CD%
90 | set WDIR=%EXEC_DIR%
91 | :findBaseDir
92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
93 | cd ..
94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
95 | set WDIR=%CD%
96 | goto findBaseDir
97 |
98 | :baseDirFound
99 | set MAVEN_PROJECTBASEDIR=%WDIR%
100 | cd "%EXEC_DIR%"
101 | goto endDetectBaseDir
102 |
103 | :baseDirNotFound
104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
105 | cd "%EXEC_DIR%"
106 |
107 | :endDetectBaseDir
108 |
109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
110 |
111 | @setlocal EnableExtensions EnableDelayedExpansion
112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
114 |
115 | :endReadAdditionalConfig
116 |
117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
118 |
119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
121 |
122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
123 | if ERRORLEVEL 1 goto error
124 | goto end
125 |
126 | :error
127 | set ERROR_CODE=1
128 |
129 | :end
130 | @endlocal & set ERROR_CODE=%ERROR_CODE%
131 |
132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
136 | :skipRcPost
137 |
138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
140 |
141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
142 |
143 | exit /B %ERROR_CODE%
144 |
--------------------------------------------------------------------------------
/serviceregistry/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.packtpub.yummy
7 | serviceregistry
8 | 0.0.1-SNAPSHOT
9 | jar
10 |
11 | ServiceRegistry
12 | Registering your services
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-parent
17 | 2.0.3.RELEASE
18 |
19 |
20 |
21 |
22 | UTF-8
23 | UTF-8
24 | 1.8
25 | Finchley.RELEASE
26 |
27 |
28 |
29 |
30 | org.springframework.cloud
31 | spring-cloud-starter-netflix-eureka-server
32 |
33 |
34 | org.springframework.cloud
35 | spring-cloud-starter-bus-amqp
36 |
37 |
38 | org.springframework.cloud
39 | spring-cloud-config-client
40 |
41 |
42 | org.springframework.boot
43 | spring-boot-starter-actuator
44 |
45 |
46 | org.springframework.boot
47 | spring-boot-starter-test
48 | test
49 |
50 |
51 |
52 |
53 |
54 |
55 | org.springframework.cloud
56 | spring-cloud-dependencies
57 | ${spring-cloud.version}
58 | pom
59 | import
60 |
61 |
62 |
63 |
64 |
65 | service
66 |
67 |
68 | org.springframework.boot
69 | spring-boot-maven-plugin
70 |
71 | true
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | spring-milestones
80 | Spring milestones
81 | https://repo.spring.io/libs-milestones
82 |
83 | false
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/serviceregistry/src/main/java/com/packtpub/yummy/serviceregistry/ServiceRegistryApplication.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.serviceregistry;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
6 |
7 | @SpringBootApplication @EnableEurekaServer
8 | public class ServiceRegistryApplication {
9 |
10 | public static void main(String[] args) {
11 | SpringApplication.run(ServiceRegistryApplication.class, args);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/serviceregistry/src/main/resources/META-INF/spring.factories:
--------------------------------------------------------------------------------
1 | org.springframework.context.ApplicationListener=\
2 | org.springframework.boot.context.ApplicationPidFileWriter
--------------------------------------------------------------------------------
/serviceregistry/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 |
2 |
3 | server.port: 8761
4 |
5 | eureka:
6 | client:
7 | register-with-eureka: false
8 | fetch-registry: false
9 | server:
10 | wait-time-in-ms-when-sync-empty: 0
11 | enable-self-preservation: false
--------------------------------------------------------------------------------
/serviceregistry/src/main/resources/bootstrap.yaml:
--------------------------------------------------------------------------------
1 | spring:
2 | application.name: 'serviceregistry'
3 | cloud:
4 | config:
5 | failFast: true
6 | retry:
7 | max-attempts: 60
8 | discovery:
9 | enabled: false
10 | uri: 'http://localhost:8888'
11 |
12 |
--------------------------------------------------------------------------------
/serviceregistry/src/test/java/com/packtpub/yummy/serviceregistry/ServiceRegistryApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.serviceregistry;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class ServiceRegistryApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/serviceregistry/src/test/resources/bootstrap.yaml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | config:
4 | enabled: false
5 |
--------------------------------------------------------------------------------
/setup/buildAll.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | unamestr=`uname`
4 |
5 | ##
6 | ## This script builds all maven projects located in ..
7 | ##
8 |
9 | if [[ "$unamestr" == 'Linux' ]]; then
10 | BASEDIR=`dirname $0`
11 | elif [[ "$unamestr" == 'Darwin' ]]; then
12 | BASEDIR=`dirname $(greadlink -f $0)`
13 | fi
14 | cd $BASEDIR
15 |
16 | echo Searching for pom files in `$BASEDIR/..`
17 | find .. -name pom.xml -exec ./helper_buildIn.sh {} $BASEDIR/builderrors.log \;
18 |
19 | echo "Done compiling!"
--------------------------------------------------------------------------------
/setup/dc-common.yaml:
--------------------------------------------------------------------------------
1 | version: '2'
2 |
3 | services:
4 | common_java:
5 | restart: on-failure
6 | volumes:
7 | - "/dev/urandom:/dev/random"
8 | mem_limit: 367001600
9 |
--------------------------------------------------------------------------------
/setup/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | version: '2'
2 |
3 | services:
4 | rabbitmq:
5 | image: "rabbitmq:3.7-management"
6 | restart: on-failure
7 | ports:
8 | - "5672:5672"
9 | - "15672:15672"
10 | environment:
11 | RABBITMQ_DEFAULT_USER: "packt"
12 | RABBITMQ_DEFAULT_PASS: "publishing"
13 | volumes:
14 | - ./rabbitmq:/var/lib/rabbitmq
15 |
16 | zipkin:
17 | image: openzipkin/zipkin
18 | ports:
19 | - "9410:9410"
20 | - "9411:9411"
21 | depends_on:
22 | - rabbitmq
23 | environment:
24 | RABBIT_URI: "amqp://packt:publishing@rabbitmq:5672"
25 | extends:
26 | file: ./dc-common.yaml
27 | service: common_java
28 |
29 | redis:
30 | image: "redis:alpine"
31 | restart: on-failure
32 | ports:
33 | - "6379:6379"
34 |
35 | redisCommander:
36 | image: tenstartups/redis-commander
37 | command: --redis-host redis
38 | restart: on-failure
39 | depends_on:
40 | - redis
41 | ports:
42 | - "8081:8081"
43 |
44 | mysqlbm:
45 | image: mysql:8.0
46 | restart: on-failure
47 | security_opt:
48 | - seccomp=unconfined
49 | ports:
50 | - "3306:3306"
51 | environment:
52 | MYSQL_DATABASE: "packtdb"
53 | MYSQL_USER: "packt"
54 | MYSQL_PASSWORD: "superSecret"
55 | MYSQL_ROOT_HOST: "%"
56 | MYSQL_ROOT_PASSWORD: "superDuperSecret"
57 |
58 | mysqlus:
59 | image: mysql:8.0
60 | restart: on-failure
61 | security_opt:
62 | - seccomp=unconfined
63 | ports:
64 | - "3307:3306"
65 | environment:
66 | MYSQL_DATABASE: "packtdb"
67 | MYSQL_USER: "packt"
68 | MYSQL_PASSWORD: "superSecret"
69 | MYSQL_ROOT_HOST: "%"
70 | MYSQL_ROOT_PASSWORD: "superDuperSecret"
71 |
72 | mysqlra:
73 | image: mysql:8.0
74 | restart: on-failure
75 | security_opt:
76 | - seccomp=unconfined
77 | ports:
78 | - "3308:3306"
79 | environment:
80 | MYSQL_DATABASE: "packtdb"
81 | MYSQL_USER: "packt"
82 | MYSQL_PASSWORD: "superSecret"
83 | MYSQL_ROOT_HOST: "%"
84 | MYSQL_ROOT_PASSWORD: "superDuperSecret"
85 |
86 | ### services
87 | admin:
88 | build: ../admin
89 | image: localhost:5000/admin
90 | ports:
91 | - "6060:8080"
92 | depends_on:
93 | - configserver
94 | - rabbitmq
95 | extends:
96 | file: ./dc-common.yaml
97 | service: common_java
98 |
99 | bookmarks_service:
100 | build: ../bookmarks
101 | image: localhost:5000/bookmarks
102 | depends_on:
103 | - configserver
104 | - mysqlbm
105 | - redis
106 | - serviceregistry
107 | - rabbitmq
108 | links:
109 | - "mysqlbm:db"
110 | extends:
111 | file: ./dc-common.yaml
112 | service: common_java
113 |
114 | configserver:
115 | build: ../configserver
116 | image: localhost:5000/configserver
117 | extends:
118 | file: ./dc-common.yaml
119 | service: common_java
120 |
121 | hystrixdashboard:
122 | build: ../hystrixdashboard
123 | image: localhost:5000/hystrixdashboard
124 | ports:
125 | - "9998:8080"
126 | depends_on:
127 | - configserver
128 | - rabbitmq
129 | - turbine
130 | extends:
131 | file: ./dc-common.yaml
132 | service: common_java
133 |
134 | ratings_service:
135 | build: ../ratings
136 | image: localhost:5000/ratings
137 | depends_on:
138 | - configserver
139 | - mysqlra
140 | - redis
141 | - rabbitmq
142 | links:
143 | - "mysqlra:db"
144 | extends:
145 | file: ./dc-common.yaml
146 | service: common_java
147 |
148 | reverseproxy:
149 | build: ../reverseproxy
150 | image: localhost:5000/reverseproxy
151 | ports:
152 | - "8080:8080"
153 | depends_on:
154 | - configserver
155 | - rabbitmq
156 | - redis
157 | extends:
158 | file: ./dc-common.yaml
159 | service: common_java
160 |
161 | serviceregistry:
162 | build: ../serviceregistry
163 | image: localhost:5000/serviceregistry
164 | restart: on-failure
165 | ports:
166 | - "8761:8761"
167 | depends_on:
168 | - configserver
169 | - rabbitmq
170 | extends:
171 | file: ./dc-common.yaml
172 | service: common_java
173 |
174 | turbine:
175 | build: ../turbine
176 | image: localhost:5000/turbine
177 | depends_on:
178 | - configserver
179 | - rabbitmq
180 | - serviceregistry
181 | extends:
182 | file: ./dc-common.yaml
183 | service: common_java
184 |
185 | users_service:
186 | build: ../users
187 | image: localhost:5000/users
188 | depends_on:
189 | - configserver
190 | - mysqlus
191 | - redis
192 | - rabbitmq
193 | - serviceregistry
194 | links:
195 | - "mysqlus:db"
196 | extends:
197 | file: ./dc-common.yaml
198 | service: common_java
199 |
--------------------------------------------------------------------------------
/setup/helper_buildIn.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##
4 | ## internal helper script to build the maven stuff
5 | ##
6 |
7 | DIR=`dirname $1`
8 | BUILD_ERROR_LOG=${2=builderrors.log}
9 |
10 | cd $DIR
11 |
12 | mvn clean install -DskipTests -DskipITs
13 |
14 | EXIT=$?
15 | if [ $EXIT -eq 0 ]
16 | then
17 | echo "Success!"
18 | else
19 | echo "Logging error for $DIR" >&2
20 | #logging errors is necessary because this is called in a find -exec which doesn't stop on errors
21 | #and your shell history is most likely not big enough, so you can see where to look for errors
22 | echo "`date +%H:%M:%S` : Error while building $DIR" >> $BUILD_ERROR_LOG
23 | fi
24 | exit $EXIT
25 |
--------------------------------------------------------------------------------
/setup/kubernetes/admin-pod.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | labels:
5 | app: admin
6 | name: admin
7 | spec:
8 | containers:
9 | - image: localhost:5000/admin
10 | name: admin
11 | imagePullPolicy: Always
12 | env:
13 | - name: ENVIRONMENT
14 | value: 'kubernetes'
15 | ports:
16 | - containerPort: 8080
17 | - containerPort: 11111
18 | resources:
19 | limits:
20 | memory: 450Mi
21 | restartPolicy: OnFailure
22 | ---
23 | kind: Service
24 | apiVersion: v1
25 | metadata:
26 | name: admin-service
27 | spec:
28 | selector:
29 | app: admin
30 | ports:
31 | - protocol: TCP
32 | port: 8080
33 | name: api
34 | - protocol: TCP
35 | port: 11111
36 | name: actuator
37 |
--------------------------------------------------------------------------------
/setup/kubernetes/bookmarks-service-pod.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | labels:
5 | app: bookmarks
6 | name: bookmarks
7 | spec:
8 | containers:
9 | - image: localhost:5000/bookmarks
10 | name: bookmarks
11 | imagePullPolicy: Always
12 | env:
13 | - name: ENVIRONMENT
14 | value: 'kubernetes'
15 | - name: DB_NAME
16 | value: 'mysqlbm'
17 | ports:
18 | - containerPort: 8080
19 | - containerPort: 11111
20 | resources:
21 | limits:
22 | memory: 550Mi
23 | restartPolicy: OnFailure
24 | ---
25 | kind: Service
26 | apiVersion: v1
27 | metadata:
28 | name: bookmarks-service
29 | spec:
30 | selector:
31 | app: bookmarks
32 | ports:
33 | - protocol: TCP
34 | port: 8080
35 | name: api
36 | - protocol: TCP
37 | port: 11111
38 | name: actuator
39 |
--------------------------------------------------------------------------------
/setup/kubernetes/configserver-pod.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | labels:
5 | app: configserver
6 | name: configserver
7 | spec:
8 | containers:
9 | - image: localhost:5000/configserver
10 | name: configserver
11 | ports:
12 | - containerPort: 8888
13 | - containerPort: 11111
14 | imagePullPolicy: Always
15 | resources:
16 | limits:
17 | memory: 350Mi
18 | restartPolicy: OnFailure
19 | ---
20 | kind: Service
21 | apiVersion: v1
22 | metadata:
23 | name: configserver
24 | spec:
25 | selector:
26 | app: configserver
27 | ports:
28 | - protocol: TCP
29 | port: 8888
30 | name: api
31 | - protocol: TCP
32 | port: 11111
33 | name: actuator
--------------------------------------------------------------------------------
/setup/kubernetes/hystrixdashboard-pod.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | labels:
5 | app: hystrixdashboard
6 | name: hystrixdashboard
7 | spec:
8 | containers:
9 | - image: localhost:5000/hystrixdashboard
10 | name: hystrixdashboard
11 | imagePullPolicy: Always
12 | env:
13 | - name: ENVIRONMENT
14 | value: 'kubernetes'
15 | ports:
16 | - containerPort: 8080
17 | - containerPort: 11111
18 | resources:
19 | limits:
20 | memory: 400Mi
21 | restartPolicy: OnFailure
22 | ---
23 | kind: Service
24 | apiVersion: v1
25 | metadata:
26 | name: hystrixdashboard-service
27 | spec:
28 | selector:
29 | app: hystrixdashboard
30 | ports:
31 | - protocol: TCP
32 | port: 8080
33 | name: api
34 | - protocol: TCP
35 | port: 11111
36 | name: actuator
37 |
--------------------------------------------------------------------------------
/setup/kubernetes/kubernetes-dashboard.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | labels:
5 | k8s-app: kubernetes-dashboard
6 | name: kubernetes-dashboard-nodeport
7 | namespace: kube-system
8 | spec:
9 | selector:
10 | k8s-app: kubernetes-dashboard
11 | ports:
12 | - protocol: TCP
13 | port: 8443
14 | targetPort: 8443
15 | nodePort: 31234
16 | sessionAffinity: None
17 | type: NodePort
18 |
19 |
--------------------------------------------------------------------------------
/setup/kubernetes/mysqlbm-pod.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | labels:
5 | app: mysqlbm
6 | name: mysqlbm
7 | spec:
8 | containers:
9 | - image: mysql:8.0
10 | name: mysqlbm
11 | env:
12 | - name: MYSQL_DATABASE
13 | value: packtdb
14 | - name: MYSQL_PASSWORD
15 | value: superSecret
16 | - name: MYSQL_ROOT_HOST
17 | value: '%'
18 | - name: MYSQL_ROOT_PASSWORD
19 | value: superDuperSecret
20 | - name: MYSQL_USER
21 | value: packt
22 | imagePullPolicy: Always
23 | ports:
24 | - containerPort: 3306
25 | resources: {}
26 | restartPolicy: OnFailure
27 |
28 | ---
29 | kind: Service
30 | apiVersion: v1
31 | metadata:
32 | name: mysqlbm
33 | spec:
34 | selector:
35 | app: mysqlbm
36 | ports:
37 | - protocol: TCP
38 | port: 3306
39 | name: api
--------------------------------------------------------------------------------
/setup/kubernetes/mysqlra-pod.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | creationTimestamp: null
5 | labels:
6 | app: mysqlra
7 | name: mysqlra
8 | spec:
9 | containers:
10 | - image: mysql:8.0
11 | name: mysqlra
12 | env:
13 | - name: MYSQL_DATABASE
14 | value: packtdb
15 | - name: MYSQL_PASSWORD
16 | value: superSecret
17 | - name: MYSQL_ROOT_HOST
18 | value: '%'
19 | - name: MYSQL_ROOT_PASSWORD
20 | value: superDuperSecret
21 | - name: MYSQL_USER
22 | value: packt
23 | imagePullPolicy: Always
24 | ports:
25 | - containerPort: 3306
26 | resources: {}
27 | restartPolicy: OnFailure
28 | status: {}
29 | ---
30 | kind: Service
31 | apiVersion: v1
32 | metadata:
33 | name: mysqlra
34 | spec:
35 | selector:
36 | app: mysqlra
37 | ports:
38 | - protocol: TCP
39 | port: 3306
40 | name: api
--------------------------------------------------------------------------------
/setup/kubernetes/mysqlus-pod.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | labels:
5 | app: mysqlus
6 | name: mysqlus
7 | spec:
8 | containers:
9 | - image: mysql:8.0
10 | name: mysqlus
11 | env:
12 | - name: MYSQL_DATABASE
13 | value: packtdb
14 | - name: MYSQL_PASSWORD
15 | value: superSecret
16 | - name: MYSQL_ROOT_HOST
17 | value: '%'
18 | - name: MYSQL_ROOT_PASSWORD
19 | value: superDuperSecret
20 | - name: MYSQL_USER
21 | value: packt
22 | imagePullPolicy: Always
23 | ports:
24 | - containerPort: 3306
25 | resources: {}
26 | restartPolicy: OnFailure
27 | ---
28 | kind: Service
29 | apiVersion: v1
30 | metadata:
31 | name: mysqlus
32 | spec:
33 | selector:
34 | app: mysqlus
35 | ports:
36 | - protocol: TCP
37 | port: 3306
38 | name: api
--------------------------------------------------------------------------------
/setup/kubernetes/nginx-ingress.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: default-http-backend
5 | spec:
6 | replicas: 1
7 | selector:
8 | matchLabels:
9 | app: default-http-backend
10 | template:
11 | metadata:
12 | labels:
13 | app: default-http-backend
14 | spec:
15 | terminationGracePeriodSeconds: 60
16 | containers:
17 | - name: default-http-backend
18 | # Any image is permissable as long as:
19 | # 1. It serves a 404 page at /
20 | # 2. It serves 200 on a /healthz endpoint
21 | image: k8s.gcr.io/defaultbackend:1.0
22 | livenessProbe:
23 | httpGet:
24 | path: /healthz
25 | port: 8080
26 | scheme: HTTP
27 | initialDelaySeconds: 30
28 | timeoutSeconds: 5
29 | ports:
30 | - containerPort: 8080
31 | resources:
32 | limits:
33 | cpu: 10m
34 | memory: 20Mi
35 | requests:
36 | cpu: 10m
37 | memory: 20Mi
38 | ---
39 | kind: Service
40 | apiVersion: v1
41 | metadata:
42 | name: default-http-backend
43 | spec:
44 | selector:
45 | app: default-http-backend
46 | ports:
47 | - protocol: TCP
48 | port: 80
49 | targetPort: 8080
50 | type: NodePort
51 | ---
52 | apiVersion: apps/v1
53 | kind: Deployment
54 | metadata:
55 | name: nginx-ingress-controller
56 | spec:
57 | replicas: 1
58 | selector:
59 | matchLabels:
60 | k8s-app: nginx-ingress-lb
61 | revisionHistoryLimit: 3
62 | template:
63 | metadata:
64 | labels:
65 | k8s-app: nginx-ingress-lb
66 | spec:
67 | containers:
68 | - args:
69 | - /nginx-ingress-controller
70 | - "--default-backend-service=$(POD_NAMESPACE)/default-http-backend"
71 | env:
72 | - name: POD_NAME
73 | valueFrom:
74 | fieldRef:
75 | fieldPath: metadata.name
76 | - name: POD_NAMESPACE
77 | valueFrom:
78 | fieldRef:
79 | fieldPath: metadata.namespace
80 | image: "quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.17.1"
81 | imagePullPolicy: Always
82 | livenessProbe:
83 | httpGet:
84 | path: /healthz
85 | port: 10254
86 | scheme: HTTP
87 | initialDelaySeconds: 10
88 | timeoutSeconds: 5
89 | name: nginx-ingress-controller
90 | ports:
91 | - containerPort: 80
92 | name: http
93 | protocol: TCP
94 | terminationGracePeriodSeconds: 60
95 | ---
96 | apiVersion: v1
97 | kind: Service
98 | metadata:
99 | name: nginx-ingress
100 | spec:
101 | type: LoadBalancer
102 | ports:
103 | - name: http
104 | port: 80
105 | targetPort: http
106 | selector:
107 | k8s-app: nginx-ingress-lb
108 |
109 | ---
110 | apiVersion: extensions/v1beta1
111 | kind: Ingress
112 | metadata:
113 | name: yummy-ingress
114 | annotations:
115 | kubernetes.io/ingress.class: "nginx"
116 | spec:
117 | rules:
118 | - host: localhost
119 | http:
120 | paths:
121 | - path: /
122 | backend:
123 | serviceName: reverseproxy-service
124 | servicePort: 8080
125 | - path: /zipkin
126 | backend:
127 | serviceName: zipkin-service
128 | servicePort: 9411
129 |
--------------------------------------------------------------------------------
/setup/kubernetes/rabbitmq-pod.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | labels:
5 | app: rabbitmq
6 | name: rabbitmq
7 | spec:
8 | containers:
9 | - env:
10 | - name: RABBITMQ_DEFAULT_PASS
11 | value: publishing
12 | - name: RABBITMQ_DEFAULT_USER
13 | value: packt
14 | image: rabbitmq:3.7-management
15 | name: rabbitmq
16 | imagePullPolicy: Always
17 | ports:
18 | - containerPort: 5672
19 | - containerPort: 15672
20 | volumeMounts:
21 | - mountPath: /var/lib/rabbitmq
22 | name: rabbitmq-claim0
23 | restartPolicy: OnFailure
24 | volumes:
25 | - name: rabbitmq-claim0
26 | persistentVolumeClaim:
27 | claimName: rabbitmq-claim0
28 | ---
29 | kind: Service
30 | apiVersion: v1
31 | metadata:
32 | name: rabbitmq
33 | spec:
34 | selector:
35 | app: rabbitmq
36 | ports:
37 | - protocol: TCP
38 | port: 5672
39 | name: api
40 | - protocol: TCP
41 | port: 15672
42 | name: ui
43 |
44 | ---
45 | apiVersion: v1
46 | kind: PersistentVolumeClaim
47 | metadata:
48 | labels:
49 | app: rabbitmq-claim0
50 | name: rabbitmq-claim0
51 | spec:
52 | accessModes:
53 | - ReadWriteOnce
54 | resources:
55 | requests:
56 | storage: 100Mi
57 |
--------------------------------------------------------------------------------
/setup/kubernetes/ratings-service-pod.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | labels:
5 | app: ratings
6 | name: ratings
7 | spec:
8 | containers:
9 | - image: localhost:5000/ratings
10 | name: users
11 | imagePullPolicy: Always
12 | env:
13 | - name: ENVIRONMENT
14 | value: 'kubernetes'
15 | - name: DB_NAME
16 | value: 'mysqlra'
17 | ports:
18 | - containerPort: 8080
19 | - containerPort: 11111
20 | resources:
21 | limits:
22 | memory: 550Mi
23 | restartPolicy: OnFailure
24 | ---
25 | kind: Service
26 | apiVersion: v1
27 | metadata:
28 | name: ratings-service
29 | spec:
30 | selector:
31 | app: ratings
32 | ports:
33 | - protocol: TCP
34 | port: 8080
35 | name: api
36 | - protocol: TCP
37 | port: 11111
38 | name: actuator
39 |
--------------------------------------------------------------------------------
/setup/kubernetes/redis-pod.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | creationTimestamp: null
5 | labels:
6 | app: redis
7 | name: redis
8 | spec:
9 | containers:
10 | - image: redis:alpine
11 | name: redis
12 | imagePullPolicy: Always
13 | ports:
14 | - containerPort: 6379
15 | resources: {}
16 | restartPolicy: OnFailure
17 | status: {}
18 | ---
19 | kind: Service
20 | apiVersion: v1
21 | metadata:
22 | name: redis
23 | spec:
24 | selector:
25 | app: redis
26 | ports:
27 | - protocol: TCP
28 | port: 6379
29 | name: api
--------------------------------------------------------------------------------
/setup/kubernetes/redisCommander-pod.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | creationTimestamp: null
5 | labels:
6 | app: rediscommander
7 | name: rediscommander
8 | spec:
9 | containers:
10 | - args:
11 | - --redis-host
12 | - redis
13 | image: tenstartups/redis-commander
14 | name: rediscommander
15 | imagePullPolicy: Always
16 | ports:
17 | - containerPort: 8081
18 | resources: {}
19 | restartPolicy: OnFailure
20 | status: {}
21 |
--------------------------------------------------------------------------------
/setup/kubernetes/reverseproxy-pod.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | labels:
5 | app: reverseproxy
6 | name: reverseproxy
7 | spec:
8 | containers:
9 | - image: localhost:5000/reverseproxy
10 | name: users
11 | imagePullPolicy: Always
12 | env:
13 | - name: ENVIRONMENT
14 | value: 'kubernetes'
15 | ports:
16 | - containerPort: 8080
17 | - containerPort: 11111
18 | resources:
19 | limits:
20 | memory: 450Mi
21 | restartPolicy: OnFailure
22 | ---
23 | kind: Service
24 | apiVersion: v1
25 | metadata:
26 | name: reverseproxy-service
27 | spec:
28 | selector:
29 | app: reverseproxy
30 | ports:
31 | - protocol: TCP
32 | port: 8080
33 | name: api
34 | - protocol: TCP
35 | port: 11111
36 | name: actuator
37 |
--------------------------------------------------------------------------------
/setup/kubernetes/serviceregistry-pod.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | labels:
5 | app: serviceregistry
6 | name: serviceregistry
7 | spec:
8 | containers:
9 | - image: localhost:5000/serviceregistry
10 | name: serviceregistry
11 | imagePullPolicy: Always
12 | ports:
13 | - containerPort: 8761
14 | - containerPort: 11111
15 | resources:
16 | limits:
17 | memory: 450Mi
18 | restartPolicy: OnFailure
19 | ---
20 | kind: Service
21 | apiVersion: v1
22 | metadata:
23 | name: serviceregistry
24 | spec:
25 | selector:
26 | app: serviceregistry
27 | ports:
28 | - protocol: TCP
29 | port: 8761
30 | name: api
31 | - protocol: TCP
32 | port: 11111
33 | name: actuator
34 |
--------------------------------------------------------------------------------
/setup/kubernetes/turbine-pod.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | labels:
5 | app: turbine
6 | name: turbine
7 | spec:
8 | containers:
9 | - image: localhost:5000/turbine
10 | name: turbine
11 | imagePullPolicy: Always
12 | ports:
13 | - containerPort: 8080
14 | - containerPort: 11111
15 | resources:
16 | limits:
17 | memory: 450Mi
18 | restartPolicy: OnFailure
19 | ---
20 | kind: Service
21 | apiVersion: v1
22 | metadata:
23 | name: turbine
24 | spec:
25 | selector:
26 | app: turbine
27 | ports:
28 | - protocol: TCP
29 | port: 8080
30 | name: api
31 | - protocol: TCP
32 | port: 11111
33 | name: actuator
34 |
--------------------------------------------------------------------------------
/setup/kubernetes/users-service-pod.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | labels:
5 | app: users
6 | name: users
7 | spec:
8 | containers:
9 | - image: localhost:5000/users
10 | name: users
11 | imagePullPolicy: Always
12 | env:
13 | - name: ENVIRONMENT
14 | value: 'kubernetes'
15 | - name: DB_NAME
16 | value: 'mysqlus'
17 | ports:
18 | - containerPort: 8080
19 | - containerPort: 11111
20 | resources:
21 | limits:
22 | memory: 550Mi
23 | restartPolicy: OnFailure
24 | ---
25 | kind: Service
26 | apiVersion: v1
27 | metadata:
28 | name: users-service
29 | spec:
30 | selector:
31 | app: users
32 | ports:
33 | - protocol: TCP
34 | port: 8080
35 | name: api
36 | - protocol: TCP
37 | port: 11111
38 | name: actuator
39 |
--------------------------------------------------------------------------------
/setup/kubernetes/zipkin-pod.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | labels:
5 | app: zipkin
6 | name: zipkin
7 | spec:
8 | containers:
9 | - env:
10 | - name: RABBIT_URI
11 | value: amqp://packt:publishing@rabbitmq:5672
12 | image: openzipkin/zipkin
13 | name: zipkin
14 | imagePullPolicy: Always
15 | ports:
16 | - containerPort: 9410
17 | - containerPort: 9411
18 | restartPolicy: OnFailure
19 | ---
20 | kind: Service
21 | apiVersion: v1
22 | metadata:
23 | name: zipkin-service
24 | spec:
25 | selector:
26 | app: zipkin
27 | ports:
28 | - protocol: TCP
29 | port: 9410
30 | name: api
31 | - protocol: TCP
32 | port: 9411
33 | name: ui
34 |
--------------------------------------------------------------------------------
/setup/runAll.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | unamestr=`uname`
4 |
5 | if [[ "$unamestr" == 'Linux' ]]; then
6 | BASEDIR=`dirname $0`
7 | elif [[ "$unamestr" == 'Darwin' ]]; then
8 | BASEDIR=`dirname $(greadlink -f $0)`
9 | fi
10 | cd $BASEDIR
11 |
12 | docker-compose up -d
13 |
14 | DIRS=(configserver serviceregistry reverseproxy bookmarks users)
15 | for i in "${DIRS[@]}"
16 | do
17 | echo ""
18 | echo "############################"
19 | echo "Make sure $i is stopped"
20 | ./stopService.sh $i
21 | echo "Start: $i"
22 | cd ../$i
23 | mvn clean install -DskipTests -DskipITs
24 | cd target
25 | echo "Starting $i"
26 | ./*.jar start 2>run.log >run.log &
27 | #give the service a little bit of time
28 | sleep 5
29 | echo "Done starting $i"
30 | cd $BASEDIR
31 | done
32 |
--------------------------------------------------------------------------------
/setup/startInfraServices.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | unamestr=`uname`
4 |
5 | if [[ "$unamestr" == 'Linux' ]]; then
6 | BASEDIR=`dirname $0`
7 | elif [[ "$unamestr" == 'Darwin' ]]; then
8 | BASEDIR=`dirname $(greadlink -f $0)`
9 | fi
10 | cd $BASEDIR
11 |
12 | docker-compose up -d --build rabbitmq zipkin redis redisCommander mysqlbm mysqlra mysqlus
13 |
14 |
--------------------------------------------------------------------------------
/setup/stopAll.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | unamestr=`uname`
4 |
5 | if [[ "$unamestr" == 'Linux' ]]; then
6 | BASEDIR=`dirname $0`
7 | elif [[ "$unamestr" == 'Darwin' ]]; then
8 | BASEDIR=`dirname $(greadlink -f $0)`
9 | fi
10 | cd $BASEDIR
11 |
12 | docker-compose down
13 |
14 | DIRS=(configserver serviceregistry reverseproxy bookmarks users)
15 | for i in "${DIRS[@]}"
16 | do
17 | ./stopService.sh $i
18 | done
19 |
--------------------------------------------------------------------------------
/setup/stopService.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | unamestr=`uname`
4 |
5 | if [[ "$unamestr" == 'Linux' ]]; then
6 | BASEDIR=`dirname $0`
7 | elif [[ "$unamestr" == 'Darwin' ]]; then
8 | BASEDIR=`dirname $(greadlink -f $0)`
9 | fi
10 | cd $BASEDIR
11 |
12 | echo "Stopping: $1"
13 | cd ../$1/target
14 | if [ -f "application.pid" ]; then
15 | echo "Found pid file for $1"
16 | pkill -F application.pid
17 | sleep 1
18 | if [ -f "application.pid" ]; then
19 | if pgrep -F "application.pid" > /dev/null
20 | then
21 | echo "Still running -- forcing kill"
22 | pkill -9 -F application.pid
23 | else
24 | echo "Removing pid file"
25 | rm application.pid
26 | fi
27 | fi
28 | else
29 | echo "Not running"
30 | fi
31 |
--------------------------------------------------------------------------------
/turbine/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 |
4 | ### STS ###
5 | .apt_generated
6 | .classpath
7 | .factorypath
8 | .project
9 | .settings
10 | .springBeans
11 | .sts4-cache
12 |
13 | ### IntelliJ IDEA ###
14 | .idea
15 | *.iws
16 | *.iml
17 | *.ipr
18 |
19 | ### NetBeans ###
20 | /nbproject/private/
21 | /build/
22 | /nbbuild/
23 | /dist/
24 | /nbdist/
25 | /.nb-gradle/
--------------------------------------------------------------------------------
/turbine/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jre-alpine3.8
2 | RUN apk --update add curl
3 |
4 | HEALTHCHECK CMD curl -v --fail http://localhost:11111/actuator/info || exit 1
5 |
6 | COPY target/service.jar /usr/app/service.jar
7 | EXPOSE 8080 11111
8 | ENV ENVIRONMENT="local"
9 |
10 | ENTRYPOINT java -Djava.net.preferIPv4Stack=true -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -jar /usr/app/service.jar --spring.profiles.active=$ENVIRONMENT,docker --spring.cloud.config.uri=http://configserver:8888
--------------------------------------------------------------------------------
/turbine/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM http://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
40 |
41 | @REM set %HOME% to equivalent of $HOME
42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
43 |
44 | @REM Execute a user defined script before this one
45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
49 | :skipRcPre
50 |
51 | @setlocal
52 |
53 | set ERROR_CODE=0
54 |
55 | @REM To isolate internal variables from possible post scripts, we use another setlocal
56 | @setlocal
57 |
58 | @REM ==== START VALIDATION ====
59 | if not "%JAVA_HOME%" == "" goto OkJHome
60 |
61 | echo.
62 | echo Error: JAVA_HOME not found in your environment. >&2
63 | echo Please set the JAVA_HOME variable in your environment to match the >&2
64 | echo location of your Java installation. >&2
65 | echo.
66 | goto error
67 |
68 | :OkJHome
69 | if exist "%JAVA_HOME%\bin\java.exe" goto init
70 |
71 | echo.
72 | echo Error: JAVA_HOME is set to an invalid directory. >&2
73 | echo JAVA_HOME = "%JAVA_HOME%" >&2
74 | echo Please set the JAVA_HOME variable in your environment to match the >&2
75 | echo location of your Java installation. >&2
76 | echo.
77 | goto error
78 |
79 | @REM ==== END VALIDATION ====
80 |
81 | :init
82 |
83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
84 | @REM Fallback to current working directory if not found.
85 |
86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
88 |
89 | set EXEC_DIR=%CD%
90 | set WDIR=%EXEC_DIR%
91 | :findBaseDir
92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
93 | cd ..
94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
95 | set WDIR=%CD%
96 | goto findBaseDir
97 |
98 | :baseDirFound
99 | set MAVEN_PROJECTBASEDIR=%WDIR%
100 | cd "%EXEC_DIR%"
101 | goto endDetectBaseDir
102 |
103 | :baseDirNotFound
104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
105 | cd "%EXEC_DIR%"
106 |
107 | :endDetectBaseDir
108 |
109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
110 |
111 | @setlocal EnableExtensions EnableDelayedExpansion
112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
114 |
115 | :endReadAdditionalConfig
116 |
117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
118 |
119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
121 |
122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
123 | if ERRORLEVEL 1 goto error
124 | goto end
125 |
126 | :error
127 | set ERROR_CODE=1
128 |
129 | :end
130 | @endlocal & set ERROR_CODE=%ERROR_CODE%
131 |
132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
136 | :skipRcPost
137 |
138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
140 |
141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
142 |
143 | exit /B %ERROR_CODE%
144 |
--------------------------------------------------------------------------------
/turbine/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.packtpub.yummy
7 | turbine
8 | 0.0.1-SNAPSHOT
9 | jar
10 |
11 | turbine
12 | Blowing your events away
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-parent
17 | 2.0.3.RELEASE
18 |
19 |
20 |
21 |
22 | UTF-8
23 | UTF-8
24 | 1.8
25 | Finchley.RELEASE
26 |
27 |
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-starter-amqp
32 |
33 |
34 | org.springframework.boot
35 | spring-boot-starter-actuator
36 |
37 |
38 | org.springframework.cloud
39 | spring-cloud-bus
40 |
41 |
42 | org.springframework.cloud
43 | spring-cloud-starter-config
44 |
45 |
46 | org.springframework.cloud
47 | spring-cloud-starter-netflix-eureka-client
48 |
49 |
50 | org.springframework.cloud
51 | spring-cloud-starter-netflix-turbine-stream
52 |
53 |
54 | org.springframework.cloud
55 | spring-cloud-stream-binder-rabbit
56 |
57 |
58 |
59 | org.springframework.boot
60 | spring-boot-starter-test
61 | test
62 |
63 |
64 |
65 |
66 |
67 |
68 | org.springframework.cloud
69 | spring-cloud-dependencies
70 | ${spring-cloud.version}
71 | pom
72 | import
73 |
74 |
75 |
76 |
77 |
78 | service
79 |
80 |
81 | org.springframework.boot
82 | spring-boot-maven-plugin
83 |
84 |
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/turbine/src/main/java/com/packtpub/yummy/turbine/TurbineApplication.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.turbine;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.netflix.turbine.stream.EnableTurbineStream;
6 |
7 | @SpringBootApplication
8 | @EnableTurbineStream
9 | public class TurbineApplication {
10 |
11 | public static void main(String[] args) {
12 | SpringApplication.run(TurbineApplication.class, args);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/turbine/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 |
2 | server.port: 9999
3 | management:
4 | server:
5 | port: 11112
--------------------------------------------------------------------------------
/turbine/src/main/resources/bootstrap.yaml:
--------------------------------------------------------------------------------
1 | spring:
2 | application.name: 'turbine'
3 | cloud:
4 | config:
5 | failFast: true
6 | retry:
7 | max-attempts: 60
8 | discovery:
9 | enabled: false
10 | uri: 'http://localhost:8888'
11 |
12 |
--------------------------------------------------------------------------------
/turbine/src/test/java/com/packtpub/yummy/turbine/TurbineApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.turbine;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class TurbineApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/users/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 |
4 | ### STS ###
5 | .apt_generated
6 | .classpath
7 | .factorypath
8 | .project
9 | .settings
10 | .springBeans
11 | .sts4-cache
12 |
13 | ### IntelliJ IDEA ###
14 | .idea
15 | *.iws
16 | *.iml
17 | *.ipr
18 |
19 | ### NetBeans ###
20 | /nbproject/private/
21 | /build/
22 | /nbbuild/
23 | /dist/
24 | /nbdist/
25 | /.nb-gradle/
--------------------------------------------------------------------------------
/users/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jre-alpine3.8
2 | RUN apk --update add curl
3 | HEALTHCHECK CMD curl -v --fail http://localhost:11111/actuator/info || exit 1
4 |
5 | COPY target/service.jar /usr/app/service.jar
6 | EXPOSE 8080 11111
7 | ENV ENVIRONMENT="local"
8 | ENV DB_NAME="db"
9 | ENTRYPOINT java -Djava.net.preferIPv4Stack=true -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -jar /usr/app/service.jar --spring.profiles.active=$ENVIRONMENT,docker --db.name=$DB_NAME --spring.cloud.config.uri=http://configserver:8888
--------------------------------------------------------------------------------
/users/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM http://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
40 |
41 | @REM set %HOME% to equivalent of $HOME
42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
43 |
44 | @REM Execute a user defined script before this one
45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
49 | :skipRcPre
50 |
51 | @setlocal
52 |
53 | set ERROR_CODE=0
54 |
55 | @REM To isolate internal variables from possible post scripts, we use another setlocal
56 | @setlocal
57 |
58 | @REM ==== START VALIDATION ====
59 | if not "%JAVA_HOME%" == "" goto OkJHome
60 |
61 | echo.
62 | echo Error: JAVA_HOME not found in your environment. >&2
63 | echo Please set the JAVA_HOME variable in your environment to match the >&2
64 | echo location of your Java installation. >&2
65 | echo.
66 | goto error
67 |
68 | :OkJHome
69 | if exist "%JAVA_HOME%\bin\java.exe" goto init
70 |
71 | echo.
72 | echo Error: JAVA_HOME is set to an invalid directory. >&2
73 | echo JAVA_HOME = "%JAVA_HOME%" >&2
74 | echo Please set the JAVA_HOME variable in your environment to match the >&2
75 | echo location of your Java installation. >&2
76 | echo.
77 | goto error
78 |
79 | @REM ==== END VALIDATION ====
80 |
81 | :init
82 |
83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
84 | @REM Fallback to current working directory if not found.
85 |
86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
88 |
89 | set EXEC_DIR=%CD%
90 | set WDIR=%EXEC_DIR%
91 | :findBaseDir
92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
93 | cd ..
94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
95 | set WDIR=%CD%
96 | goto findBaseDir
97 |
98 | :baseDirFound
99 | set MAVEN_PROJECTBASEDIR=%WDIR%
100 | cd "%EXEC_DIR%"
101 | goto endDetectBaseDir
102 |
103 | :baseDirNotFound
104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
105 | cd "%EXEC_DIR%"
106 |
107 | :endDetectBaseDir
108 |
109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
110 |
111 | @setlocal EnableExtensions EnableDelayedExpansion
112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
114 |
115 | :endReadAdditionalConfig
116 |
117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
118 |
119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
121 |
122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
123 | if ERRORLEVEL 1 goto error
124 | goto end
125 |
126 | :error
127 | set ERROR_CODE=1
128 |
129 | :end
130 | @endlocal & set ERROR_CODE=%ERROR_CODE%
131 |
132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
136 | :skipRcPost
137 |
138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
140 |
141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
142 |
143 | exit /B %ERROR_CODE%
144 |
--------------------------------------------------------------------------------
/users/src/main/java/com/packtpub/yummy/users/UsersApplication.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.users;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class UsersApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(UsersApplication.class, args);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/users/src/main/java/com/packtpub/yummy/users/config/DataInitialization.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.users.config;
2 |
3 | import com.packtpub.yummy.users.service.UserService;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.boot.context.event.ApplicationReadyEvent;
8 | import org.springframework.context.ApplicationListener;
9 | import org.springframework.security.core.authority.SimpleGrantedAuthority;
10 | import org.springframework.security.core.userdetails.User;
11 | import org.springframework.stereotype.Component;
12 |
13 | import java.util.Arrays;
14 |
15 | @Component
16 | public class DataInitialization implements ApplicationListener {
17 | private static final Logger LOG = LoggerFactory.getLogger(DataInitialization.class);
18 | @Autowired
19 | UserService userService;
20 | @Override
21 | public void onApplicationEvent(ApplicationReadyEvent event) {
22 | if (!userService.hasUser("admin")) {
23 | userService.addUser(new User("admin", "password",
24 | Arrays.asList(
25 | new SimpleGrantedAuthority("ROLE_ADMIN"),
26 | new SimpleGrantedAuthority("ROLE_USER")
27 | )));
28 | }
29 | if (!userService.hasUser("user")) {
30 | userService.addUser(new User("user", "password",
31 | Arrays.asList(
32 | new SimpleGrantedAuthority("ROLE_USER")
33 | )));
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/users/src/main/java/com/packtpub/yummy/users/config/SecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.users.config;
2 |
3 | import lombok.AllArgsConstructor;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
8 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
9 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
10 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
11 | import org.springframework.security.crypto.factory.PasswordEncoderFactories;
12 | import org.springframework.security.crypto.password.PasswordEncoder;
13 | import org.springframework.web.util.DefaultUriBuilderFactory;
14 |
15 | import javax.sql.DataSource;
16 |
17 | @Configuration
18 | @AllArgsConstructor
19 | @EnableGlobalMethodSecurity(prePostEnabled = true)
20 | public class SecurityConfig extends WebSecurityConfigurerAdapter {
21 | private final DataSource dataSource;
22 | private final DefaultUriBuilderFactory defaultUriBuilderFactory
23 | = new DefaultUriBuilderFactory();
24 | @Bean
25 | public PasswordEncoder passwordEncoder() {
26 | return PasswordEncoderFactories.createDelegatingPasswordEncoder();
27 | }
28 |
29 | @Override
30 | protected void configure(HttpSecurity http) throws Exception {
31 | http
32 | .authorizeRequests()
33 | .antMatchers("/webjars/**", "/actuator/**").permitAll()
34 | .anyRequest().authenticated()
35 | .and()
36 | .formLogin().loginPage("/login").permitAll()
37 | .successHandler((request, response, authentication) ->
38 | response.sendRedirect(
39 | defaultUriBuilderFactory.builder()
40 | .replacePath("/").build().toString()
41 | )
42 | )
43 | .and()
44 | .logout().permitAll();
45 | }
46 |
47 | @Autowired
48 | public void configureGlobal(AuthenticationManagerBuilder builder) throws Exception {
49 | builder.jdbcAuthentication()
50 | .dataSource(dataSource)
51 | .passwordEncoder(passwordEncoder());
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/users/src/main/java/com/packtpub/yummy/users/config/WebConfig.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.users.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.core.Ordered;
6 | import org.springframework.http.MediaType;
7 | import org.springframework.http.converter.HttpMessageConverter;
8 | import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
9 | import org.springframework.web.servlet.LocaleResolver;
10 | import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
11 | import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
12 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
13 | import org.springframework.web.servlet.i18n.SessionLocaleResolver;
14 |
15 | import java.util.List;
16 | import java.util.Locale;
17 |
18 | @Configuration
19 | public class WebConfig implements WebMvcConfigurer {
20 |
21 |
22 | @Override
23 | public void addViewControllers(ViewControllerRegistry registry) {
24 | registry.addViewController("/login").setViewName("login");
25 | registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
26 | }
27 |
28 | @Override
29 | public void extendMessageConverters(List> converters) {
30 | converters.removeIf(c -> c instanceof Jaxb2RootElementHttpMessageConverter);
31 | }
32 |
33 | @Override
34 | public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
35 | configurer.defaultContentType(MediaType.APPLICATION_JSON_UTF8);
36 | }
37 |
38 | @Bean
39 | public LocaleResolver localeResolver(){
40 | SessionLocaleResolver slr = new SessionLocaleResolver();
41 | slr.setDefaultLocale(Locale.GERMANY);
42 | return slr;
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/users/src/main/java/com/packtpub/yummy/users/service/UserService.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.users.service;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
5 | import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
6 | import org.springframework.jdbc.core.namedparam.SqlParameterSource;
7 | import org.springframework.security.core.userdetails.UserDetails;
8 | import org.springframework.security.crypto.password.PasswordEncoder;
9 | import org.springframework.stereotype.Service;
10 |
11 | @Service
12 | public class UserService {
13 | @Autowired
14 | PasswordEncoder passwordEncoder;
15 | @Autowired
16 | NamedParameterJdbcTemplate jdbcTemplate;
17 |
18 | public void addUser(UserDetails userDetails) {
19 | jdbcTemplate.update("INSERT INTO users(username, password,enabled)" +
20 | " VALUES (lower(:username),:password,1)",
21 | new MapSqlParameterSource("username", userDetails.getUsername())
22 | .addValue("password", passwordEncoder.encode(userDetails.getPassword())));
23 | jdbcTemplate.batchUpdate("INSERT INTO authorities(username, authority) " +
24 | "VALUES (lower(:username), :role)",
25 | (SqlParameterSource[]) userDetails.getAuthorities().stream()
26 | .map(a -> new MapSqlParameterSource("username", userDetails.getUsername())
27 | .addValue("role", a.getAuthority()))
28 | .toArray(size -> new SqlParameterSource[size]));
29 | }
30 |
31 | public boolean hasUser(String username){
32 | return !jdbcTemplate.query("select 1 from users where username=lower(:username)",
33 | new MapSqlParameterSource("username",username)
34 | ,(rs, rowNum) -> rs.getInt(1)
35 | ).isEmpty();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/users/src/main/resources/META-INF/spring.factories:
--------------------------------------------------------------------------------
1 | org.springframework.context.ApplicationListener=\
2 | org.springframework.boot.context.ApplicationPidFileWriter
--------------------------------------------------------------------------------
/users/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 | spring:
2 | datasource:
3 | url: "jdbc:mysql://localhost:3307/packtdb"
4 | username: "packt"
5 | password: "superSecret"
6 |
7 | server.port: 9070
8 |
--------------------------------------------------------------------------------
/users/src/main/resources/bootstrap.yaml:
--------------------------------------------------------------------------------
1 | spring:
2 | application.name: 'users'
3 | cloud:
4 | config:
5 | failFast: true
6 | retry:
7 | max-attempts: 60
8 | discovery:
9 | enabled: false
10 | uri: 'http://localhost:8888'
11 |
12 |
--------------------------------------------------------------------------------
/users/src/main/resources/db/migration/V1.0__init.sql:
--------------------------------------------------------------------------------
1 | create table users (
2 | username varchar(50) not null primary key,
3 | password varchar(500) not null,
4 | enabled boolean not null
5 | );
6 | create table authorities (
7 | username varchar(50) not null,
8 | authority varchar(50) not null,
9 | constraint fk_authorities_users
10 | foreign key (username) references users (username)
11 | );
12 | create unique index ix_auth_username
13 | on authorities (username, authority);
--------------------------------------------------------------------------------
/users/src/main/resources/templates/login.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | Our Login Page
7 |
8 |
9 |
10 |
11 | Login with Username and Password please
12 |
13 |
14 |
42 |
46 |
47 |
--------------------------------------------------------------------------------
/users/src/test/java/com/packtpub/yummy/users/UsersApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.packtpub.yummy.users;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class UsersApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/users/src/test/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 | spring.data.redis.repositories.enabled=false
3 | spring.session.store-type=none
4 |
5 |
--------------------------------------------------------------------------------
/users/src/test/resources/bootstrap.yaml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | config:
4 | enabled: false
5 |
--------------------------------------------------------------------------------