├── .gitignore
├── 01-hello-world-rest-api
├── Dockerfile
├── pom.xml
├── readme.md
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── in28minutes
│ │ │ └── rest
│ │ │ └── webservices
│ │ │ └── restfulwebservices
│ │ │ ├── HelloWorldBean.java
│ │ │ ├── HelloWorldController.java
│ │ │ └── RestfulWebServicesApplication.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── in28minutes
│ └── rest
│ └── webservices
│ └── restfulwebservices
│ └── RestfulWebServicesApplicationTests.java
├── 02-spring-boot-simple-task
├── Dockerfile
├── pom.xml
├── readme.md
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── in28minutes
│ │ │ └── spring
│ │ │ └── simple
│ │ │ └── task
│ │ │ ├── EnvironmentConfigurationLogger.java
│ │ │ ├── SpringSimpleTaskApplication.java
│ │ │ └── TaskImpl.java
│ └── resources
│ │ ├── application.properties
│ │ └── log.txt
│ └── test
│ └── java
│ └── com
│ └── in28minutes
│ └── spring
│ └── simple
│ └── task
│ └── SpringIn5StepsApplicationTests.java
├── 03-currency-exchange-service-h2
├── Dockerfile
├── pom.xml
├── readme.md
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── in28minutes
│ │ │ └── microservices
│ │ │ └── currencyexchangeservice
│ │ │ ├── CurrencyExchangeServiceApplicationH2.java
│ │ │ ├── resource
│ │ │ ├── CurrencyExchangeController.java
│ │ │ ├── ExchangeValue.java
│ │ │ └── ExchangeValueRepository.java
│ │ │ └── util
│ │ │ ├── containerservice
│ │ │ └── ContainerMetaDataService.java
│ │ │ └── logging
│ │ │ └── EnvironmentConfigurationLogger.java
│ └── resources
│ │ ├── application.properties
│ │ └── data.sql
│ └── test
│ └── java
│ └── com
│ └── in28minutes
│ └── microservices
│ └── currencyexchangeservice
│ └── CurrencyExchangeServiceApplicationTests.java
├── 04-currency-exchange-service-mysql
├── Dockerfile
├── pom.xml
├── readme.md
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── in28minutes
│ │ │ └── microservices
│ │ │ └── currencyexchangeservice
│ │ │ ├── CurrencyExchangeServiceApplicationMySql.java
│ │ │ ├── resource
│ │ │ ├── CurrencyExchangeController.java
│ │ │ ├── ExchangeValue.java
│ │ │ └── ExchangeValueRepository.java
│ │ │ └── util
│ │ │ ├── containerservice
│ │ │ └── ContainerMetaDataService.java
│ │ │ └── logging
│ │ │ └── EnvironmentConfigurationLogger.java
│ └── resources
│ │ └── application.properties
│ └── test
│ ├── java
│ └── com
│ │ └── in28minutes
│ │ └── microservices
│ │ └── currencyexchangeservice
│ │ └── CurrencyExchangeServiceApplicationTests.java
│ └── resources
│ └── application.properties
├── 05-currency-conversion-service
├── Dockerfile
├── pom.xml
├── readme.md
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── in28minutes
│ │ │ └── microservices
│ │ │ └── currencyconversionservice
│ │ │ ├── CurrencyConversionServiceApplication.java
│ │ │ ├── resource
│ │ │ ├── CurrencyConversionBean.java
│ │ │ └── CurrencyConversionController.java
│ │ │ └── util
│ │ │ ├── containerservice
│ │ │ └── ContainerMetaDataService.java
│ │ │ └── logging
│ │ │ └── EnvironmentConfigurationLogger.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── in28minutes
│ └── microservices
│ └── currencyconversionservice
│ └── CurrencyConversionServiceApplicationTests.java
├── 06-currency-exchange-service-h2-xray
├── Dockerfile
├── pom.xml
├── readme.md
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── in28minutes
│ │ │ └── microservices
│ │ │ └── currencyexchangeservice
│ │ │ ├── CurrencyExchangeServiceApplicationH2.java
│ │ │ ├── resource
│ │ │ ├── CurrencyExchangeController.java
│ │ │ ├── ExchangeValue.java
│ │ │ └── ExchangeValueRepository.java
│ │ │ ├── util
│ │ │ ├── containerservice
│ │ │ │ └── ContainerMetaDataService.java
│ │ │ └── logging
│ │ │ │ └── EnvironmentConfigurationLogger.java
│ │ │ └── xray
│ │ │ ├── AwsXrayConfig.java
│ │ │ └── XRayInspector.java
│ └── resources
│ │ ├── application.properties
│ │ └── data.sql
│ └── test
│ └── java
│ └── com
│ └── in28minutes
│ └── microservices
│ └── currencyexchangeservice
│ └── CurrencyExchangeServiceApplicationTests.java
├── 07-currency-conversion-service-xray
├── Dockerfile
├── pom.xml
├── readme.md
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── in28minutes
│ │ │ └── microservices
│ │ │ └── currencyconversionservice
│ │ │ ├── CurrencyConversionServiceApplication.java
│ │ │ ├── resource
│ │ │ ├── CurrencyConversionBean.java
│ │ │ └── CurrencyConversionController.java
│ │ │ ├── util
│ │ │ ├── containerservice
│ │ │ │ └── ContainerMetaDataService.java
│ │ │ └── logging
│ │ │ │ └── EnvironmentConfigurationLogger.java
│ │ │ └── xray
│ │ │ ├── AwsXrayConfig.java
│ │ │ └── XRayInspector.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── in28minutes
│ └── microservices
│ └── currencyconversionservice
│ └── CurrencyConversionServiceApplicationTests.java
├── 08-hello-world-rest-api-code-pipeline
├── Dockerfile
├── appspec.yaml
├── buildspec.yaml
├── pom.xml
├── readme.md
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── in28minutes
│ │ │ └── rest
│ │ │ └── webservices
│ │ │ └── restfulwebservices
│ │ │ ├── HelloWorldBean.java
│ │ │ ├── HelloWorldController.java
│ │ │ └── RestfulWebServicesApplication.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── in28minutes
│ └── rest
│ └── webservices
│ └── restfulwebservices
│ └── RestfulWebServicesApplicationTests.java
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 | /out-tsc
7 |
8 | # dependencies
9 | node_modules
10 |
11 | # IDEs and editors
12 | /.idea
13 | .project
14 | .classpath
15 | .c9/
16 | *.launch
17 | .settings/
18 | *.sublime-workspace
19 |
20 | # IDE - VSCode
21 | .vscode/*
22 | !.vscode/settings.json
23 | !.vscode/tasks.json
24 | !.vscode/launch.json
25 | !.vscode/extensions.json
26 |
27 | # misc
28 | /.sass-cache
29 | /connect.lock
30 | /coverage
31 | /libpeerconnection.log
32 | npm-debug.log
33 | yarn-error.log
34 | testem.log
35 | /typings
36 |
37 | # System Files
38 | .DS_Store
39 | Thumbs.db
40 |
41 | # Compiled class file
42 | *.class
43 |
44 | # Log file
45 | *.log
46 |
47 | # BlueJ files
48 | *.ctxt
49 |
50 | # Mobile Tools for Java (J2ME)
51 | .mtj.tmp/
52 |
53 | # Package Files #
54 | *.jar
55 | *.war
56 | *.ear
57 | *.tar.gz
58 | *.rar
59 | *.cmd
60 | *.classpath
61 | *.settings
62 | *.project
63 | *.mvn
64 | mvnw
65 | target
66 | *.DS_Store
67 |
68 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
69 | hs_err_pid*
70 |
--------------------------------------------------------------------------------
/01-hello-world-rest-api/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jdk-alpine
2 | VOLUME /tmp
3 | EXPOSE 80
4 | ADD target/*.jar app.jar
5 | ENV JAVA_OPTS=""
6 | ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]
--------------------------------------------------------------------------------
/01-hello-world-rest-api/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.in28minutes.rest.webservices
8 | 01-aws-hello-world-rest-api
9 | 1.0.0-RELEASE
10 | jar
11 | Demo project for Spring Boot
12 | aws-hello-world-rest-api
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-parent
17 | 2.1.0.RELEASE
18 |
19 |
20 |
21 |
22 | UTF-8
23 | UTF-8
24 | 1.8
25 |
26 |
27 |
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-starter-web
32 |
33 |
34 |
35 | org.springframework.boot
36 | spring-boot-devtools
37 | runtime
38 |
39 |
40 |
41 | javax.xml.bind
42 | jaxb-api
43 |
44 |
45 | com.sun.xml.bind
46 | jaxb-impl
47 | 2.3.0
48 |
49 |
50 | org.glassfish.jaxb
51 | jaxb-runtime
52 |
53 |
54 | javax.activation
55 | activation
56 | 1.1.1
57 |
58 |
59 |
60 | org.springframework.boot
61 | spring-boot-starter-test
62 | test
63 |
64 |
65 |
66 |
67 |
68 |
69 | org.springframework.boot
70 | spring-boot-maven-plugin
71 |
72 |
73 |
74 | com.spotify
75 | dockerfile-maven-plugin
76 | 1.4.10
77 |
78 |
79 | default
80 |
81 | build
82 |
83 |
84 |
85 |
86 |
87 | in28min/${project.name}
88 | ${project.version}
89 | true
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | spring-snapshots
98 | Spring Snapshots
99 | https://repo.spring.io/snapshot
100 |
101 | true
102 |
103 |
104 |
105 | spring-milestones
106 | Spring Milestones
107 | https://repo.spring.io/milestone
108 |
109 | false
110 |
111 |
112 |
113 |
114 |
115 |
116 | spring-snapshots
117 | Spring Snapshots
118 | https://repo.spring.io/snapshot
119 |
120 | true
121 |
122 |
123 |
124 | spring-milestones
125 | Spring Milestones
126 | https://repo.spring.io/milestone
127 |
128 | false
129 |
130 |
131 |
132 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/01-hello-world-rest-api/readme.md:
--------------------------------------------------------------------------------
1 | # Hello World Rest API
2 |
3 | - Main class com.in28minutes.rest.webservices.restfulwebservices.RestfulWebServicesApplication
4 | - You cannot run this app on local as it is configured to run on port 80 - https://serverfault.com/questions/112795/how-to-run-a-server-on-port-80-as-a-normal-user-on-linux. You can run it as a docker container as shown below
5 |
6 |
7 | ### Creating Containers
8 |
9 | - mvn clean package
10 | - docker run --publish 8200:80 in28min/aws-hello-world-rest-api:0.0.1-SNAPSHOT
11 |
12 | ```
13 | docker login
14 | docker push @@REPO@@/aws-hello-world-rest-api:0.0.1-SNAPSHOT
15 | ```
16 |
17 | ## Test URLs
18 |
19 | - http://localhost:8200/hello-world
20 |
21 | ```txt
22 | Hello World
23 | ```
24 |
25 | - http://localhost:8200/hello-world-bean
26 |
27 | ```json
28 | {"message":"Hello World - Changed"}
29 | ```
30 |
31 | - http://localhost:8200/hello-world/path-variable/in28minutes
32 |
33 | ```json
34 | {"message":"Hello World, in28minutes"}
35 | ```
36 |
37 |
--------------------------------------------------------------------------------
/01-hello-world-rest-api/src/main/java/com/in28minutes/rest/webservices/restfulwebservices/HelloWorldBean.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.rest.webservices.restfulwebservices;
2 |
3 | public class HelloWorldBean {
4 |
5 | private String message;
6 |
7 | public HelloWorldBean(String message) {
8 | this.message = message;
9 | }
10 |
11 | public String getMessage() {
12 | return message;
13 | }
14 |
15 | public void setMessage(String message) {
16 | this.message = message;
17 | }
18 |
19 | @Override
20 | public String toString() {
21 | return String.format("HelloWorldBean [message=%s]", message);
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/01-hello-world-rest-api/src/main/java/com/in28minutes/rest/webservices/restfulwebservices/HelloWorldController.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.rest.webservices.restfulwebservices;
2 |
3 | import org.springframework.web.bind.annotation.GetMapping;
4 | import org.springframework.web.bind.annotation.PathVariable;
5 | import org.springframework.web.bind.annotation.RestController;
6 |
7 | @RestController
8 | public class HelloWorldController {
9 |
10 | @GetMapping(path = "/hello-world")
11 | public String helloWorld() {
12 | return "Hello World";
13 | }
14 |
15 | @GetMapping(path = "/hello-world-bean")
16 | public HelloWorldBean helloWorldBean() {
17 | return new HelloWorldBean("Hello World - Changed");
18 | }
19 |
20 | @GetMapping(path = "/hello-world/path-variable/{name}")
21 | public HelloWorldBean helloWorldPathVariable(@PathVariable String name) {
22 | return new HelloWorldBean(String.format("Hello World, %s", name));
23 | }
24 | }
--------------------------------------------------------------------------------
/01-hello-world-rest-api/src/main/java/com/in28minutes/rest/webservices/restfulwebservices/RestfulWebServicesApplication.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.rest.webservices.restfulwebservices;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class RestfulWebServicesApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(RestfulWebServicesApplication.class, args);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/01-hello-world-rest-api/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.port=80
--------------------------------------------------------------------------------
/01-hello-world-rest-api/src/test/java/com/in28minutes/rest/webservices/restfulwebservices/RestfulWebServicesApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.rest.webservices.restfulwebservices;
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 RestfulWebServicesApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/02-spring-boot-simple-task/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jdk-alpine
2 | VOLUME /tmp
3 | EXPOSE 8000
4 | ADD target/*.jar app.jar
5 | ENV JAVA_OPTS=""
6 | ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]
--------------------------------------------------------------------------------
/02-spring-boot-simple-task/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.in28minutes.spring.basics
8 | 02-aws-simple-spring-task
9 | 1.0.0-RELEASE
10 | jar
11 |
12 | aws-simple-spring-task
13 | Demo project for Spring Boot
14 |
15 |
16 | org.springframework.boot
17 | spring-boot-starter-parent
18 | 2.0.0.RELEASE
19 |
20 |
21 |
22 |
23 | UTF-8
24 | UTF-8
25 | 1.8
26 |
27 |
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-starter
32 |
33 |
34 |
35 | org.springframework.boot
36 | spring-boot-starter-test
37 | test
38 |
39 |
40 |
41 |
42 |
43 |
44 | org.springframework.boot
45 | spring-boot-maven-plugin
46 |
47 |
48 |
49 | com.spotify
50 | dockerfile-maven-plugin
51 | 1.4.10
52 |
53 |
54 | default
55 |
56 | build
57 |
58 |
59 |
60 |
61 |
62 | in28min/${project.name}
63 | ${project.version}
64 | true
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | spring-snapshots
73 | Spring Snapshots
74 | https://repo.spring.io/snapshot
75 |
76 | true
77 |
78 |
79 |
80 | spring-milestones
81 | Spring Milestones
82 | https://repo.spring.io/milestone
83 |
84 | false
85 |
86 |
87 |
88 |
89 |
90 |
91 | spring-snapshots
92 | Spring Snapshots
93 | https://repo.spring.io/snapshot
94 |
95 | true
96 |
97 |
98 |
99 | spring-milestones
100 | Spring Milestones
101 | https://repo.spring.io/milestone
102 |
103 | false
104 |
105 |
106 |
107 |
108 |
109 |
--------------------------------------------------------------------------------
/02-spring-boot-simple-task/readme.md:
--------------------------------------------------------------------------------
1 | # Simple Spring Task
2 |
3 | Run `com.in28minutes.spring.simple.task.SpringSimpleTaskApplication` as a Java Application.
4 |
5 | Runs `com.in28minutes.spring.simple.task.TaskImpl.performTask()` at launch
6 |
7 | ### Creating Containers
8 |
9 | - mvn clean package
10 | - docker run in28min/aws-simple-spring-task:0.0.1-SNAPSHOT
11 |
12 | ```
13 | docker login
14 | docker push @@REPO@@/aws-simple-spring-task:0.0.1-SNAPSHOT
15 | ```
--------------------------------------------------------------------------------
/02-spring-boot-simple-task/src/main/java/com/in28minutes/spring/simple/task/EnvironmentConfigurationLogger.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.spring.simple.task;
2 |
3 | import java.util.Arrays;
4 | import java.util.stream.StreamSupport;
5 |
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 | import org.springframework.context.event.ContextRefreshedEvent;
9 | import org.springframework.context.event.EventListener;
10 | import org.springframework.core.env.AbstractEnvironment;
11 | import org.springframework.core.env.EnumerablePropertySource;
12 | import org.springframework.core.env.Environment;
13 | import org.springframework.core.env.MutablePropertySources;
14 | import org.springframework.stereotype.Component;
15 |
16 | @Component
17 | public class EnvironmentConfigurationLogger {
18 |
19 | private static final Logger LOGGER = LoggerFactory.getLogger(EnvironmentConfigurationLogger.class);
20 |
21 | @SuppressWarnings("rawtypes")
22 | @EventListener
23 | public void handleContextRefresh(ContextRefreshedEvent event) {
24 | final Environment environment = event.getApplicationContext().getEnvironment();
25 | LOGGER.info("====== Environment and configuration ======");
26 | LOGGER.info("Active profiles: {}", Arrays.toString(environment.getActiveProfiles()));
27 | final MutablePropertySources sources = ((AbstractEnvironment) environment).getPropertySources();
28 | StreamSupport.stream(sources.spliterator(), false).filter(ps -> ps instanceof EnumerablePropertySource)
29 | .map(ps -> ((EnumerablePropertySource) ps).getPropertyNames()).flatMap(Arrays::stream).distinct()
30 | .forEach(prop -> LOGGER.info("{}", prop));// environment.getProperty(prop)
31 | LOGGER.info("===========================================");
32 |
33 | // LOGGER.info(retrieveContainerMetadataInfo());
34 | }
35 |
36 | }
--------------------------------------------------------------------------------
/02-spring-boot-simple-task/src/main/java/com/in28minutes/spring/simple/task/SpringSimpleTaskApplication.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.spring.simple.task;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.context.ApplicationContext;
6 |
7 | @SpringBootApplication
8 | public class SpringSimpleTaskApplication {
9 | public static void main(String[] args) {
10 | ApplicationContext applicationContext = SpringApplication.run(SpringSimpleTaskApplication.class, args);
11 | TaskImpl task = applicationContext.getBean(TaskImpl.class);
12 | task.performTask();
13 | }
14 | }
--------------------------------------------------------------------------------
/02-spring-boot-simple-task/src/main/java/com/in28minutes/spring/simple/task/TaskImpl.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.spring.simple.task;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import org.springframework.stereotype.Component;
6 |
7 | @Component
8 | public class TaskImpl {
9 |
10 | private static final Logger LOGGER = LoggerFactory.getLogger(TaskImpl.class);
11 |
12 | public void performTask() {
13 | LOGGER.info("DO THE ONE TIME TASK HERE!");
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/02-spring-boot-simple-task/src/main/resources/application.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/in28minutes/deploy-spring-microservices-to-aws-ecs-fargate/2d6d655aeee2f237688387fe9d3f069fdaacd332/02-spring-boot-simple-task/src/main/resources/application.properties
--------------------------------------------------------------------------------
/02-spring-boot-simple-task/src/main/resources/log.txt:
--------------------------------------------------------------------------------
1 | Searching directory [/in28Minutes/git/getting-started-in-5-steps/spring-in-5-steps/target/classes/com/in28minutes/spring/basics/springin5steps] for files matching pattern [/in28Minutes/git/getting-started-in-5-steps/spring-in-5-steps/target/classes/com/in28minutes/spring/basics/springin5steps/**/*.class]
2 | Identified candidate component class: file [/in28Minutes/git/getting-started-in-5-steps/spring-in-5-steps/target/classes/com/in28minutes/spring/basics/springin5steps/BinarySearchImpl.class]
3 | Identified candidate component class: file [/in28Minutes/git/getting-started-in-5-steps/spring-in-5-steps/target/classes/com/in28minutes/spring/basics/springin5steps/BubbleSortAlgorithm.class]
4 |
5 | Creating instance of bean 'binarySearchImpl'
6 | Creating instance of bean 'bubbleSortAlgorithm'
7 | Finished creating instance of bean 'bubbleSortAlgorithm'
8 |
9 | Constuctor - Autowiring by type from bean name 'binarySearchImpl' via constructor
10 | to bean named 'bubbleSortAlgorithm'
11 | Setter - Autowiring by type from bean name 'binarySearchImpl' to bean named 'bubbleSortAlgorithm'
12 | No Setter or Constructor - Autowiring by type from bean name 'binarySearchImpl' to bean named 'bubbleSortAlgorithm'
13 |
14 |
15 | Finished creating instance of bean 'binarySearchImpl'
16 |
--------------------------------------------------------------------------------
/02-spring-boot-simple-task/src/test/java/com/in28minutes/spring/simple/task/SpringIn5StepsApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.spring.simple.task;
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 SpringIn5StepsApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/03-currency-exchange-service-h2/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jdk-alpine
2 | VOLUME /tmp
3 | EXPOSE 8000
4 | ADD target/*.jar app.jar
5 | ENV JAVA_OPTS=""
6 | ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]
--------------------------------------------------------------------------------
/03-currency-exchange-service-h2/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.in28minutes.microservices
8 | 03-aws-currency-exchange-service-h2
9 | 0.0.1-SNAPSHOT
10 | jar
11 |
12 | aws-currency-exchange-service-h2
13 | Demo project for Spring Boot
14 |
15 |
16 | org.springframework.boot
17 | spring-boot-starter-parent
18 | 2.1.1.RELEASE
19 |
20 |
21 |
22 |
23 | UTF-8
24 | UTF-8
25 | 1.8
26 | Greenwich.RC2
27 |
28 |
29 |
30 |
31 |
32 | org.springframework.boot
33 | spring-boot-starter-web
34 |
35 |
36 |
37 | org.springframework.boot
38 | spring-boot-starter-data-jpa
39 |
40 |
41 |
42 | org.springframework.cloud
43 | spring-cloud-starter-sleuth
44 |
45 |
46 |
47 | org.springframework.boot
48 | spring-boot-starter-actuator
49 |
50 |
51 |
52 | org.springframework.boot
53 | spring-boot-devtools
54 | runtime
55 |
56 |
57 |
58 | com.h2database
59 | h2
60 | runtime
61 |
62 |
63 |
64 | javax.xml.bind
65 | jaxb-api
66 |
67 |
68 | com.sun.xml.bind
69 | jaxb-impl
70 | 2.3.0
71 |
72 |
73 | org.glassfish.jaxb
74 | jaxb-runtime
75 |
76 |
77 | javax.activation
78 | activation
79 | 1.1.1
80 |
81 |
82 |
83 | org.springframework.boot
84 | spring-boot-starter-test
85 | test
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 | org.springframework.cloud
94 | spring-cloud-dependencies
95 | ${spring-cloud.version}
96 | pom
97 | import
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 | org.springframework.boot
106 | spring-boot-maven-plugin
107 |
108 |
109 |
110 | com.spotify
111 | dockerfile-maven-plugin
112 | 1.4.10
113 |
114 |
115 | default
116 |
117 | build
118 |
119 |
120 |
121 |
122 |
123 | in28min/${project.name}
124 | ${project.version}
125 | true
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 | spring-snapshots
134 | Spring Snapshots
135 | https://repo.spring.io/snapshot
136 |
137 | true
138 |
139 |
140 |
141 | spring-milestones
142 | Spring Milestones
143 | https://repo.spring.io/milestone
144 |
145 | false
146 |
147 |
148 |
149 |
150 |
151 |
152 | spring-snapshots
153 | Spring Snapshots
154 | https://repo.spring.io/snapshot
155 |
156 | true
157 |
158 |
159 |
160 | spring-milestones
161 | Spring Milestones
162 | https://repo.spring.io/milestone
163 |
164 | false
165 |
166 |
167 |
168 |
169 |
170 |
171 |
--------------------------------------------------------------------------------
/03-currency-exchange-service-h2/readme.md:
--------------------------------------------------------------------------------
1 | # Currency Exchange Micro Service - H2
2 |
3 | Run com.in28minutes.microservices.currencyconversionservice.CurrencyConversionServiceApplicationH2 as a Java Application.
4 |
5 | ## Containerization
6 |
7 | ### Troubleshooting
8 |
9 | - Problem - Caused by: com.spotify.docker.client.shaded.javax.ws.rs.ProcessingException: java.io.IOException: No such file or directory
10 | - Solution - Check if docker is up and running!
11 | - Problem - Error creating the Docker image on MacOS - java.io.IOException: Cannot run program “docker-credential-osxkeychain”: error=2, No such file or directory
12 | - Solution - https://medium.com/@dakshika/error-creating-the-docker-image-on-macos-wso2-enterprise-integrator-tooling-dfb5b537b44e
13 |
14 | ### Creating Container
15 |
16 | - mvn package
17 |
18 | ### Running Container
19 |
20 | #### Basic
21 | ```
22 | docker container run --publish 8000:8000 in28min/aws-currency-exchange-service-h2:0.0.1-SNAPSHOT
23 | ```
24 | #### Custom Network
25 | ```
26 | docker run --publish 8000:8000 --network currency-network --name=currency-exchange-service in28min/aws-currency-exchange-service-h2:0.0.1-SNAPSHOT
27 | ```
28 |
29 | Test API
30 | - http://localhost:8000/api/currency-exchange-microservice/currency-exchange/from/USD/to/INR
31 |
32 | ```
33 | docker login
34 | docker push @@@REPO_NAME@@@/aws-currency-exchange-service-h2:0.0.1-SNAPSHOT
35 | ```
36 |
37 | ## Resources
38 |
39 | - http://localhost:8000/api/currency-exchange-microservice/currency-exchange/from/USD/to/INR
40 |
41 | ```json
42 | {
43 | "id": 10001,
44 | "from": "USD",
45 | "to": "INR",
46 | "conversionMultiple": 65.00,
47 | "environmentInfo": "NA"
48 | }
49 | ```
50 |
51 | ## H2 Console
52 |
53 | - http://localhost:8000/api/currency-exchange-microservice/h2-console
54 | - Use `jdbc:h2:mem:testdb` as JDBC URL
55 |
56 |
57 | ## Tables Created
58 | ```
59 | create table exchange_value
60 | (
61 | id bigint not null,
62 | conversion_multiple decimal(19,2),
63 | currency_from varchar(255),
64 | currency_to varchar(255),
65 | primary key (id)
66 | )
67 | ```
68 |
--------------------------------------------------------------------------------
/03-currency-exchange-service-h2/src/main/java/com/in28minutes/microservices/currencyexchangeservice/CurrencyExchangeServiceApplicationH2.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyexchangeservice;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class CurrencyExchangeServiceApplicationH2 {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(CurrencyExchangeServiceApplicationH2.class, args);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/03-currency-exchange-service-h2/src/main/java/com/in28minutes/microservices/currencyexchangeservice/resource/CurrencyExchangeController.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyexchangeservice.resource;
2 |
3 | import java.util.Map;
4 |
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.web.bind.annotation.GetMapping;
9 | import org.springframework.web.bind.annotation.PathVariable;
10 | import org.springframework.web.bind.annotation.RequestHeader;
11 | import org.springframework.web.bind.annotation.RestController;
12 |
13 | import com.in28minutes.microservices.currencyexchangeservice.util.containerservice.ContainerMetaDataService;
14 |
15 | @RestController
16 | public class CurrencyExchangeController {
17 |
18 | private static final Logger LOGGER = LoggerFactory.getLogger(CurrencyExchangeController.class);
19 |
20 | @Autowired
21 | private ExchangeValueRepository repository;
22 |
23 | @Autowired
24 | private ContainerMetaDataService containerMetaDataService;
25 |
26 | @GetMapping("/currency-exchange/from/{from}/to/{to}")
27 | public ExchangeValue retrieveExchangeValue(@PathVariable String from, @PathVariable String to,
28 | @RequestHeader Map headers) {
29 |
30 | printAllHeaders(headers);
31 |
32 | ExchangeValue exchangeValue = repository.findByFromAndTo(from, to);
33 |
34 | LOGGER.info("{} {} {}", from, to, exchangeValue);
35 |
36 | if (exchangeValue == null) {
37 | throw new RuntimeException("Unable to find data to convert " + from + " to " + to);
38 | }
39 |
40 | exchangeValue.setExchangeEnvironmentInfo(containerMetaDataService.retrieveContainerMetadataInfo());
41 |
42 | return exchangeValue;
43 | }
44 |
45 | private void printAllHeaders(Map headers) {
46 | headers.forEach((key, value) -> {
47 | LOGGER.info(String.format("Header '%s' = %s", key, value));
48 | });
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/03-currency-exchange-service-h2/src/main/java/com/in28minutes/microservices/currencyexchangeservice/resource/ExchangeValue.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyexchangeservice.resource;
2 |
3 | import java.math.BigDecimal;
4 |
5 | import javax.persistence.Column;
6 | import javax.persistence.Entity;
7 | import javax.persistence.Id;
8 | import javax.persistence.Transient;
9 |
10 | @Entity
11 | public class ExchangeValue {
12 |
13 | @Id
14 | private Long id;
15 |
16 | @Column(name = "currency_from")
17 | private String from;
18 |
19 | @Column(name = "currency_to")
20 | private String to;
21 |
22 | private BigDecimal conversionMultiple;
23 |
24 | @Transient
25 | private String exchangeEnvironmentInfo;
26 |
27 | public ExchangeValue() {
28 |
29 | }
30 |
31 | public ExchangeValue(Long id, String from, String to, BigDecimal conversionMultiple) {
32 | super();
33 | this.id = id;
34 | this.from = from;
35 | this.to = to;
36 | this.conversionMultiple = conversionMultiple;
37 | }
38 |
39 | public Long getId() {
40 | return id;
41 | }
42 |
43 | public String getFrom() {
44 | return from;
45 | }
46 |
47 | public String getTo() {
48 | return to;
49 | }
50 |
51 | public BigDecimal getConversionMultiple() {
52 | return conversionMultiple;
53 | }
54 |
55 | public String getExchangeEnvironmentInfo() {
56 | return exchangeEnvironmentInfo;
57 | }
58 |
59 | public void setExchangeEnvironmentInfo(String environmentInfo) {
60 | this.exchangeEnvironmentInfo = environmentInfo;
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/03-currency-exchange-service-h2/src/main/java/com/in28minutes/microservices/currencyexchangeservice/resource/ExchangeValueRepository.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyexchangeservice.resource;
2 |
3 | import org.springframework.data.jpa.repository.JpaRepository;
4 |
5 | public interface ExchangeValueRepository extends JpaRepository {
6 | ExchangeValue findByFromAndTo(String from, String to);
7 | }
8 |
--------------------------------------------------------------------------------
/03-currency-exchange-service-h2/src/main/java/com/in28minutes/microservices/currencyexchangeservice/util/containerservice/ContainerMetaDataService.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyexchangeservice.util.containerservice;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import org.springframework.beans.factory.annotation.Value;
6 | import org.springframework.stereotype.Service;
7 | import org.springframework.web.client.RestTemplate;
8 |
9 | @Service
10 | public class ContainerMetaDataService {
11 |
12 | private static final String ENVIRONMENT_VARIABLE_ECS_CONTAINER_METADATA_URI = "ECS_CONTAINER_METADATA_URI";
13 |
14 | private static final String DEFAULT_VALUE = "EMPTY";
15 |
16 | private static final Logger LOGGER = LoggerFactory.getLogger(ContainerMetaDataService.class);
17 |
18 | // @Value(${ENVIRONMENT_VARIABLE_NAME:DEFAULT_VALUE})
19 | @Value("${" + ENVIRONMENT_VARIABLE_ECS_CONTAINER_METADATA_URI + ":" + DEFAULT_VALUE + "}")
20 | private String containerMetadataUri;
21 |
22 | public String retrieveContainerMetadataInfo() {
23 |
24 | if (containerMetadataUri.contains(DEFAULT_VALUE)) {
25 | LOGGER.info("Environment Variable Not Available - " + ENVIRONMENT_VARIABLE_ECS_CONTAINER_METADATA_URI);
26 | return "NA";
27 | }
28 |
29 | return new RestTemplate().getForObject(containerMetadataUri, String.class);
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/03-currency-exchange-service-h2/src/main/java/com/in28minutes/microservices/currencyexchangeservice/util/logging/EnvironmentConfigurationLogger.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyexchangeservice.util.logging;
2 |
3 | import java.util.Arrays;
4 | import java.util.stream.StreamSupport;
5 |
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 | import org.springframework.context.event.ContextRefreshedEvent;
9 | import org.springframework.context.event.EventListener;
10 | import org.springframework.core.env.AbstractEnvironment;
11 | import org.springframework.core.env.EnumerablePropertySource;
12 | import org.springframework.core.env.Environment;
13 | import org.springframework.core.env.MutablePropertySources;
14 | import org.springframework.stereotype.Component;
15 |
16 | @Component
17 | public class EnvironmentConfigurationLogger {
18 |
19 | private static final Logger LOGGER = LoggerFactory.getLogger(EnvironmentConfigurationLogger.class);
20 |
21 | @SuppressWarnings("rawtypes")
22 | @EventListener
23 | public void handleContextRefresh(ContextRefreshedEvent event) {
24 | final Environment environment = event.getApplicationContext().getEnvironment();
25 | LOGGER.info("====== Environment and configuration ======");
26 | LOGGER.info("Active profiles: {}", Arrays.toString(environment.getActiveProfiles()));
27 | final MutablePropertySources sources = ((AbstractEnvironment) environment).getPropertySources();
28 | StreamSupport.stream(sources.spliterator(), false).filter(ps -> ps instanceof EnumerablePropertySource)
29 | .map(ps -> ((EnumerablePropertySource) ps).getPropertyNames()).flatMap(Arrays::stream).distinct()
30 | .forEach(prop -> LOGGER.info("{}", prop));// environment.getProperty(prop)
31 | LOGGER.info("===========================================");
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/03-currency-exchange-service-h2/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.application.name=currency-exchange-microservice
2 | server.port=8000
3 |
4 | spring.jpa.show-sql=true
5 | spring.h2.console.enabled=true
6 |
7 | management.endpoints.web.base-path=/manage
8 | server.servlet.context-path=/api/currency-exchange-microservice
--------------------------------------------------------------------------------
/03-currency-exchange-service-h2/src/main/resources/data.sql:
--------------------------------------------------------------------------------
1 | insert into exchange_value(id,currency_from,currency_to,conversion_multiple)
2 | values(10001,'USD','INR',65);
3 | insert into exchange_value(id,currency_from,currency_to,conversion_multiple)
4 | values(10002,'EUR','INR',75);
5 | insert into exchange_value(id,currency_from,currency_to,conversion_multiple)
6 | values(10003,'AUD','INR',25);
--------------------------------------------------------------------------------
/03-currency-exchange-service-h2/src/test/java/com/in28minutes/microservices/currencyexchangeservice/CurrencyExchangeServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyexchangeservice;
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 CurrencyExchangeServiceApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/04-currency-exchange-service-mysql/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jdk-alpine
2 | VOLUME /tmp
3 | EXPOSE 8000
4 | ADD target/*.jar app.jar
5 | ENV JAVA_OPTS=""
6 | ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]
--------------------------------------------------------------------------------
/04-currency-exchange-service-mysql/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.in28minutes.microservices
8 | 04-aws-currency-exchange-service-mysql
9 | 0.0.1-SNAPSHOT
10 | jar
11 |
12 | aws-currency-exchange-service-mysql
13 | Demo project for Spring Boot
14 |
15 |
16 | org.springframework.boot
17 | spring-boot-starter-parent
18 | 2.1.1.RELEASE
19 |
20 |
21 |
22 |
23 | UTF-8
24 | UTF-8
25 | 1.8
26 | Greenwich.RC2
27 |
28 |
29 |
30 |
31 |
32 | org.springframework.boot
33 | spring-boot-starter-web
34 |
35 |
36 |
37 | org.springframework.boot
38 | spring-boot-starter-data-jpa
39 |
40 |
41 |
42 | org.springframework.cloud
43 | spring-cloud-starter-sleuth
44 |
45 |
46 |
47 | org.springframework.boot
48 | spring-boot-starter-actuator
49 |
50 |
51 |
52 | org.springframework.boot
53 | spring-boot-devtools
54 | runtime
55 |
56 |
57 |
58 | mysql
59 | mysql-connector-java
60 |
61 |
62 |
63 | com.h2database
64 | h2
65 | test
66 |
67 |
68 |
69 | javax.xml.bind
70 | jaxb-api
71 |
72 |
73 | com.sun.xml.bind
74 | jaxb-impl
75 | 2.3.0
76 |
77 |
78 | org.glassfish.jaxb
79 | jaxb-runtime
80 |
81 |
82 | javax.activation
83 | activation
84 | 1.1.1
85 |
86 |
87 |
88 | org.springframework.boot
89 | spring-boot-starter-test
90 | test
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 | org.springframework.cloud
99 | spring-cloud-dependencies
100 | ${spring-cloud.version}
101 | pom
102 | import
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 | org.springframework.boot
111 | spring-boot-maven-plugin
112 |
113 |
114 |
115 | com.spotify
116 | dockerfile-maven-plugin
117 | 1.4.10
118 |
119 |
120 | default
121 |
122 | build
123 |
124 |
125 |
126 |
127 |
128 | in28min/${project.name}
129 | ${project.version}
130 | true
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 | spring-snapshots
139 | Spring Snapshots
140 | https://repo.spring.io/snapshot
141 |
142 | true
143 |
144 |
145 |
146 | spring-milestones
147 | Spring Milestones
148 | https://repo.spring.io/milestone
149 |
150 | false
151 |
152 |
153 |
154 |
155 |
156 |
157 | spring-snapshots
158 | Spring Snapshots
159 | https://repo.spring.io/snapshot
160 |
161 | true
162 |
163 |
164 |
165 | spring-milestones
166 | Spring Milestones
167 | https://repo.spring.io/milestone
168 |
169 | false
170 |
171 |
172 |
173 |
174 |
175 |
176 |
--------------------------------------------------------------------------------
/04-currency-exchange-service-mysql/readme.md:
--------------------------------------------------------------------------------
1 | # Currency Exchange Micro Service - Mysql
2 |
3 | Run com.in28minutes.microservices.currencyconversionservice.CurrencyConversionServiceApplicationMySql as a Java Application.
4 |
5 | Application uses h2 database to run the tests.
6 |
7 | ## Changes from H2 Application
8 |
9 | #### pom.xml
10 |
11 | ```
12 |
13 | com.h2database
14 | h2
15 | test
16 |
17 |
18 |
19 | mysql
20 | mysql-connector-java
21 |
22 | ```
23 |
24 | #### src/main/resources/application.properties
25 |
26 | ```
27 | #spring.h2.console.enabled=true
28 | #spring.h2.console.settings.web-allow-others=true
29 |
30 | spring.jpa.hibernate.ddl-auto=update
31 | spring.datasource.url=jdbc:mysql://${RDS_HOSTNAME:localhost}:${RDS_PORT:3306}/${RDS_DB_NAME:exchange-db}
32 | spring.datasource.username=${RDS_USERNAME:exchange-db-user}
33 | spring.datasource.password=${RDS_PASSWORD:dummyexchange}
34 | spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
35 | ```
36 |
37 | #### src/test/resources/application.properties
38 |
39 | ```
40 | spring.jpa.hibernate.ddl-auto=create-drop
41 | spring.datasource.driver-class-name=org.h2.Driver
42 | spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1
43 | spring.datasource.username=sa
44 | spring.datasource.password=sa
45 | ```
46 |
47 | ## Dummy Data
48 |
49 | Removed data.sql
50 |
51 | ```
52 | long count = repository.count();
53 |
54 | if(count ==0) {
55 | repository.save(new ExchangeValue(10001L,"USD","INR", BigDecimal.valueOf(65)));
56 | repository.save(new ExchangeValue(10002L,"EUR","INR", BigDecimal.valueOf(75)));
57 | repository.save(new ExchangeValue(10003L,"AUD","INR", BigDecimal.valueOf(25)));
58 | }
59 | ```
60 |
61 | ## My SQL
62 |
63 | ### Launching MySQL using Docker
64 |
65 | ```
66 | docker run --detach --env MYSQL_ROOT_PASSWORD=dummypassword --env MYSQL_USER=exchange-db-user --env MYSQL_PASSWORD=dummyexchange --env MYSQL_DATABASE=exchange-db --name mysql --publish 3306:3306 mysql:5.7
67 | ```
68 |
69 |
70 | ### My SQL Shell Client
71 |
72 | - https://dev.mysql.com/downloads/shell/
73 |
74 | - Install on mac using `brew install caskroom/cask/mysql-shell`.
75 |
76 |
77 | ```
78 | Rangas-MacBook-Air:aws-projects in28min$ mysqlsh
79 | MySQL Shell 8.0.15
80 | Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
81 | Oracle is a registered trademark of Oracle Corporation and/or its affiliates.
82 | Other names may be trademarks of their respective owners.
83 |
84 | Type '\help' or '\?' for help; '\quit' to exit.
85 |
86 | MySQL JS > \connect todos-user@localhost:3306
87 | Creating a session to 'todos-user@localhost:3306'
88 | Please provide the password for 'todos-user@localhost:3306':
89 | Save password for 'todos-user@localhost:3306'? [Y]es/[N]o/Ne[v]er (default No): v
90 | Fetching schema names for autocompletion... Press ^C to stop.
91 | Your MySQL connection id is 37
92 | Server version: 5.7.26 MySQL Community Server (GPL)
93 | No default schema selected; type \use to set one.
94 |
95 | MySQL localhost:3306 ssl JS > \sql
96 | Switching to SQL mode... Commands end with ;
97 |
98 | MySQL localhost:3306 ssl SQL > use todos
99 | Default schema set to `todos`.
100 | Fetching table and column names from `todos` for auto-completion... Press ^C to stop.
101 |
102 | MySQL localhost:3306 ssl todos SQL > select * from todo ;
103 | +----+--------------+---------+----------------------------+-------------+
104 | | id | description | is_done | target_date | user |
105 | +----+--------------+---------+----------------------------+-------------+
106 | | 1 | Default Desc | 0 | 2019-06-26 18:30:00.000000 | in28minutes |
107 | +----+--------------+---------+----------------------------+-------------+
108 | 1 row in set (0.0032 sec)
109 |
110 | ```
111 |
112 | ## Containerization
113 |
114 | ### Troubleshooting
115 |
116 | - Problem - Caused by: com.spotify.docker.client.shaded.javax.ws.rs.ProcessingException: java.io.IOException: No such file or directory
117 | - Solution - Check if docker is up and running!
118 | - Problem - Error creating the Docker image on MacOS - java.io.IOException: Cannot run program “docker-credential-osxkeychain”: error=2, No such file or directory
119 | - Solution - https://medium.com/@dakshika/error-creating-the-docker-image-on-macos-wso2-enterprise-integrator-tooling-dfb5b537b44e
120 |
121 | ### Creating Containers
122 |
123 | - mvn package
124 | - docker run --publish 8000:8000 --network MY_BRIDGE --name currency-exchange-microservice in28min/aws-currency-exchange-service-mysql:0.0.1-SNAPSHOT
125 |
126 | Test API
127 | - http://localhost:8000/api/currency-exchange-microservice/currency-exchange/from/USD/to/INR
128 |
129 | ```
130 | docker login
131 | docker push @@@REPO_NAME@@@/aws-currency-exchange-service-mysql:0.0.1-SNAPSHOT
132 | ```
133 |
134 | ## Environment Variables
135 |
136 | SSM URN - arn:aws:ssm:us-east-1::parameter/
137 |
138 | - /dev/currency-exchange-service/RDS_DB_NAME - exchange_db
139 | - /dev/currency-exchange-service/RDS_HOSTNAME
140 | - /dev/currency-exchange-service/RDS_PASSWORD
141 | - /dev/currency-exchange-service/RDS_PORT - 3306
142 | - /dev/currency-exchange-service/RDS_USERNAME - exchange_db_user
143 |
144 |
145 |
146 | ## Resources
147 |
148 | - http://localhost:8000/api/currency-exchange-microservice/currency-exchange/from/USD/to/INR
149 |
150 | ```json
151 | {
152 | "id": 10001,
153 | "from": "USD",
154 | "to": "INR",
155 | "conversionMultiple": 65.00,
156 | "environmentInfo": "NA"
157 | }
158 | ```
159 |
160 | ## Tables Created
161 | ```
162 | create table exchange_value
163 | (
164 | id bigint not null,
165 | conversion_multiple decimal(19,2),
166 | currency_from varchar(255),
167 | currency_to varchar(255),
168 | primary key (id)
169 | )
170 | ```
171 |
--------------------------------------------------------------------------------
/04-currency-exchange-service-mysql/src/main/java/com/in28minutes/microservices/currencyexchangeservice/CurrencyExchangeServiceApplicationMySql.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyexchangeservice;
2 |
3 | import java.math.BigDecimal;
4 |
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.boot.CommandLineRunner;
7 | import org.springframework.boot.SpringApplication;
8 | import org.springframework.boot.autoconfigure.SpringBootApplication;
9 |
10 | import com.in28minutes.microservices.currencyexchangeservice.resource.ExchangeValue;
11 | import com.in28minutes.microservices.currencyexchangeservice.resource.ExchangeValueRepository;
12 |
13 | @SpringBootApplication
14 | public class CurrencyExchangeServiceApplicationMySql implements CommandLineRunner {
15 |
16 | @Autowired
17 | ExchangeValueRepository repository;
18 |
19 | public static void main(String[] args) {
20 | SpringApplication.run(CurrencyExchangeServiceApplicationMySql.class, args);
21 | }
22 |
23 | @Override
24 | public void run(String... args) throws Exception {
25 |
26 | long count = repository.count();
27 |
28 | if (count == 0) {
29 | repository.save(new ExchangeValue(10001L, "USD", "INR", BigDecimal.valueOf(60)));
30 | repository.save(new ExchangeValue(10002L, "EUR", "INR", BigDecimal.valueOf(70)));
31 | repository.save(new ExchangeValue(10003L, "AUD", "INR", BigDecimal.valueOf(20)));
32 | }
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/04-currency-exchange-service-mysql/src/main/java/com/in28minutes/microservices/currencyexchangeservice/resource/CurrencyExchangeController.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyexchangeservice.resource;
2 |
3 | import java.util.Map;
4 |
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.web.bind.annotation.GetMapping;
9 | import org.springframework.web.bind.annotation.PathVariable;
10 | import org.springframework.web.bind.annotation.RequestHeader;
11 | import org.springframework.web.bind.annotation.RestController;
12 |
13 | import com.in28minutes.microservices.currencyexchangeservice.util.containerservice.ContainerMetaDataService;
14 |
15 | @RestController
16 | public class CurrencyExchangeController {
17 |
18 | private static final Logger LOGGER = LoggerFactory.getLogger(CurrencyExchangeController.class);
19 |
20 | @Autowired
21 | private ExchangeValueRepository repository;
22 |
23 | @Autowired
24 | private ContainerMetaDataService containerMetaDataService;
25 |
26 | @GetMapping("/currency-exchange/from/{from}/to/{to}")
27 | public ExchangeValue retrieveExchangeValue(@PathVariable String from, @PathVariable String to,
28 | @RequestHeader Map headers) {
29 |
30 | printAllHeaders(headers);
31 |
32 | ExchangeValue exchangeValue = repository.findByFromAndTo(from, to);
33 |
34 | LOGGER.info("{} {} {}", from, to, exchangeValue);
35 |
36 | if (exchangeValue == null) {
37 | throw new RuntimeException("Unable to find data to convert " + from + " to " + to);
38 | }
39 |
40 | exchangeValue.setExchangeEnvironmentInfo(containerMetaDataService.retrieveContainerMetadataInfo());
41 |
42 | return exchangeValue;
43 | }
44 |
45 | private void printAllHeaders(Map headers) {
46 | headers.forEach((key, value) -> {
47 | LOGGER.info(String.format("Header '%s' = %s", key, value));
48 | });
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/04-currency-exchange-service-mysql/src/main/java/com/in28minutes/microservices/currencyexchangeservice/resource/ExchangeValue.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyexchangeservice.resource;
2 |
3 | import java.math.BigDecimal;
4 |
5 | import javax.persistence.Column;
6 | import javax.persistence.Entity;
7 | import javax.persistence.Id;
8 | import javax.persistence.Transient;
9 |
10 | @Entity
11 | public class ExchangeValue {
12 |
13 | @Id
14 | private Long id;
15 |
16 | @Column(name = "currency_from")
17 | private String from;
18 |
19 | @Column(name = "currency_to")
20 | private String to;
21 |
22 | private BigDecimal conversionMultiple;
23 |
24 | @Transient
25 | private String exchangeEnvironmentInfo;
26 |
27 | public ExchangeValue() {
28 |
29 | }
30 |
31 | public ExchangeValue(Long id, String from, String to, BigDecimal conversionMultiple) {
32 | super();
33 | this.id = id;
34 | this.from = from;
35 | this.to = to;
36 | this.conversionMultiple = conversionMultiple;
37 | }
38 |
39 | public Long getId() {
40 | return id;
41 | }
42 |
43 | public String getFrom() {
44 | return from;
45 | }
46 |
47 | public String getTo() {
48 | return to;
49 | }
50 |
51 | public BigDecimal getConversionMultiple() {
52 | return conversionMultiple;
53 | }
54 |
55 | public String getExchangeEnvironmentInfo() {
56 | return exchangeEnvironmentInfo;
57 | }
58 |
59 | public void setExchangeEnvironmentInfo(String environmentInfo) {
60 | this.exchangeEnvironmentInfo = environmentInfo;
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/04-currency-exchange-service-mysql/src/main/java/com/in28minutes/microservices/currencyexchangeservice/resource/ExchangeValueRepository.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyexchangeservice.resource;
2 |
3 | import org.springframework.data.jpa.repository.JpaRepository;
4 |
5 | public interface ExchangeValueRepository extends JpaRepository {
6 | ExchangeValue findByFromAndTo(String from, String to);
7 | }
8 |
--------------------------------------------------------------------------------
/04-currency-exchange-service-mysql/src/main/java/com/in28minutes/microservices/currencyexchangeservice/util/containerservice/ContainerMetaDataService.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyexchangeservice.util.containerservice;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import org.springframework.beans.factory.annotation.Value;
6 | import org.springframework.stereotype.Service;
7 | import org.springframework.web.client.RestTemplate;
8 |
9 | @Service
10 | public class ContainerMetaDataService {
11 |
12 | private static final String ENVIRONMENT_VARIABLE_ECS_CONTAINER_METADATA_URI = "ECS_CONTAINER_METADATA_URI";
13 |
14 | private static final String DEFAULT_VALUE = "EMPTY";
15 |
16 | private static final Logger LOGGER = LoggerFactory.getLogger(ContainerMetaDataService.class);
17 |
18 | // @Value(${ENVIRONMENT_VARIABLE_NAME:DEFAULT_VALUE})
19 | @Value("${" + ENVIRONMENT_VARIABLE_ECS_CONTAINER_METADATA_URI + ":" + DEFAULT_VALUE + "}")
20 | private String containerMetadataUri;
21 |
22 | public String retrieveContainerMetadataInfo() {
23 |
24 | if (containerMetadataUri.contains(DEFAULT_VALUE)) {
25 | LOGGER.info("Environment Variable Not Available - " + ENVIRONMENT_VARIABLE_ECS_CONTAINER_METADATA_URI);
26 | return "NA";
27 | }
28 |
29 | return new RestTemplate().getForObject(containerMetadataUri, String.class);
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/04-currency-exchange-service-mysql/src/main/java/com/in28minutes/microservices/currencyexchangeservice/util/logging/EnvironmentConfigurationLogger.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyexchangeservice.util.logging;
2 |
3 | import java.util.Arrays;
4 | import java.util.stream.StreamSupport;
5 |
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 | import org.springframework.context.event.ContextRefreshedEvent;
9 | import org.springframework.context.event.EventListener;
10 | import org.springframework.core.env.AbstractEnvironment;
11 | import org.springframework.core.env.EnumerablePropertySource;
12 | import org.springframework.core.env.Environment;
13 | import org.springframework.core.env.MutablePropertySources;
14 | import org.springframework.stereotype.Component;
15 |
16 | @Component
17 | public class EnvironmentConfigurationLogger {
18 |
19 | private static final Logger LOGGER = LoggerFactory.getLogger(EnvironmentConfigurationLogger.class);
20 |
21 | @SuppressWarnings("rawtypes")
22 | @EventListener
23 | public void handleContextRefresh(ContextRefreshedEvent event) {
24 | final Environment environment = event.getApplicationContext().getEnvironment();
25 | LOGGER.info("====== Environment and configuration ======");
26 | LOGGER.info("Active profiles: {}", Arrays.toString(environment.getActiveProfiles()));
27 | final MutablePropertySources sources = ((AbstractEnvironment) environment).getPropertySources();
28 | StreamSupport.stream(sources.spliterator(), false).filter(ps -> ps instanceof EnumerablePropertySource)
29 | .map(ps -> ((EnumerablePropertySource) ps).getPropertyNames()).flatMap(Arrays::stream).distinct()
30 | .forEach(prop -> LOGGER.info("{}", prop));// environment.getProperty(prop)
31 | LOGGER.info("===========================================");
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/04-currency-exchange-service-mysql/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.application.name=currency-exchange-microservice
2 | server.port=8000
3 |
4 | spring.jpa.show-sql=true
5 | #spring.h2.console.enabled=true
6 | #spring.h2.console.settings.web-allow-others=true
7 |
8 | management.endpoints.web.base-path=/manage
9 | server.servlet.context-path=/api/currency-exchange-microservice
10 |
11 | spring.jpa.hibernate.ddl-auto=update
12 | spring.datasource.url=jdbc:mysql://${RDS_HOSTNAME:localhost}:${RDS_PORT:3306}/${RDS_DB_NAME:exchange-db}
13 | spring.datasource.username=${RDS_USERNAME:exchange-db-user}
14 | spring.datasource.password=${RDS_PASSWORD:dummyexchange}
15 | spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
--------------------------------------------------------------------------------
/04-currency-exchange-service-mysql/src/test/java/com/in28minutes/microservices/currencyexchangeservice/CurrencyExchangeServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyexchangeservice;
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 CurrencyExchangeServiceApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/04-currency-exchange-service-mysql/src/test/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.jpa.hibernate.ddl-auto=create-drop
2 | spring.datasource.driver-class-name=org.h2.Driver
3 | spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1
4 | spring.datasource.username=sa
5 | spring.datasource.password=sa
--------------------------------------------------------------------------------
/05-currency-conversion-service/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jdk-alpine
2 | VOLUME /tmp
3 | EXPOSE 8100
4 | ADD target/*.jar app.jar
5 | ENV JAVA_OPTS=""
6 | ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]
--------------------------------------------------------------------------------
/05-currency-conversion-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.in28minutes.microservices
8 | 05-aws-currency-conversion-service
9 | 0.0.1-SNAPSHOT
10 | jar
11 |
12 | aws-currency-conversion-service
13 | Demo project for Spring Boot
14 |
15 |
16 | org.springframework.boot
17 | spring-boot-starter-parent
18 | 2.1.1.RELEASE
19 |
20 |
21 |
22 |
23 | UTF-8
24 | UTF-8
25 | 1.8
26 | Greenwich.RC2
27 |
28 |
29 |
30 |
31 |
32 | org.springframework.boot
33 | spring-boot-starter-web
34 |
35 |
36 |
37 | org.springframework.boot
38 | spring-boot-starter-data-jpa
39 |
40 |
41 | com.h2database
42 | h2
43 | runtime
44 |
45 |
46 |
47 |
48 | org.springframework.cloud
49 | spring-cloud-starter-sleuth
50 |
51 |
52 |
53 | org.springframework.boot
54 | spring-boot-starter-actuator
55 |
56 |
57 |
58 |
59 | org.springframework.boot
60 | spring-boot-devtools
61 | runtime
62 |
63 |
64 |
65 | javax.xml.bind
66 | jaxb-api
67 |
68 |
69 | com.sun.xml.bind
70 | jaxb-impl
71 | 2.3.0
72 |
73 |
74 | org.glassfish.jaxb
75 | jaxb-runtime
76 |
77 |
78 | javax.activation
79 | activation
80 | 1.1.1
81 |
82 |
83 |
84 |
85 | org.springframework.boot
86 | spring-boot-starter-test
87 | test
88 |
89 |
90 |
91 |
92 |
93 |
94 | org.springframework.cloud
95 | spring-cloud-dependencies
96 | ${spring-cloud.version}
97 | pom
98 | import
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | org.springframework.boot
107 | spring-boot-maven-plugin
108 |
109 |
110 |
111 | com.spotify
112 | dockerfile-maven-plugin
113 | 1.4.10
114 |
115 |
116 | default
117 |
118 | build
119 |
120 |
121 |
122 |
123 |
124 | in28min/${project.name}
125 | ${project.version}
126 | true
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 | spring-snapshots
135 | Spring Snapshots
136 | https://repo.spring.io/snapshot
137 |
138 | true
139 |
140 |
141 |
142 | spring-milestones
143 | Spring Milestones
144 | https://repo.spring.io/milestone
145 |
146 | false
147 |
148 |
149 |
150 |
151 |
152 |
153 | spring-snapshots
154 | Spring Snapshots
155 | https://repo.spring.io/snapshot
156 |
157 | true
158 |
159 |
160 |
161 | spring-milestones
162 | Spring Milestones
163 | https://repo.spring.io/milestone
164 |
165 | false
166 |
167 |
168 |
169 |
170 |
--------------------------------------------------------------------------------
/05-currency-conversion-service/readme.md:
--------------------------------------------------------------------------------
1 | # Currency Conversion Micro Service
2 |
3 | Run com.in28minutes.microservices.currencyconversionservice.CurrencyConversionServiceApplication as a Java Application.
4 |
5 | ## Containerization
6 |
7 | ### Troubleshooting
8 |
9 | - Problem - Caused by: com.spotify.docker.client.shaded.javax.ws.rs.ProcessingException: java.io.IOException: No such file or directory
10 | - Solution - Check if docker is up and running!
11 | - Problem - Error creating the Docker image on MacOS - java.io.IOException: Cannot run program “docker-credential-osxkeychain”: error=2, No such file or directory
12 | - Solution - https://medium.com/@dakshika/error-creating-the-docker-image-on-macos-wso2-enterprise-integrator-tooling-dfb5b537b44e
13 |
14 | ### Creating Containers
15 |
16 | - mvn package
17 |
18 | ### Running Containers
19 |
20 | ```
21 | docker run --publish 8100:8100 --network currency-network --env CURRENCY_EXCHANGE_URI=http://currency-exchange-service:8000 in28min/aws-currency-conversion-service:0.0.1-SNAPSHOT
22 | ```
23 |
24 | #### Test API
25 | - http://localhost:8100/api/currency-conversion-microservice/currency-converter/from/EUR/to/INR/quantity/10
26 | ```
27 | docker login
28 | docker push @@@REPO_NAME@@@/aws-currency-conversion-service:0.0.1-SNAPSHOT
29 | ```
30 |
31 |
32 | ## Resources
33 |
34 | - http://localhost:8100/api/currency-conversion-microservice/currency-converter/from/EUR/to/INR/quantity/10
35 |
36 | ```json
37 | {
38 | id: 10002,
39 | from: "EUR",
40 | to: "INR",
41 | conversionMultiple: 75,
42 | quantity: 10,
43 | totalCalculatedAmount: 750,
44 | exchangeEnvironmentInfo: "NA",
45 | conversionEnvironmentInfo: "NA",
46 | }
47 | ```
--------------------------------------------------------------------------------
/05-currency-conversion-service/src/main/java/com/in28minutes/microservices/currencyconversionservice/CurrencyConversionServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyconversionservice;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.web.client.RestTemplate;
7 |
8 | @SpringBootApplication
9 | public class CurrencyConversionServiceApplication {
10 |
11 | public static void main(String[] args) {
12 | SpringApplication.run(CurrencyConversionServiceApplication.class, args);
13 | }
14 |
15 | // Spring Cloud Sleuth uses request headers to propagate trace-id & span-id.
16 | // Creating a bean for RestTemplate allows Spring Cloud Sleuth to inject the
17 | // headers into RestTemplate.
18 |
19 | @Bean
20 | public RestTemplate getRestTemplate() {
21 | return new RestTemplate();
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/05-currency-conversion-service/src/main/java/com/in28minutes/microservices/currencyconversionservice/resource/CurrencyConversionBean.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyconversionservice.resource;
2 |
3 | import java.math.BigDecimal;
4 |
5 | public class CurrencyConversionBean {
6 |
7 | private Long id;
8 |
9 | private String from;
10 |
11 | private String to;
12 |
13 | private BigDecimal conversionMultiple;
14 |
15 | private BigDecimal quantity;
16 |
17 | private BigDecimal totalCalculatedAmount;
18 |
19 | private String exchangeEnvironmentInfo;
20 |
21 | private String conversionEnvironmentInfo;
22 |
23 | public CurrencyConversionBean() {
24 |
25 | }
26 |
27 | public CurrencyConversionBean(Long id, String from, String to, BigDecimal conversionMultiple, BigDecimal quantity,
28 | BigDecimal totalCalculatedAmount, String exchangeEnvironmentInfo, String conversionEnvironmentInfo) {
29 | super();
30 | this.id = id;
31 | this.from = from;
32 | this.to = to;
33 | this.conversionMultiple = conversionMultiple;
34 | this.quantity = quantity;
35 | this.totalCalculatedAmount = totalCalculatedAmount;
36 | this.exchangeEnvironmentInfo = exchangeEnvironmentInfo;
37 | this.conversionEnvironmentInfo = conversionEnvironmentInfo;
38 | }
39 |
40 | public Long getId() {
41 | return id;
42 | }
43 |
44 | public void setId(Long id) {
45 | this.id = id;
46 | }
47 |
48 | public String getFrom() {
49 | return from;
50 | }
51 |
52 | public void setFrom(String from) {
53 | this.from = from;
54 | }
55 |
56 | public String getTo() {
57 | return to;
58 | }
59 |
60 | public void setTo(String to) {
61 | this.to = to;
62 | }
63 |
64 | public BigDecimal getConversionMultiple() {
65 | return conversionMultiple;
66 | }
67 |
68 | public void setConversionMultiple(BigDecimal conversionMultiple) {
69 | this.conversionMultiple = conversionMultiple;
70 | }
71 |
72 | public BigDecimal getQuantity() {
73 | return quantity;
74 | }
75 |
76 | public void setQuantity(BigDecimal quantity) {
77 | this.quantity = quantity;
78 | }
79 |
80 | public BigDecimal getTotalCalculatedAmount() {
81 | return totalCalculatedAmount;
82 | }
83 |
84 | public void setTotalCalculatedAmount(BigDecimal totalCalculatedAmount) {
85 | this.totalCalculatedAmount = totalCalculatedAmount;
86 | }
87 |
88 | public String getExchangeEnvironmentInfo() {
89 | return exchangeEnvironmentInfo;
90 | }
91 |
92 | public void setExchangeEnvironmentInfo(String environmentInfo) {
93 | this.exchangeEnvironmentInfo = environmentInfo;
94 | }
95 |
96 | public String getConversionEnvironmentInfo() {
97 | return conversionEnvironmentInfo;
98 | }
99 |
100 | public void setConversionEnvironmentInfo(String conversionEnvironmentInfo) {
101 | this.conversionEnvironmentInfo = conversionEnvironmentInfo;
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/05-currency-conversion-service/src/main/java/com/in28minutes/microservices/currencyconversionservice/resource/CurrencyConversionController.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyconversionservice.resource;
2 |
3 | import java.math.BigDecimal;
4 | import java.util.HashMap;
5 | import java.util.Map;
6 |
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.beans.factory.annotation.Value;
11 | import org.springframework.http.ResponseEntity;
12 | import org.springframework.web.bind.annotation.GetMapping;
13 | import org.springframework.web.bind.annotation.PathVariable;
14 | import org.springframework.web.bind.annotation.RestController;
15 | import org.springframework.web.client.RestTemplate;
16 |
17 | import com.in28minutes.microservices.currencyconversionservice.util.containerservice.ContainerMetaDataService;
18 |
19 | @RestController
20 | public class CurrencyConversionController {
21 |
22 | private static final Logger LOGGER = LoggerFactory.getLogger(CurrencyConversionController.class);
23 |
24 | @Autowired
25 | private ContainerMetaDataService containerMetaDataService;
26 |
27 | @Value("${CURRENCY_EXCHANGE_URI:http://localhost:8000}")
28 | private String currencyExchangeHost;
29 |
30 | @Autowired
31 | private RestTemplate restTemplate;
32 |
33 | @GetMapping("/currency-converter/from/{from}/to/{to}/quantity/{quantity}")
34 | public CurrencyConversionBean convertCurrency(@PathVariable String from, @PathVariable String to,
35 | @PathVariable BigDecimal quantity) {
36 |
37 | LOGGER.info("Received Request to convert from {} {} to {} ", quantity, from, to);
38 |
39 | ResponseEntity responseEntity = restTemplate.getForEntity(
40 | currencyExchangeHost + "/api/currency-exchange-microservice/currency-exchange/from/{from}/to/{to}",
41 | CurrencyConversionBean.class, createUriVariables(from, to));
42 |
43 | CurrencyConversionBean response = responseEntity.getBody();
44 |
45 | BigDecimal convertedValue = quantity.multiply(response.getConversionMultiple());
46 |
47 | String conversionEnvironmentInfo = containerMetaDataService.retrieveContainerMetadataInfo();
48 |
49 | return new CurrencyConversionBean(response.getId(), from, to, response.getConversionMultiple(), quantity,
50 | convertedValue, response.getExchangeEnvironmentInfo(), conversionEnvironmentInfo);
51 | }
52 |
53 | private Map createUriVariables(String from, String to) {
54 | Map uriVariables = new HashMap<>();
55 | uriVariables.put("from", from);
56 | uriVariables.put("to", to);
57 | return uriVariables;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/05-currency-conversion-service/src/main/java/com/in28minutes/microservices/currencyconversionservice/util/containerservice/ContainerMetaDataService.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyconversionservice.util.containerservice;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import org.springframework.beans.factory.annotation.Value;
6 | import org.springframework.stereotype.Service;
7 | import org.springframework.web.client.RestTemplate;
8 |
9 | @Service
10 | public class ContainerMetaDataService {
11 |
12 | private static final String ENVIRONMENT_VARIABLE_ECS_CONTAINER_METADATA_URI = "ECS_CONTAINER_METADATA_URI";
13 |
14 | private static final String DEFAULT_VALUE = "EMPTY";
15 |
16 | private static final Logger LOGGER = LoggerFactory.getLogger(ContainerMetaDataService.class);
17 |
18 | // @Value(${ENVIRONMENT_VARIABLE_NAME:DEFAULT_VALUE})
19 | @Value("${" + ENVIRONMENT_VARIABLE_ECS_CONTAINER_METADATA_URI + ":" + DEFAULT_VALUE + "}")
20 | private String containerMetadataUri;
21 |
22 | public String retrieveContainerMetadataInfo() {
23 |
24 | if (containerMetadataUri.contains(DEFAULT_VALUE)) {
25 | LOGGER.info("Environment Variable Not Available - " + ENVIRONMENT_VARIABLE_ECS_CONTAINER_METADATA_URI);
26 | return "NA";
27 | }
28 |
29 | return new RestTemplate().getForObject(containerMetadataUri, String.class);
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/05-currency-conversion-service/src/main/java/com/in28minutes/microservices/currencyconversionservice/util/logging/EnvironmentConfigurationLogger.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyconversionservice.util.logging;
2 |
3 | import java.util.Arrays;
4 | import java.util.stream.StreamSupport;
5 |
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 | import org.springframework.context.event.ContextRefreshedEvent;
9 | import org.springframework.context.event.EventListener;
10 | import org.springframework.core.env.AbstractEnvironment;
11 | import org.springframework.core.env.EnumerablePropertySource;
12 | import org.springframework.core.env.Environment;
13 | import org.springframework.core.env.MutablePropertySources;
14 | import org.springframework.stereotype.Component;
15 |
16 | @Component
17 | public class EnvironmentConfigurationLogger {
18 |
19 | private static final Logger LOGGER = LoggerFactory.getLogger(EnvironmentConfigurationLogger.class);
20 |
21 | @SuppressWarnings("rawtypes")
22 | @EventListener
23 | public void handleContextRefresh(ContextRefreshedEvent event) {
24 | final Environment environment = event.getApplicationContext().getEnvironment();
25 | LOGGER.info("====== Environment and configuration ======");
26 | LOGGER.info("Active profiles: {}", Arrays.toString(environment.getActiveProfiles()));
27 | final MutablePropertySources sources = ((AbstractEnvironment) environment).getPropertySources();
28 | StreamSupport.stream(sources.spliterator(), false).filter(ps -> ps instanceof EnumerablePropertySource)
29 | .map(ps -> ((EnumerablePropertySource) ps).getPropertyNames()).flatMap(Arrays::stream).distinct()
30 | .forEach(prop -> LOGGER.info("{}", prop));// environment.getProperty(prop)
31 | LOGGER.info("===========================================");
32 | }
33 | }
--------------------------------------------------------------------------------
/05-currency-conversion-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.application.name=currency-conversion-microservice
2 | server.port=8100
3 |
4 | management.endpoints.web.base-path=/manage
5 | server.servlet.context-path=/api/currency-conversion-microservice
--------------------------------------------------------------------------------
/05-currency-conversion-service/src/test/java/com/in28minutes/microservices/currencyconversionservice/CurrencyConversionServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyconversionservice;
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 CurrencyConversionServiceApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/06-currency-exchange-service-h2-xray/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jdk-alpine
2 | VOLUME /tmp
3 | EXPOSE 8000
4 | ADD target/*.jar app.jar
5 | ENV JAVA_OPTS=""
6 | ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]
--------------------------------------------------------------------------------
/06-currency-exchange-service-h2-xray/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.in28minutes.microservices
8 | 06-aws-currency-exchange-service-h2-xray
9 | 0.0.1-SNAPSHOT
10 | jar
11 |
12 | aws-currency-exchange-service-h2-xray
13 | Demo project for Spring Boot
14 |
15 |
16 | org.springframework.boot
17 | spring-boot-starter-parent
18 | 2.1.1.RELEASE
19 |
20 |
21 |
22 |
23 | UTF-8
24 | UTF-8
25 | 1.8
26 | Greenwich.RC2
27 |
28 |
29 |
30 |
31 |
32 | org.springframework.boot
33 | spring-boot-starter-web
34 |
35 |
36 |
37 | org.springframework.boot
38 | spring-boot-starter-data-jpa
39 |
40 |
41 |
42 | org.springframework.cloud
43 | spring-cloud-starter-sleuth
44 |
45 |
46 |
47 | org.springframework.boot
48 | spring-boot-starter-actuator
49 |
50 |
51 |
52 | org.springframework.boot
53 | spring-boot-devtools
54 | runtime
55 |
56 |
57 |
58 | com.h2database
59 | h2
60 | runtime
61 |
62 |
63 |
64 | com.amazonaws
65 | aws-xray-recorder-sdk-spring
66 | 2.3.0
67 |
68 |
69 |
70 | javax.xml.bind
71 | jaxb-api
72 |
73 |
74 | com.sun.xml.bind
75 | jaxb-impl
76 | 2.3.0
77 |
78 |
79 | org.glassfish.jaxb
80 | jaxb-runtime
81 |
82 |
83 | javax.activation
84 | activation
85 | 1.1.1
86 |
87 |
88 |
89 | org.springframework.boot
90 | spring-boot-starter-test
91 | test
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | org.springframework.cloud
100 | spring-cloud-dependencies
101 | ${spring-cloud.version}
102 | pom
103 | import
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 | org.springframework.boot
112 | spring-boot-maven-plugin
113 |
114 |
115 |
116 | com.spotify
117 | dockerfile-maven-plugin
118 | 1.4.10
119 |
120 |
121 | default
122 |
123 | build
124 |
125 |
126 |
127 |
128 |
129 | in28min/${project.name}
130 | ${project.version}
131 | true
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 | spring-snapshots
140 | Spring Snapshots
141 | https://repo.spring.io/snapshot
142 |
143 | true
144 |
145 |
146 |
147 | spring-milestones
148 | Spring Milestones
149 | https://repo.spring.io/milestone
150 |
151 | false
152 |
153 |
154 |
155 |
156 |
157 |
158 | spring-snapshots
159 | Spring Snapshots
160 | https://repo.spring.io/snapshot
161 |
162 | true
163 |
164 |
165 |
166 | spring-milestones
167 | Spring Milestones
168 | https://repo.spring.io/milestone
169 |
170 | false
171 |
172 |
173 |
174 |
175 |
176 |
177 |
--------------------------------------------------------------------------------
/06-currency-exchange-service-h2-xray/readme.md:
--------------------------------------------------------------------------------
1 | # Currency Exchange Micro Service - H2 with XRay
2 |
3 | Run com.in28minutes.microservices.currencyconversionservice.CurrencyConversionServiceApplicationH2 as a Java Application.
4 |
5 |
6 | ## Changes from H2 Application
7 |
8 | - pom.xml - aws-xray-recorder-sdk-spring
9 | - AwsXrayConfig.java
10 | - XRayInspector.java
11 | - CurrencyExchangeController.java
12 |
13 | ```
14 | @RestController
15 | @XRayEnabled
16 | public class CurrencyExchangeController {
17 | ```
18 |
19 | ## XRay Daemon
20 |
21 | - amazon/aws-xray-daemon:1
22 |
23 |
24 | ## Containerization
25 |
26 | ### Troubleshooting
27 |
28 | - Problem - Caused by: com.spotify.docker.client.shaded.javax.ws.rs.ProcessingException: java.io.IOException: No such file or directory
29 | - Solution - Check if docker is up and running!
30 | - Problem - Error creating the Docker image on MacOS - java.io.IOException: Cannot run program “docker-credential-osxkeychain”: error=2, No such file or directory
31 | - Solution - https://medium.com/@dakshika/error-creating-the-docker-image-on-macos-wso2-enterprise-integrator-tooling-dfb5b537b44e
32 |
33 | ### Running Containers
34 |
35 | - mvn package
36 | - docker run --publish 8000:8000 --network MY_BRIDGE --name currency-exchange-microservice in28min/aws-currency-exchange-service-h2-xray:0.0.1-SNAPSHOT
37 |
38 | Test API
39 | - http://localhost:8000/api/currency-exchange-microservice/currency-exchange/from/USD/to/INR
40 |
41 | ```
42 | docker login
43 | docker push @@@REPO_NAME@@@/aws-currency-exchange-service-h2-xray:0.0.1-SNAPSHOT
44 | ```
45 |
46 | ## Resources
47 |
48 | - http://localhost:8000/api/currency-exchange-microservice/currency-exchange/from/USD/to/INR
49 |
50 | ```json
51 | {
52 | "id": 10001,
53 | "from": "USD",
54 | "to": "INR",
55 | "conversionMultiple": 65.00,
56 | "environmentInfo": "NA"
57 | }
58 | ```
59 |
60 | ## H2 Console
61 |
62 | - http://localhost:8000/h2-console
63 | - Use `jdbc:h2:mem:testdb` as JDBC URL
64 |
65 |
66 | ## Tables Created
67 | ```
68 | create table exchange_value
69 | (
70 | id bigint not null,
71 | conversion_multiple decimal(19,2),
72 | currency_from varchar(255),
73 | currency_to varchar(255),
74 | primary key (id)
75 | )
76 | ```
77 |
--------------------------------------------------------------------------------
/06-currency-exchange-service-h2-xray/src/main/java/com/in28minutes/microservices/currencyexchangeservice/CurrencyExchangeServiceApplicationH2.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyexchangeservice;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class CurrencyExchangeServiceApplicationH2 {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(CurrencyExchangeServiceApplicationH2.class, args);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/06-currency-exchange-service-h2-xray/src/main/java/com/in28minutes/microservices/currencyexchangeservice/resource/CurrencyExchangeController.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyexchangeservice.resource;
2 |
3 | import java.util.Map;
4 |
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.web.bind.annotation.GetMapping;
9 | import org.springframework.web.bind.annotation.PathVariable;
10 | import org.springframework.web.bind.annotation.RequestHeader;
11 | import org.springframework.web.bind.annotation.RestController;
12 |
13 | import com.amazonaws.xray.spring.aop.XRayEnabled;
14 | import com.in28minutes.microservices.currencyexchangeservice.util.containerservice.ContainerMetaDataService;
15 |
16 | @RestController
17 | @XRayEnabled
18 | public class CurrencyExchangeController {
19 |
20 | private static final Logger LOGGER = LoggerFactory.getLogger(CurrencyExchangeController.class);
21 |
22 | @Autowired
23 | private ExchangeValueRepository repository;
24 |
25 | @Autowired
26 | private ContainerMetaDataService containerMetaDataService;
27 |
28 | @GetMapping("/currency-exchange/from/{from}/to/{to}")
29 | public ExchangeValue retrieveExchangeValue(@PathVariable String from, @PathVariable String to,
30 | @RequestHeader Map headers) {
31 |
32 | printAllHeaders(headers);
33 |
34 | ExchangeValue exchangeValue = repository.findByFromAndTo(from, to);
35 |
36 | LOGGER.info("{} {} {}", from, to, exchangeValue);
37 |
38 | if (exchangeValue == null) {
39 | throw new RuntimeException("Unable to find data to convert " + from + " to " + to);
40 | }
41 |
42 | exchangeValue.setExchangeEnvironmentInfo(containerMetaDataService.retrieveContainerMetadataInfo());
43 |
44 | return exchangeValue;
45 | }
46 |
47 | private void printAllHeaders(Map headers) {
48 | headers.forEach((key, value) -> {
49 | LOGGER.info(String.format("Header '%s' = %s", key, value));
50 | });
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/06-currency-exchange-service-h2-xray/src/main/java/com/in28minutes/microservices/currencyexchangeservice/resource/ExchangeValue.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyexchangeservice.resource;
2 |
3 | import java.math.BigDecimal;
4 |
5 | import javax.persistence.Column;
6 | import javax.persistence.Entity;
7 | import javax.persistence.Id;
8 | import javax.persistence.Transient;
9 |
10 | @Entity
11 | public class ExchangeValue {
12 |
13 | @Id
14 | private Long id;
15 |
16 | @Column(name = "currency_from")
17 | private String from;
18 |
19 | @Column(name = "currency_to")
20 | private String to;
21 |
22 | private BigDecimal conversionMultiple;
23 |
24 | @Transient
25 | private String exchangeEnvironmentInfo;
26 |
27 | public ExchangeValue() {
28 |
29 | }
30 |
31 | public ExchangeValue(Long id, String from, String to, BigDecimal conversionMultiple) {
32 | super();
33 | this.id = id;
34 | this.from = from;
35 | this.to = to;
36 | this.conversionMultiple = conversionMultiple;
37 | }
38 |
39 | public Long getId() {
40 | return id;
41 | }
42 |
43 | public String getFrom() {
44 | return from;
45 | }
46 |
47 | public String getTo() {
48 | return to;
49 | }
50 |
51 | public BigDecimal getConversionMultiple() {
52 | return conversionMultiple;
53 | }
54 |
55 | public String getExchangeEnvironmentInfo() {
56 | return exchangeEnvironmentInfo;
57 | }
58 |
59 | public void setExchangeEnvironmentInfo(String environmentInfo) {
60 | this.exchangeEnvironmentInfo = environmentInfo;
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/06-currency-exchange-service-h2-xray/src/main/java/com/in28minutes/microservices/currencyexchangeservice/resource/ExchangeValueRepository.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyexchangeservice.resource;
2 |
3 | import org.springframework.data.jpa.repository.JpaRepository;
4 |
5 | public interface ExchangeValueRepository extends JpaRepository {
6 | ExchangeValue findByFromAndTo(String from, String to);
7 | }
8 |
--------------------------------------------------------------------------------
/06-currency-exchange-service-h2-xray/src/main/java/com/in28minutes/microservices/currencyexchangeservice/util/containerservice/ContainerMetaDataService.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyexchangeservice.util.containerservice;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import org.springframework.beans.factory.annotation.Value;
6 | import org.springframework.stereotype.Service;
7 | import org.springframework.web.client.RestTemplate;
8 |
9 | @Service
10 | public class ContainerMetaDataService {
11 |
12 | private static final String ENVIRONMENT_VARIABLE_ECS_CONTAINER_METADATA_URI = "ECS_CONTAINER_METADATA_URI";
13 |
14 | private static final String DEFAULT_VALUE = "EMPTY";
15 |
16 | private static final Logger LOGGER = LoggerFactory.getLogger(ContainerMetaDataService.class);
17 |
18 | // @Value(${ENVIRONMENT_VARIABLE_NAME:DEFAULT_VALUE})
19 | @Value("${" + ENVIRONMENT_VARIABLE_ECS_CONTAINER_METADATA_URI + ":" + DEFAULT_VALUE + "}")
20 | private String containerMetadataUri;
21 |
22 | public String retrieveContainerMetadataInfo() {
23 |
24 | if (containerMetadataUri.contains(DEFAULT_VALUE)) {
25 | LOGGER.info("Environment Variable Not Available - " + ENVIRONMENT_VARIABLE_ECS_CONTAINER_METADATA_URI);
26 | return "NA";
27 | }
28 |
29 | return new RestTemplate().getForObject(containerMetadataUri, String.class);
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/06-currency-exchange-service-h2-xray/src/main/java/com/in28minutes/microservices/currencyexchangeservice/util/logging/EnvironmentConfigurationLogger.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyexchangeservice.util.logging;
2 |
3 | import java.util.Arrays;
4 | import java.util.stream.StreamSupport;
5 |
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 | import org.springframework.context.event.ContextRefreshedEvent;
9 | import org.springframework.context.event.EventListener;
10 | import org.springframework.core.env.AbstractEnvironment;
11 | import org.springframework.core.env.EnumerablePropertySource;
12 | import org.springframework.core.env.Environment;
13 | import org.springframework.core.env.MutablePropertySources;
14 | import org.springframework.stereotype.Component;
15 |
16 | @Component
17 | public class EnvironmentConfigurationLogger {
18 |
19 | private static final Logger LOGGER = LoggerFactory.getLogger(EnvironmentConfigurationLogger.class);
20 |
21 | @SuppressWarnings("rawtypes")
22 | @EventListener
23 | public void handleContextRefresh(ContextRefreshedEvent event) {
24 | final Environment environment = event.getApplicationContext().getEnvironment();
25 | LOGGER.info("====== Environment and configuration ======");
26 | LOGGER.info("Active profiles: {}", Arrays.toString(environment.getActiveProfiles()));
27 | final MutablePropertySources sources = ((AbstractEnvironment) environment).getPropertySources();
28 | StreamSupport.stream(sources.spliterator(), false).filter(ps -> ps instanceof EnumerablePropertySource)
29 | .map(ps -> ((EnumerablePropertySource) ps).getPropertyNames()).flatMap(Arrays::stream).distinct()
30 | .forEach(prop -> LOGGER.info("{}", prop));// environment.getProperty(prop)
31 | LOGGER.info("===========================================");
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/06-currency-exchange-service-h2-xray/src/main/java/com/in28minutes/microservices/currencyexchangeservice/xray/AwsXrayConfig.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyexchangeservice.xray;
2 |
3 | import javax.servlet.Filter;
4 |
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 |
8 | import com.amazonaws.xray.javax.servlet.AWSXRayServletFilter;
9 |
10 | @Configuration
11 | public class AwsXrayConfig {
12 |
13 | @Bean
14 | public Filter TracingFilter() {
15 | return new AWSXRayServletFilter("currency-exchange-service");
16 | }
17 | }
--------------------------------------------------------------------------------
/06-currency-exchange-service-h2-xray/src/main/java/com/in28minutes/microservices/currencyexchangeservice/xray/XRayInspector.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyexchangeservice.xray;
2 |
3 | import java.util.Map;
4 |
5 | import org.aspectj.lang.ProceedingJoinPoint;
6 | import org.aspectj.lang.annotation.Aspect;
7 | import org.aspectj.lang.annotation.Pointcut;
8 | import org.springframework.stereotype.Component;
9 |
10 | import com.amazonaws.xray.entities.Subsegment;
11 | import com.amazonaws.xray.spring.aop.AbstractXRayInterceptor;
12 |
13 | @Aspect
14 | @Component
15 | public class XRayInspector extends AbstractXRayInterceptor {
16 | @Override
17 | protected Map> generateMetadata(ProceedingJoinPoint proceedingJoinPoint,
18 | Subsegment subsegment) {
19 | return super.generateMetadata(proceedingJoinPoint, subsegment);
20 | }
21 |
22 | @Override
23 | @Pointcut("@within(com.amazonaws.xray.spring.aop.XRayEnabled) && bean(*)")
24 | public void xrayEnabledClasses() {
25 | }
26 | }
--------------------------------------------------------------------------------
/06-currency-exchange-service-h2-xray/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.application.name=currency-exchange-microservice
2 | server.port=8000
3 |
4 | spring.jpa.show-sql=true
5 | spring.h2.console.enabled=true
6 |
7 | management.endpoints.web.base-path=/manage
8 | server.servlet.context-path=/api/currency-exchange-microservice
--------------------------------------------------------------------------------
/06-currency-exchange-service-h2-xray/src/main/resources/data.sql:
--------------------------------------------------------------------------------
1 | insert into exchange_value(id,currency_from,currency_to,conversion_multiple)
2 | values(10001,'USD','INR',65);
3 | insert into exchange_value(id,currency_from,currency_to,conversion_multiple)
4 | values(10002,'EUR','INR',75);
5 | insert into exchange_value(id,currency_from,currency_to,conversion_multiple)
6 | values(10003,'AUD','INR',25);
--------------------------------------------------------------------------------
/06-currency-exchange-service-h2-xray/src/test/java/com/in28minutes/microservices/currencyexchangeservice/CurrencyExchangeServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyexchangeservice;
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 CurrencyExchangeServiceApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/07-currency-conversion-service-xray/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jdk-alpine
2 | VOLUME /tmp
3 | EXPOSE 8100
4 | ADD target/*.jar app.jar
5 | ENV JAVA_OPTS=""
6 | ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]
--------------------------------------------------------------------------------
/07-currency-conversion-service-xray/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.in28minutes.microservices
8 | 07-aws-currency-conversion-service-xray
9 | 0.0.1-SNAPSHOT
10 | jar
11 |
12 | aws-currency-conversion-service-xray
13 | Demo project for Spring Boot
14 |
15 |
16 | org.springframework.boot
17 | spring-boot-starter-parent
18 | 2.1.1.RELEASE
19 |
20 |
21 |
22 |
23 | UTF-8
24 | UTF-8
25 | 1.8
26 | Greenwich.RC2
27 |
28 |
29 |
30 |
31 |
32 | org.springframework.boot
33 | spring-boot-starter-web
34 |
35 |
36 |
37 | org.springframework.boot
38 | spring-boot-starter-data-jpa
39 |
40 |
41 | com.h2database
42 | h2
43 | runtime
44 |
45 |
46 |
47 |
48 | org.springframework.cloud
49 | spring-cloud-starter-sleuth
50 |
51 |
52 |
53 | org.springframework.boot
54 | spring-boot-starter-actuator
55 |
56 |
57 |
58 |
59 | org.springframework.boot
60 | spring-boot-devtools
61 | runtime
62 |
63 |
64 |
65 | com.amazonaws
66 | aws-xray-recorder-sdk-spring
67 | 2.3.0
68 |
69 |
70 |
71 | com.amazonaws
72 | aws-xray-recorder-sdk-apache-http
73 | 2.3.0
74 |
75 |
76 |
77 |
78 | javax.xml.bind
79 | jaxb-api
80 |
81 |
82 | com.sun.xml.bind
83 | jaxb-impl
84 | 2.3.0
85 |
86 |
87 | org.glassfish.jaxb
88 | jaxb-runtime
89 |
90 |
91 | javax.activation
92 | activation
93 | 1.1.1
94 |
95 |
96 |
97 |
98 | org.springframework.boot
99 | spring-boot-starter-test
100 | test
101 |
102 |
103 |
104 |
105 |
106 |
107 | org.springframework.cloud
108 | spring-cloud-dependencies
109 | ${spring-cloud.version}
110 | pom
111 | import
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | org.springframework.boot
120 | spring-boot-maven-plugin
121 |
122 |
123 |
124 | com.spotify
125 | dockerfile-maven-plugin
126 | 1.4.10
127 |
128 |
129 | default
130 |
131 | build
132 |
133 |
134 |
135 |
136 |
137 | in28min/${project.name}
138 | ${project.version}
139 | true
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 | spring-snapshots
148 | Spring Snapshots
149 | https://repo.spring.io/snapshot
150 |
151 | true
152 |
153 |
154 |
155 | spring-milestones
156 | Spring Milestones
157 | https://repo.spring.io/milestone
158 |
159 | false
160 |
161 |
162 |
163 |
164 |
165 |
166 | spring-snapshots
167 | Spring Snapshots
168 | https://repo.spring.io/snapshot
169 |
170 | true
171 |
172 |
173 |
174 | spring-milestones
175 | Spring Milestones
176 | https://repo.spring.io/milestone
177 |
178 | false
179 |
180 |
181 |
182 |
183 |
--------------------------------------------------------------------------------
/07-currency-conversion-service-xray/readme.md:
--------------------------------------------------------------------------------
1 | # Currency Conversion Micro Service
2 |
3 | Run com.in28minutes.microservices.currencyconversionservice.CurrencyConversionServiceApplication as a Java Application.
4 |
5 | ## Changes for X Ray
6 |
7 | - pom.xml - aws-xray-recorder-sdk-spring & aws-xray-recorder-sdk-apache-http
8 | - AwsXrayConfig.java
9 | - XRayInspector.java
10 | - CurrencyConversionServiceApplication.java
11 |
12 | ```
13 | @Bean
14 | public RestTemplate restTemplate() {
15 | // return new RestTemplate();
16 | return new RestTemplate(clientHttpRequestFactory());
17 |
18 | }
19 |
20 | private ClientHttpRequestFactory clientHttpRequestFactory() {
21 | HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(
22 | HttpClientBuilder.create().useSystemProperties().build());
23 | factory.setReadTimeout(10000);
24 | factory.setConnectTimeout(2000);
25 | factory.setConnectionRequestTimeout(2000);
26 | return factory;
27 | }
28 |
29 | ```
30 |
31 |
32 | - CurrencyConversionController.java
33 |
34 | ```
35 | @RestController
36 | @XRayEnabled
37 | public class CurrencyConversionController {
38 | ```
39 |
40 | ## XRay Daemon
41 |
42 | - amazon/aws-xray-daemon:1
43 |
44 |
45 | ## Containerization
46 |
47 | ### Troubleshooting
48 |
49 | - Problem - Caused by: com.spotify.docker.client.shaded.javax.ws.rs.ProcessingException: java.io.IOException: No such file or directory
50 | - Solution - Check if docker is up and running!
51 | - Problem - Error creating the Docker image on MacOS - java.io.IOException: Cannot run program “docker-credential-osxkeychain”: error=2, No such file or directory
52 | - Solution - https://medium.com/@dakshika/error-creating-the-docker-image-on-macos-wso2-enterprise-integrator-tooling-dfb5b537b44e
53 |
54 | ### Creating Containers
55 |
56 | - mvn package
57 | - docker run --publish 8100:8100 --network MY_BRIDGE --env CURRENCY_EXCHANGE_URI=http://currency-exchange-microservice:8000 in28min/aws-currency-conversion-service-xray:0.0.1-SNAPSHOT
58 |
59 |
60 |
61 | Test API
62 | - http://localhost:8100/api/currency-conversion-microservice/currency-converter/from/USD/to/INR/quantity/1000
63 | - http://localhost:8100/api/currency-conversion-microservice/currency-converter-feign/from/USD/to/INR/quantity/10000
64 |
65 | ```
66 | docker login
67 | docker push @@REPO@@/aws-currency-conversion-service-xray:0.0.1-SNAPSHOT
68 | ```
69 |
70 |
71 | ## Resources
72 |
73 | - http://localhost:8100/api/currency-conversion-microservice/currency-converter-feign/from/USD/to/INR/quantity/10000
74 |
75 | ```json
76 | {
77 | "id": 10001,
78 | "from": "USD",
79 | "to": "INR",
80 | "conversionMultiple": 65.00,
81 | "quantity": 1000,
82 | "totalCalculatedAmount": 65000.00,
83 | "environmentInfo": "NA"
84 | }
85 | ```
--------------------------------------------------------------------------------
/07-currency-conversion-service-xray/src/main/java/com/in28minutes/microservices/currencyconversionservice/CurrencyConversionServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyconversionservice;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.http.client.ClientHttpRequestFactory;
7 | import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
8 | import org.springframework.web.client.RestTemplate;
9 |
10 | import com.amazonaws.xray.proxies.apache.http.HttpClientBuilder;
11 |
12 | @SpringBootApplication
13 | public class CurrencyConversionServiceApplication {
14 |
15 | public static void main(String[] args) {
16 | SpringApplication.run(CurrencyConversionServiceApplication.class, args);
17 | }
18 |
19 | @Bean
20 | public RestTemplate restTemplate() {
21 | // return new RestTemplate();
22 | return new RestTemplate(clientHttpRequestFactory());
23 |
24 | }
25 |
26 | private ClientHttpRequestFactory clientHttpRequestFactory() {
27 | HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(
28 | HttpClientBuilder.create().useSystemProperties().build());
29 | factory.setReadTimeout(10000);
30 | factory.setConnectTimeout(2000);
31 | factory.setConnectionRequestTimeout(2000);
32 | return factory;
33 | }
34 |
35 | }
--------------------------------------------------------------------------------
/07-currency-conversion-service-xray/src/main/java/com/in28minutes/microservices/currencyconversionservice/resource/CurrencyConversionBean.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyconversionservice.resource;
2 |
3 | import java.math.BigDecimal;
4 |
5 | public class CurrencyConversionBean {
6 |
7 | private Long id;
8 |
9 | private String from;
10 |
11 | private String to;
12 |
13 | private BigDecimal conversionMultiple;
14 |
15 | private BigDecimal quantity;
16 |
17 | private BigDecimal totalCalculatedAmount;
18 |
19 | private String exchangeEnvironmentInfo;
20 |
21 | private String conversionEnvironmentInfo;
22 |
23 | public CurrencyConversionBean() {
24 |
25 | }
26 |
27 | public CurrencyConversionBean(Long id, String from, String to, BigDecimal conversionMultiple, BigDecimal quantity,
28 | BigDecimal totalCalculatedAmount, String exchangeEnvironmentInfo, String conversionEnvironmentInfo) {
29 | super();
30 | this.id = id;
31 | this.from = from;
32 | this.to = to;
33 | this.conversionMultiple = conversionMultiple;
34 | this.quantity = quantity;
35 | this.totalCalculatedAmount = totalCalculatedAmount;
36 | this.exchangeEnvironmentInfo = exchangeEnvironmentInfo;
37 | this.conversionEnvironmentInfo = conversionEnvironmentInfo;
38 | }
39 |
40 | public Long getId() {
41 | return id;
42 | }
43 |
44 | public void setId(Long id) {
45 | this.id = id;
46 | }
47 |
48 | public String getFrom() {
49 | return from;
50 | }
51 |
52 | public void setFrom(String from) {
53 | this.from = from;
54 | }
55 |
56 | public String getTo() {
57 | return to;
58 | }
59 |
60 | public void setTo(String to) {
61 | this.to = to;
62 | }
63 |
64 | public BigDecimal getConversionMultiple() {
65 | return conversionMultiple;
66 | }
67 |
68 | public void setConversionMultiple(BigDecimal conversionMultiple) {
69 | this.conversionMultiple = conversionMultiple;
70 | }
71 |
72 | public BigDecimal getQuantity() {
73 | return quantity;
74 | }
75 |
76 | public void setQuantity(BigDecimal quantity) {
77 | this.quantity = quantity;
78 | }
79 |
80 | public BigDecimal getTotalCalculatedAmount() {
81 | return totalCalculatedAmount;
82 | }
83 |
84 | public void setTotalCalculatedAmount(BigDecimal totalCalculatedAmount) {
85 | this.totalCalculatedAmount = totalCalculatedAmount;
86 | }
87 |
88 | public String getExchangeEnvironmentInfo() {
89 | return exchangeEnvironmentInfo;
90 | }
91 |
92 | public void setExchangeEnvironmentInfo(String environmentInfo) {
93 | this.exchangeEnvironmentInfo = environmentInfo;
94 | }
95 |
96 | public String getConversionEnvironmentInfo() {
97 | return conversionEnvironmentInfo;
98 | }
99 |
100 | public void setConversionEnvironmentInfo(String conversionEnvironmentInfo) {
101 | this.conversionEnvironmentInfo = conversionEnvironmentInfo;
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/07-currency-conversion-service-xray/src/main/java/com/in28minutes/microservices/currencyconversionservice/resource/CurrencyConversionController.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyconversionservice.resource;
2 |
3 | import java.math.BigDecimal;
4 | import java.util.HashMap;
5 | import java.util.Map;
6 |
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.beans.factory.annotation.Value;
11 | import org.springframework.http.ResponseEntity;
12 | import org.springframework.web.bind.annotation.GetMapping;
13 | import org.springframework.web.bind.annotation.PathVariable;
14 | import org.springframework.web.bind.annotation.RestController;
15 | import org.springframework.web.client.RestTemplate;
16 |
17 | import com.amazonaws.xray.spring.aop.XRayEnabled;
18 | import com.in28minutes.microservices.currencyconversionservice.util.containerservice.ContainerMetaDataService;
19 |
20 | @RestController
21 | @XRayEnabled
22 | public class CurrencyConversionController {
23 |
24 | private static final Logger LOGGER = LoggerFactory.getLogger(CurrencyConversionController.class);
25 |
26 | @Autowired
27 | private ContainerMetaDataService containerMetaDataService;
28 |
29 | @Value("${CURRENCY_EXCHANGE_URI:http://localhost:8000}")
30 | private String currencyExchangeHost;
31 |
32 | @Autowired
33 | private RestTemplate restTemplate;
34 |
35 | @GetMapping("/currency-converter/from/{from}/to/{to}/quantity/{quantity}")
36 | public CurrencyConversionBean convertCurrency(@PathVariable String from, @PathVariable String to,
37 | @PathVariable BigDecimal quantity) {
38 |
39 | LOGGER.info("Received Request to convert from {} {} to {} ", quantity, from, to);
40 |
41 | ResponseEntity responseEntity = restTemplate.getForEntity(
42 | currencyExchangeHost + "/api/currency-exchange-microservice/currency-exchange/from/{from}/to/{to}",
43 | CurrencyConversionBean.class, createUriVariables(from, to));
44 |
45 | CurrencyConversionBean response = responseEntity.getBody();
46 |
47 | BigDecimal convertedValue = quantity.multiply(response.getConversionMultiple());
48 |
49 | String conversionEnvironmentInfo = containerMetaDataService.retrieveContainerMetadataInfo();
50 |
51 | return new CurrencyConversionBean(response.getId(), from, to, response.getConversionMultiple(), quantity,
52 | convertedValue, response.getExchangeEnvironmentInfo(), conversionEnvironmentInfo);
53 | }
54 |
55 | private Map createUriVariables(String from, String to) {
56 | Map uriVariables = new HashMap<>();
57 | uriVariables.put("from", from);
58 | uriVariables.put("to", to);
59 | return uriVariables;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/07-currency-conversion-service-xray/src/main/java/com/in28minutes/microservices/currencyconversionservice/util/containerservice/ContainerMetaDataService.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyconversionservice.util.containerservice;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import org.springframework.beans.factory.annotation.Value;
6 | import org.springframework.stereotype.Service;
7 | import org.springframework.web.client.RestTemplate;
8 |
9 | @Service
10 | public class ContainerMetaDataService {
11 |
12 | private static final String ENVIRONMENT_VARIABLE_ECS_CONTAINER_METADATA_URI = "ECS_CONTAINER_METADATA_URI";
13 |
14 | private static final String DEFAULT_VALUE = "EMPTY";
15 |
16 | private static final Logger LOGGER = LoggerFactory.getLogger(ContainerMetaDataService.class);
17 |
18 | // @Value(${ENVIRONMENT_VARIABLE_NAME:DEFAULT_VALUE})
19 | @Value("${" + ENVIRONMENT_VARIABLE_ECS_CONTAINER_METADATA_URI + ":" + DEFAULT_VALUE + "}")
20 | private String containerMetadataUri;
21 |
22 | public String retrieveContainerMetadataInfo() {
23 |
24 | if (containerMetadataUri.contains(DEFAULT_VALUE)) {
25 | LOGGER.info("Environment Variable Not Available - " + ENVIRONMENT_VARIABLE_ECS_CONTAINER_METADATA_URI);
26 | return "NA";
27 | }
28 |
29 | return new RestTemplate().getForObject(containerMetadataUri, String.class);
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/07-currency-conversion-service-xray/src/main/java/com/in28minutes/microservices/currencyconversionservice/util/logging/EnvironmentConfigurationLogger.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyconversionservice.util.logging;
2 |
3 | import java.util.Arrays;
4 | import java.util.stream.StreamSupport;
5 |
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 | import org.springframework.context.event.ContextRefreshedEvent;
9 | import org.springframework.context.event.EventListener;
10 | import org.springframework.core.env.AbstractEnvironment;
11 | import org.springframework.core.env.EnumerablePropertySource;
12 | import org.springframework.core.env.Environment;
13 | import org.springframework.core.env.MutablePropertySources;
14 | import org.springframework.stereotype.Component;
15 |
16 | @Component
17 | public class EnvironmentConfigurationLogger {
18 |
19 | private static final Logger LOGGER = LoggerFactory.getLogger(EnvironmentConfigurationLogger.class);
20 |
21 | @SuppressWarnings("rawtypes")
22 | @EventListener
23 | public void handleContextRefresh(ContextRefreshedEvent event) {
24 | final Environment environment = event.getApplicationContext().getEnvironment();
25 | LOGGER.info("====== Environment and configuration ======");
26 | LOGGER.info("Active profiles: {}", Arrays.toString(environment.getActiveProfiles()));
27 | final MutablePropertySources sources = ((AbstractEnvironment) environment).getPropertySources();
28 | StreamSupport.stream(sources.spliterator(), false).filter(ps -> ps instanceof EnumerablePropertySource)
29 | .map(ps -> ((EnumerablePropertySource) ps).getPropertyNames()).flatMap(Arrays::stream).distinct()
30 | .forEach(prop -> LOGGER.info("{}", prop));// environment.getProperty(prop)
31 | LOGGER.info("===========================================");
32 | }
33 | }
--------------------------------------------------------------------------------
/07-currency-conversion-service-xray/src/main/java/com/in28minutes/microservices/currencyconversionservice/xray/AwsXrayConfig.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyconversionservice.xray;
2 |
3 | import javax.servlet.Filter;
4 |
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 |
8 | import com.amazonaws.xray.javax.servlet.AWSXRayServletFilter;
9 |
10 | @Configuration
11 | public class AwsXrayConfig {
12 |
13 | @Bean
14 | public Filter TracingFilter() {
15 | return new AWSXRayServletFilter("currency-conversion-service");
16 |
17 | }
18 | }
--------------------------------------------------------------------------------
/07-currency-conversion-service-xray/src/main/java/com/in28minutes/microservices/currencyconversionservice/xray/XRayInspector.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyconversionservice.xray;
2 |
3 | import java.util.Map;
4 |
5 | import org.aspectj.lang.ProceedingJoinPoint;
6 | import org.aspectj.lang.annotation.Aspect;
7 | import org.aspectj.lang.annotation.Pointcut;
8 | import org.springframework.stereotype.Component;
9 |
10 | import com.amazonaws.xray.entities.Subsegment;
11 | import com.amazonaws.xray.spring.aop.AbstractXRayInterceptor;
12 |
13 | @Aspect
14 | @Component
15 | public class XRayInspector extends AbstractXRayInterceptor {
16 | @Override
17 | protected Map> generateMetadata(ProceedingJoinPoint proceedingJoinPoint,
18 | Subsegment subsegment) {
19 | return super.generateMetadata(proceedingJoinPoint, subsegment);
20 | }
21 |
22 | @Override
23 | @Pointcut("@within(com.amazonaws.xray.spring.aop.XRayEnabled) && bean(*)")
24 | public void xrayEnabledClasses() {
25 | }
26 |
27 | }
--------------------------------------------------------------------------------
/07-currency-conversion-service-xray/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.application.name=currency-conversion-microservice
2 | server.port=8100
3 |
4 | management.endpoints.web.base-path=/manage
5 | server.servlet.context-path=/api/currency-conversion-microservice
--------------------------------------------------------------------------------
/07-currency-conversion-service-xray/src/test/java/com/in28minutes/microservices/currencyconversionservice/CurrencyConversionServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.microservices.currencyconversionservice;
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 CurrencyConversionServiceApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/08-hello-world-rest-api-code-pipeline/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jdk-alpine
2 | VOLUME /tmp
3 | EXPOSE 80
4 | ADD target/*.jar app.jar
5 | ENV JAVA_OPTS=""
6 | ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]
--------------------------------------------------------------------------------
/08-hello-world-rest-api-code-pipeline/appspec.yaml:
--------------------------------------------------------------------------------
1 | version: 1.0
2 | Resources:
3 | - TargetService:
4 | Type: AWS::ECS::Service
5 | Properties:
6 | TaskDefinition: "arn:aws:ecs:us-east-1:183686979203:task-definition/aws-hello-world-rest-api:1"
7 | LoadBalancerInfo:
8 | ContainerName: "aws-hello-world-rest-api"
9 | ContainerPort: "80"
10 | PlatformVersion: "LATEST"
--------------------------------------------------------------------------------
/08-hello-world-rest-api-code-pipeline/buildspec.yaml:
--------------------------------------------------------------------------------
1 | version: 0.2
2 | phases:
3 | install:
4 | runtime-versions:
5 | java: corretto8
6 | pre_build:
7 | commands:
8 | - echo Logging in to Amazon ECR...
9 | - aws --version
10 | - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
11 | - TAG="$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | head -c 8)"
12 | - IMAGE_URI=${REPOSITORY_URI}:${TAG}
13 | build:
14 | commands:
15 | - echo Build started on `date`
16 | - echo $IMAGE_URI
17 | - mvn clean package -Ddockerfile.skip
18 | - docker build --tag $IMAGE_URI .
19 | post_build:
20 | commands:
21 | - printenv
22 | - echo Build completed on `date`
23 | - echo $(docker images)
24 | - echo Pushing docker image
25 | - docker push $IMAGE_URI
26 | - echo push completed
27 | - printf '[{"name":"%s","imageUri":"%s"}]' $CONTAINER_NAME $IMAGE_URI > imagedefinitions.json
28 | artifacts:
29 | files:
30 | - imagedefinitions.json
31 |
--------------------------------------------------------------------------------
/08-hello-world-rest-api-code-pipeline/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.in28minutes.rest.webservices
8 | 08-aws-hello-world-rest-api-pipeline
9 | 0.0.1-SNAPSHOT
10 | jar
11 | Demo project for Spring Boot
12 | aws-hello-world-rest-api-pipeline
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-parent
17 | 2.1.0.RELEASE
18 |
19 |
20 |
21 |
22 | UTF-8
23 | UTF-8
24 | 1.8
25 |
26 |
27 |
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-starter-web
32 |
33 |
34 |
35 | org.springframework.boot
36 | spring-boot-devtools
37 | runtime
38 |
39 |
40 |
41 | javax.xml.bind
42 | jaxb-api
43 |
44 |
45 | com.sun.xml.bind
46 | jaxb-impl
47 | 2.3.0
48 |
49 |
50 | org.glassfish.jaxb
51 | jaxb-runtime
52 |
53 |
54 | javax.activation
55 | activation
56 | 1.1.1
57 |
58 |
59 |
60 | org.springframework.boot
61 | spring-boot-starter-test
62 | test
63 |
64 |
65 |
66 |
67 |
68 |
69 | org.springframework.boot
70 | spring-boot-maven-plugin
71 |
72 |
73 |
74 | com.spotify
75 | dockerfile-maven-plugin
76 | 1.4.10
77 |
78 |
79 | default
80 |
81 | build
82 |
83 |
84 |
85 |
86 |
87 | in28min/${project.name}
88 | ${project.version}
89 | true
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | spring-snapshots
98 | Spring Snapshots
99 | https://repo.spring.io/snapshot
100 |
101 | true
102 |
103 |
104 |
105 | spring-milestones
106 | Spring Milestones
107 | https://repo.spring.io/milestone
108 |
109 | false
110 |
111 |
112 |
113 |
114 |
115 |
116 | spring-snapshots
117 | Spring Snapshots
118 | https://repo.spring.io/snapshot
119 |
120 | true
121 |
122 |
123 |
124 | spring-milestones
125 | Spring Milestones
126 | https://repo.spring.io/milestone
127 |
128 | false
129 |
130 |
131 |
132 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/08-hello-world-rest-api-code-pipeline/readme.md:
--------------------------------------------------------------------------------
1 | # Hello World Rest API
2 |
3 | - Main class com.in28minutes.rest.webservices.restfulwebservices.RestfulWebServicesApplication
4 | - You cannot run this app on local as it is configured to run on port 80 - https://serverfault.com/questions/112795/how-to-run-a-server-on-port-80-as-a-normal-user-on-linux. You can run it as a docker container as shown below
5 |
6 |
7 | ### Creating Containers
8 |
9 | - mvn clean package
10 | - docker run --publish 8200:80 in28min/aws-hello-world-rest-api:0.0.1-SNAPSHOT
11 |
12 | ```
13 | docker login
14 | docker push @@REPO@@/aws-hello-world-rest-api:0.0.1-SNAPSHOT
15 | ```
16 |
17 | ## Test URLs
18 |
19 | - http://localhost:8200/hello-world
20 |
21 | ```txt
22 | Hello World
23 | ```
24 |
25 | - http://localhost:8200/hello-world-bean
26 |
27 | ```json
28 | {"message":"Hello World - Changed"}
29 | ```
30 |
31 | - http://localhost:8200/hello-world/path-variable/in28minutes
32 |
33 | ```json
34 | {"message":"Hello World, in28minutes"}
35 | ```
36 |
--------------------------------------------------------------------------------
/08-hello-world-rest-api-code-pipeline/src/main/java/com/in28minutes/rest/webservices/restfulwebservices/HelloWorldBean.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.rest.webservices.restfulwebservices;
2 |
3 | public class HelloWorldBean {
4 |
5 | private String message;
6 |
7 | public HelloWorldBean(String message) {
8 | this.message = message;
9 | }
10 |
11 | public String getMessage() {
12 | return message;
13 | }
14 |
15 | public void setMessage(String message) {
16 | this.message = message;
17 | }
18 |
19 | @Override
20 | public String toString() {
21 | return String.format("HelloWorldBean [message=%s]", message);
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/08-hello-world-rest-api-code-pipeline/src/main/java/com/in28minutes/rest/webservices/restfulwebservices/HelloWorldController.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.rest.webservices.restfulwebservices;
2 |
3 | import org.springframework.web.bind.annotation.GetMapping;
4 | import org.springframework.web.bind.annotation.PathVariable;
5 | import org.springframework.web.bind.annotation.RestController;
6 |
7 | @RestController
8 | public class HelloWorldController {
9 |
10 | @GetMapping(path = "/hello-world")
11 | public String helloWorld() {
12 | return "Hello World";
13 | }
14 |
15 | @GetMapping(path = "/hello-world-bean")
16 | public HelloWorldBean helloWorldBean() {
17 | return new HelloWorldBean("Hello World - Changed - V2");
18 | }
19 |
20 | @GetMapping(path = "/hello-world/path-variable/{name}")
21 | public HelloWorldBean helloWorldPathVariable(@PathVariable String name) {
22 | return new HelloWorldBean(String.format("Hello World, %s", name));
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/08-hello-world-rest-api-code-pipeline/src/main/java/com/in28minutes/rest/webservices/restfulwebservices/RestfulWebServicesApplication.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.rest.webservices.restfulwebservices;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class RestfulWebServicesApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(RestfulWebServicesApplication.class, args);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/08-hello-world-rest-api-code-pipeline/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.port=80
--------------------------------------------------------------------------------
/08-hello-world-rest-api-code-pipeline/src/test/java/com/in28minutes/rest/webservices/restfulwebservices/RestfulWebServicesApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.rest.webservices.restfulwebservices;
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 RestfulWebServicesApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Deploy Spring Boot and Docker Microservices to AWS using ECS and AWS Fargate
2 |
3 | [](https://www.udemy.com/course/deploy-spring-microservices-to-aws-with-ecs-and-aws-fargate/)
4 |
5 |
6 | ## Learn Amazon Web Services - AWS - deploying Spring Boot and Docker Microservices to AWS Fargate. Implement Service Discovery, Load Balancing, Auto Discovery, Centralized Configuration and Distributed Tracing in AWS.
7 |
8 | Spring Boot is the No 1 Java Framework to develop REST API and Microservices. AWS (Amazon Web Services) is the No 1 Cloud Service Provider today.
9 |
10 | How about learning AWS by deploying Spring Boot Docker Containers to Amazon Web Services using Elastic Container Service - ECS and AWS Fargate?
11 |
12 | ## Getting Started
13 |
14 | - [Video - Docker in 5 Steps](https://youtu.be/Rt5G5Gj7RP0)
15 | - [Video - Spring in 10 Steps](https://www.youtube.com/watch?v=edgZo2g-LTM)
16 | - [Video - Spring Boot in 10 Steps](https://www.youtube.com/watch?v=pcdpk3Yd1EA)
17 | - [Video - JPA/Hibernate in 10 Steps](https://www.youtube.com/watch?v=MaI0_XdpdP8)
18 | - [AWS Code Pipeline Github Repo](https://github.com/in28minutes/hello-world-rest-api-aws-ecs-codepipeline)
19 |
20 | ## Container Images
21 |
22 | | Application | Container |
23 | | ------------------------------- | --------------------------------------------- |
24 | | Hello World | in28min/aws-hello-world-rest-api:1.0.0-RELEASE |
25 | | Simple Task | in28min/aws-simple-spring-task:1.0.0-RELEASE |
26 | | CurrencyExchangeMicroservice-H2 | in28min/aws-currency-exchange-service-h2:0.0.1-SNAPSHOT |
27 | | CurrencyExchangeMicroservice-H2 - V2 | in28min/aws-currency-exchange-service-h2:1.0.1-RELEASE|
28 | | CurrencyExchangeMicroSevice-MySQL| in28min/aws-currency-exchange-service-mysql:0.0.1-SNAPSHOT|
29 | | CurrencyConversionMicroservice | in28min/aws-currency-conversion-service:0.0.1-SNAPSHOT |
30 | | Currency Exchange - X Ray | in28min/aws-currency-exchange-service-h2-xray:0.0.1-SNAPSHOT|
31 | | Currency Conversion - X Ray | in28min/aws-currency-conversion-service-xray:0.0.1-SNAPSHOT|
32 |
33 | | Utility | Container Image |
34 | | ------------- | ------------------------- |
35 | | aws-xray-daemon| amazon/aws-xray-daemon:1|
36 |
37 | ## Microservice URLs and Details
38 |
39 | ### Currency Exchange Service
40 |
41 | - PORT - 8000
42 | - URL - `http://localhost:8000/api/currency-exchange-microservice/currency-exchange/from/EUR/to/INR`
43 | - HEALTH URL - `http://localhost:8000/api/currency-exchange-microservice/manage/health`
44 | - Enviroment Variables
45 | - SSM URN - `arn:aws:ssm:us-east-1::parameter/`
46 | - /dev/currency-exchange-service/RDS_DB_NAME - exchange_db
47 | - /dev/currency-exchange-service/RDS_HOSTNAME
48 | - /dev/currency-exchange-service/RDS_PASSWORD
49 | - /dev/currency-exchange-service/RDS_PORT - 3306
50 | - /dev/currency-exchange-service/RDS_USERNAME - exchange_db_user
51 |
52 | ### Currency Conversion Service
53 |
54 | - PORT - 8100
55 | - URL - `http://localhost:8100/api/currency-conversion-microservice/currency-converter/from/USD/to/INR/quantity/10`
56 | - HEALTH URL - `http://localhost:8100/api/currency-conversion-microservice/manage/health`
57 | - Enviroment Variables
58 | - SSM URN - `arn:aws:ssm:us-east-1::parameter/`
59 | - /dev/currency-conversion-service/CURRENCY_EXCHANGE_URI
60 |
61 | ## Enviroment Variables
62 |
63 | SSM URN - `arn:aws:ssm:us-east-1::parameter/`
64 |
65 | - /dev/currency-conversion-service/CURRENCY_EXCHANGE_URI
66 | - /dev/currency-exchange-service/RDS_DB_NAME - exchange_db
67 | - /dev/currency-exchange-service/RDS_HOSTNAME
68 | - /dev/currency-exchange-service/RDS_PASSWORD
69 | - /dev/currency-exchange-service/RDS_PORT - 3306
70 | - /dev/currency-exchange-service/RDS_USERNAME - exchange_db_user
71 |
72 | ## Setting up App Mesh
73 |
74 | #### Virtual nodes
75 | - currency-exchange-service-vn - currency-exchange-service.in28minutes-dev.com
76 | - currency-conversion-service-vn - currency-conversion-service.in28minutes-dev.com
77 |
78 | #### Virtual services
79 | - currency-exchange-service.in28minutes-dev.com -> currency-exchange-service-vn
80 | - currency-conversion-service.in28minutes-dev.com -> currency-conversion-service-vn
81 |
82 | #### Backend Registration
83 | - currency-conversion-service-vn -> currency-exchange-service.in28minutes-dev.com
84 |
85 | #### Task Definition Updates
86 | - aws-currency-conversion-service
87 | - aws-currency-exchange-service-h2
88 | - ```ENVOY_LOG_LEVEL-trace, ENABLE_ENVOY_XRAY_TRACING-1```
89 |
90 | #### Service Updates
91 | - aws-currency-conversion-service-appmesh
92 | - aws-currency-exchange-service-appmesh
93 |
94 | ## Deploying Version 2 of Currency Exchange Service to ECS and App Mesh
95 |
96 | #### App Mesh - New Virtual Node
97 | currency-exchange-service-v2-vn - currency-exchange-service-v2.in28minutes-dev.com
98 |
99 | #### ECS Fargate - Update Task Definition
100 | aws-currency-exchange-service-h2
101 | - in28min/aws-currency-exchange-service-h2:1.0.1-RELEASE
102 | - Use New Virtual Node
103 |
104 | #### ECS Fargate - Create New Service
105 | aws-currency-exchange-service-v2-appmesh
106 | - Service Discovery - currency-exchange-service-v2
107 |
108 | #### App Mesh - Create Virtual Router
109 | currency-exchange-service-vr distributing traffic to
110 | - currency-exchange-service-vn
111 | - currency-exchange-service-v2-vn
112 |
113 | #### App Mesh - Update Service to Use Virtual Router
114 | currency-exchange-service.in28minutes-dev.com -> currency-exchange-service-vr
115 |
116 |
117 | #### jq
118 |
119 | ```
120 | sudo yum install jq
121 | ```
122 |
123 | #### AWS CLI Hosted Zones
124 |
125 | ```
126 | aws --version
127 | aws configure
128 | aws servicediscovery list-services
129 | aws servicediscovery delete-service --id={id}
130 | aws servicediscovery list-services
131 |
132 | aws servicediscovery list-namespaces
133 | aws servicediscovery delete-namespace --id={id}
134 | aws servicediscovery list-namespaces
135 |
136 | aws servicediscovery delete-service --id=srv-7q3fkztnbo6aa5kc
137 | aws servicediscovery delete-service --id=srv-mdybugm4bh5u4ugx
138 | aws servicediscovery delete-service --id=srv-7upzjx3mhfleyfoz
139 | aws servicediscovery delete-namespace --id=ns-ctvtysasurklojm3
140 | ```
141 |
142 | ## Installation Guides
143 |
144 | #### Required Tools
145 |
146 | - Java 8+
147 | - Eclipse - Oxygen+ - (Embedded Maven From Eclipse)
148 | - Git
149 | - Docker
150 |
151 | #### Installing Guides
152 |
153 | - [Playlist - Installing Java, Eclipse & Embedded Maven](https://www.youtube.com/playlist?list=PLBBog2r6uMCSmMVTW_QmDLyASBvovyAO3)
154 |
155 | #### Troubleshooting Installations
156 | - Eclipse and Embedded Maven
157 | - Troubleshooting Guide : https://github.com/in28minutes/in28minutes-initiatives/tree/master/The-in28Minutes-TroubleshootingGuide-And-FAQ#tip--troubleshooting-embedded-maven-in-eclipse
158 | - PDF : https://github.com/in28minutes/SpringIn28Minutes/blob/master/InstallationGuide-JavaEclipseAndMaven_v2.pdf
159 | - GIT Repository For Installation : https://github.com/in28minutes/getting-started-in-5-steps
160 |
161 | ## Course Overview
162 |
163 | This course would be a perfect first step as an introduction to Amazon Web Services - AWS and the Cloud.
164 |
165 | In this course, we deploy a variety of Java Spring Boot Microservices to Amazon Web Services using AWS Fargate and ECS - Elastic Container Service.
166 |
167 | You will learn the basics of implementing Container Orchestration with ECS (Elastic Container Service) - Cluster, Task Definitions, Tasks, Containers and Services. You will learn about the two launch types of ECS - EC2 and AWS Fargate. In this course, we would focus extensively on AWS Fargate to simplify your Container Orchestration. You will learn to deploy multiple containers in the same ECS task.
168 |
169 | You will learn to Build Container Images for your Java Spring Boot Microservice Projects.
170 |
171 | You will implement the following features for your Microservices
172 | - Centralized Configuration Management with AWS Parameter Store
173 | - Distributed Tracing with AWS X Ray
174 | - Auto Scaling and Load Balancing with ECS, Elastic Load Balancers and Target Groups
175 | - Service Mesh using AWS App Mesh. You will learn the basics of AWS App Mesh - Mesh, Virtual Nodes and Virtual Services. You will learn to perform Canary Deployments using AWS AppMesh.
176 | - Service Discovery with Route 53 Hosted Zones and DNS.
177 | - Continuous Integration and Continuous Deployment with AWS Code Pipeline
178 |
179 | You will learn to debug problems with deploying containers using Service events and AWS CloudWatch logs.
180 |
181 | You will learn about automating deployments and creating a continuous delivery pipeline with AWS Code Pipeline. You will learn how to Auto Scale applications based on load as well as deploy multiple instances behind a load balancer using AWS ECS Fargate.
182 |
183 | You will be using a number of AWS Services - ECS - Elastic Container Services, AWS Fargate, EC2 - Elastic Compute Cloud, S3, AWS CodePipeLine, AWS CodeBuild, IAM, CloudWatch, ELB, Target Groups, X Ray, AWS Parameter Store, AWS App Mesh and Route 53.
184 |
185 | You will be using deploying a variety of projects to Amazon Web Services (AWS). These projects are created with Spring Boot (REST API Framework), Spring (Dependency Management), Maven (dependencies management), Eclipse (Java IDE) and Tomcat Embedded Web Server. We will help you set up each one of these.
186 |
187 | ## What you'll learn
188 | - You will Learn the Fundamentals of Amazon Web Services from Zero, no previous experience required
189 | - You will learn to deploy Spring Boot REST API and Microservices to AWS with AWS Fargate and ECS
190 | - You will learn the basics of implementing Container Orchestration with ECS (Elastic Container Service) - Cluster, Task Definitions, Tasks, Containers and Services
191 | - You will learn to Build Container Images for your Java Spring Boot Microservice Projects
192 | - You will learn about the two launch types of ECS - EC2 and AWS Fargate
193 | - You will learn to debug problems with deploying containers using Service events and AWS CloudWatch logs
194 | - You will be using a number of AWS Services - ECS - Elastic Container Services, AWS Fargate, EC2 - Elastic Compute Cloud, S3, AWS CodePipeLine, AWS CodeBuild, IAM, CloudWatch, ELB, Target Groups, X Ray, AWS Parameter Store, AWS App Mesh and Route 53
195 | - You will learn to create a continuous delivery pipeline with AWS Code Pipeline
196 | - You will learn how to Auto Scale applications based on load as well as deploy multiple instances behind a load balancer using AWS Fargate.
197 | - You will learn to implement Centralized Configuration Management for your Java Spring Boot Microservices with AWS Parameter Store
198 | - You will learn to implement Distributed Tracing for Java Spring Boot Microservices with AWS X Ray
199 | - You will learn the basics of AWS App Mesh - Mesh, Virtual Nodes and Virtual Services. You will learn to perform Canary Deployments for Java Spring Boot Microservices using AWS AppMesh.
200 | - You will Join 300,000 Learners having AMAZING LEARNING Experiences with in28Minutes
201 |
202 | ## Requirements
203 | - You have an attitude to learn while having fun :)
204 | - You have some programming experience with Java, Spring and Spring Boot
205 | - You have a valid debit or credit card to create a AWS Account
206 | - AWS Fargate is not in FREE Tier. You are responsible for monitoring the usage of AWS resources to reduce your billing.
207 | - You DO NOT need to have any experience with AWS (Amazon Web Services)
208 |
209 |
210 | ## Step By Step Details
211 |
212 | ### Getting Started with the course
213 |
214 | - Step 00 - Deploying Spring Boot Microservices with ECS and AWS Fargate - Introduction
215 | - Step 01 - Deploying Spring Boot Microservices with ECS and AWS Fargate - Getting Started with the Course
216 |
217 | ### Getting Started with AWS
218 |
219 | - Step 01 - Creating an AWS Root Account
220 | - Step 02 - Creating an IAM User for your AWS Account
221 |
222 | ### Getting Started with ECS and AWS Fargate
223 |
224 | - Step 01 - 10000 Feet Overview of Cloud, AWS, ECS and AWS Fargate
225 | - Step 02 - Getting Started with AWS Fargate - Deploy First Docker Container to AWS
226 | - Step 03 - Launch Sample App in Browser
227 | - Step 04 - Understanding AWS ECS Task Definition - Create first task definition for Hello World API
228 | - Step 05 - Create an ECS Service for Hello World API
229 | - Step 06 - Explore ECS Services - Launch Hello World REST API in Browser
230 | - Step 07 - Its Your Responsibility to Monitor Billing on the Cloud - 5 Recommendations
231 | - Step 08 - Monitor AWS Billing - Setting Billing Alerts
232 | - Step 09 - Reduce Bills - Set Service Desired Tasks to 0
233 | - Step 10 - Launch an AWS Fargate Task Directly
234 | - Step 11 - Run Batch Programs Using ECS Tasks - Simple Spring Task
235 |
236 | ### Getting Started with ECS with EC2 instances
237 |
238 | - Step 01 - Getting Started with ECS with EC2 instances
239 | - Step 02 - Create a Cluster for ECS with EC2 instances
240 | - Step 03 - Create a Service - Introduction to Region and AZ
241 | - Step 04 - Using Host Network Mode - Create New Task Definition and Service
242 | - Step 05 - ECS Cluster Management - Scale EC2 Instances
243 | - Step 06 - Debugging ECS and Fargate Problems using Service Events
244 | - Step 07 - Debugging Problems - Container Status, Stopped Reason and Cloud Watch Logs
245 | - Step 08 - Clean up Cluster
246 | - Step 09 - ECS with EC2 vs AWS Fargate
247 |
248 | ### Introduction to Microservices
249 |
250 | - Step 01 - Introduction to Microservices
251 | - Step 02 - Microservices - Challenges
252 | - Step 03 - Advantages of Microservices
253 |
254 | ### Deploying Currency Exchange Microservice with H2 to AWS Fargate
255 |
256 | - Step 01 - Import Microservices Projects into Eclipse
257 | - Step 02 - Code Review and Running Currency Exchange Microservice on Local
258 | - Step 03 - Build and Run Docker Container Image on Local for Currency Exchange Microservice
259 | - Step 04 - Push Currency Exchange Microservice Docker Image to Docker Hub
260 | - Step 05 - Currency Exchange Microservice with H2 - Create Task Definition and Service
261 | - Step 06 - Execute Currency Exchange Microservice on AWS
262 | - Step 07 - Using Task Metadata service to populate environment information
263 | - Step 08 - Exercise - Build Container Images for Hello World and Spring Task Projects
264 |
265 | ### Deploying Currency Exchange Microservice with MySQL to AWS Fargate
266 |
267 | - Step 00 - Quick Tip - Use Prebuild Container Images from Docker Hub
268 | - Step 01 - Currency Exchange Microservice with MySQL - Code Review
269 | - Step 02 - Launch MySQL as a Docker Container in Local
270 | - Step 03 - Connect Local Currency Exchange Microservice with MySQL
271 | - Step 04 - Create Currency Exchange Microservice with MySQL Docker Image and Push to Docker Hub
272 | - Step 05 - Create MySQL Database on AWS using RDS
273 | - Step 06 - Create Task Definition and Service for Currency Exchange Microservice with MySQL
274 | - Step 07 - Configure Security Group to all traffic from Microsevice to RDS Database
275 | - Step 08 - Creating a New Security Group for RDS Database
276 |
277 | ### Deploying Currency Conversion Microservice to AWS Fargate
278 |
279 | - Step 01 - Code Review and Running Currency Conversion Microservice on Local
280 | - Step 02 - Create Docker Image for Currency Conversion Microservice and Connect to Exchange Microservice using same network
281 | - Step 03 - Deploy Currency Conversion Microservice to AWS Fargate - Create ECS Task Definition and Service
282 | - Step 04 - Execute Currency Conversion Microservice on AWS Fargate
283 | - Step 05 - Running Currency Conversion Microservice and Currency Conversion Microservice in Same Task - Part 1
284 | - Step 06 - Running Currency Conversion Microservice and Currency Conversion Microservice in Same Task - Part 2
285 |
286 | ### Implement Centralized Configuration Management with AWS Parameter Store
287 |
288 | - Step 01 - Introduction to Centralized Configuration Management with AWS Parameter Store
289 | - Step 02 - Update ECS Task Definitions to use Centralized Configuration
290 | - Step 03 - Provide access to Parameter Store for ECS Task Execution Role and Test the REST API
291 | - Step 04 - Centralized Configuration Management - A Review
292 |
293 | ### Implement Distributed Tracing with AWS X Ray
294 |
295 | - Step 01 - Introduction to Distributed Tracing with AWS X Ray - Code Review
296 | - Step 02 - Deploy Currency Exchange Microservice with AWS X Ray - Update Task Def and Service
297 | - Step 03 - Provide access to AWS X Ray for ECS Task Execution Role
298 | - Step 04 - Currency Conversion Microservice with X Ray - Code Review and Deployment to AWS
299 | - Step 05 - CCS and CES in X Ray - Service Maps, Traces and Analytics
300 |
301 | ## Implement Auto Scaling and Load Balancing with AWS Fargate
302 |
303 | - Step 01 - Introduction to Auto Scaling and Load Balancing - Create ELB
304 | - Step 02 - Deploy New Load Balanced Service for Currency Exchange Microservice
305 | - Step 03 - Testing Currency Exchange Microservice through Load Balancer
306 | - Step 04 - Deploy New Load Balanced Service for Currency Conversion Microservice
307 | - Step 05 - Testing Currency Conversion Microservice through Load Balancer
308 | - Step 06 - Configure Auto Scaling for Currency Exchange Microservice
309 | - Step 07 - AWS Fargate Auto Scaling in Action - Scale in and Scale out
310 | - Step 08 - Clean Resources from this section
311 | - Step 09 - Tracing Request across Microservices using AWS CloudWatch Log Groups
312 |
313 | ## Deploying Service Mesh using AWS App Mesh
314 |
315 | - Step 01 - Introduction to AWS App Mesh
316 | - Step 02 - Introduction to Service Discovery and Implementing Service Discovery for Currency Exchange Microservice
317 | - Step 03 - Implementing Service Discovery for Currency Conversion Microservice - Review Hosted Zones and DNS
318 | - Step 04 - Creating EC2 Instance in VPC for Service Discovery Testing
319 | - Step 05 - SSH into EC2 Instance and Run Microservices using curl
320 | - Step 06 - Quick Tip - Format using jq
321 | - Step 07 - Basics of AWS App Mesh - Mesh, Virtual Nodes and Virtual Services
322 | - Step 08 - Integrate Microservics with AWS App Mesh - Update ECS Task Definitions and Service
323 | - Step 09 - Review AWS App Mesh - Cloud Watch Logs and X Ray Tracing
324 | - Step 10 - App Mesh and X Ray - Zero Microservice Code Change Needed - Deploy Non X Ray Microsevices to AWS Fargate
325 | - Step 11 - Canary Deployments with AWS AppMesh - Deploy Multiple Version of Microservice - 1
326 | - Step 12 - Canary Deployments with AWS AppMesh - Deploy Multiple Version of Microservice - 2
327 | - Step 13 - Clean Up Services and Hosted Zones
328 |
329 | ## Implement CI and CD with AWS Code Pipeline
330 |
331 | - Step 01 - Overview - CI and CD with AWS Code Pipeline - Create ECR Repository
332 | - Step 02 - Commit Hello World REST API Project to GIT Repository
333 | - Step 03 - Updating Application Specification for ECS Deployment with Task Definition and Container Name
334 | - Step 04 - Create Code Pipeline for Hello World REST API
335 | - Step 05 - Provide Access to ECR to Code Build Role
336 | - Step 06 - Understanding Code Build Specification - Build Spec
337 | - Step 07 - Review of AWS Code Pipeline
338 |
339 | ## Diagrams
340 |
341 | - Courtesy http://viz-js.com/
342 |
343 | ```
344 | graph architecture {
345 |
346 | node[style=filled,color="#59C8DE"]
347 | //node [style=filled,color="#D14D28", fontcolor=white];
348 | rankdir = TB;
349 | node[shape=record, width=2]
350 |
351 | 1 -- 2 -- 3 -- 4
352 |
353 | 1[label=]
354 | 2[label=]
355 | 3[label=]
356 | 4[label=]
357 |
358 | }
359 |
360 | digraph architecture {
361 |
362 | node[style=filled,color="#59C8DE"]
363 | //node [style=filled,color="#D14D28", fontcolor=white];
364 | rankdir = TB;
365 | node[shape=record]
366 | CO[shape=record, width=6.5, style=filled,color="#D14D28", fontcolor=white]
367 | CI,CC[shape=record, width=2]
368 | CL[shape=record, width=6]
369 | 2,3,4[shape=record, width=1.5]
370 | CI -> CO
371 | CC -> CO
372 | CO -> CL
373 | CL -> 2
374 | CL -> 3
375 | CL -> 4
376 |
377 | CI[label=]
378 | CO[label=]
379 | CC[label=]
380 | CL[label=]
381 | 2[label=]
382 | 3[label=]
383 | 4[label=]
384 |
385 | }
386 |
387 | digraph architecture {
388 |
389 | node[style=filled,color="#36BF80"]
390 | //node [style=filled,color="#D14D28", fontcolor=white];
391 | rankdir = TB;
392 | node[shape=record]
393 | CO[shape=record, width=6.5, style=filled,color="#D14D28", fontcolor=white]
394 | CI,CC[shape=record, width=2]
395 | CL[shape=record, width=6]
396 | 2,3,4[shape=record, width=1.5]
397 | CI -> CO
398 | CC -> CO
399 | CO -> CL
400 | CL -> 2
401 | CL -> 3
402 | CL -> 4
403 |
404 | CI[label=]
405 | CO[label=]
406 | CC[label=]
407 | CL[label=]
408 | 2[label=]
409 | 3[label=]
410 | 4[label=]
411 | }
412 |
413 | digraph architecture {
414 |
415 | node[style=filled,color="#36BF80"]
416 | //node [style=filled,color="#D14D28", fontcolor=white];
417 | rankdir = TB;
418 | node[shape=record]
419 | CO[shape=record, width=6.5, style=filled,color="#D14D28", fontcolor=white]
420 | CI,CC[shape=record, width=2]
421 | CL[shape=record, width=6,color="#59C8DE"]
422 | CI -> CO
423 | CC -> CO
424 | CO -> CL
425 |
426 | CI[label=]
427 | CO[label=]
428 | CC[label=]
429 | CL[label=]
430 | }
431 |
432 | digraph architecture {
433 | rankdir=TB;
434 | {rank=same; CurrencyConversionService, CurrencyExchangeService};
435 | Database[shape=cylinder]
436 | CurrencyConversionService, CurrencyExchangeService[shape=component]
437 |
438 | CurrencyConversionService -> CurrencyExchangeService;
439 |
440 | CurrencyExchangeService->Database;
441 |
442 | CurrencyConversionService[label=
10 USD = 600 INR
>];
443 | CurrencyExchangeService[label=
1 USD = 60 INR
1 EUR = 70 INR
1 AUD = 50 INR>];
444 |
445 | }
446 |
447 | graph architecture {
448 |
449 | node[style=filled,color="#59C8DE"]
450 | //node [style=filled,color="#D14D28", fontcolor=white];
451 | rankdir = TB
452 |
453 | node[shape=record, width=0.5]
454 | LoadBalancer[width=5,label=,color="#D14D28", fontcolor=white]
455 | Listener1[width=3,label=>]
456 | Listener2[width=3,label=]
457 | TG1,TG2[width=2.5,label=>]
458 | Rule1[width=2.75,label=/api/currency-conversion-microservice>]
459 | Rule2[width=2.75,label=/api/currency-exchange-microservice>]
460 | CCS1,CCS2,CCS3[label=Service>]
461 | CES1,CES2[label=Service>]
462 | LoadBalancer -- Listener1
463 | LoadBalancer -- Listener2
464 | Listener1 -- Rule1
465 | Listener1 -- Rule2
466 | Rule1 -- TG1
467 | Rule2 -- TG2
468 | TG1 -- CCS1
469 | TG1 -- CCS2
470 | TG1 -- CCS3
471 | TG2 -- CES1
472 | TG2 -- CES2
473 |
474 | }
475 |
476 | graph architecture {
477 |
478 | node[style=filled,color="#59C8DE"]
479 | //node [style=filled,color="#D14D28", fontcolor=white];
480 | rankdir = TB;
481 | node[shape=record]
482 |
483 | IAM -- Console
484 | Console -- UserID
485 | Console -- Password
486 | IAM -- Application
487 | Application -- AccessKeyID
488 | Application -- SecretAccessKey
489 |
490 | IAM[label=]
491 | AccessKeyID[label=]
492 | UserID[label=]
493 | SecretAccessKey[label=]
494 | Console[label=]
495 | Application[label=]
496 | }
497 |
498 | graph architecture {
499 |
500 | node[style=filled,color="#59C8DE"]
501 | //node [style=filled,color="#D14D28", fontcolor=white];
502 | rankdir = TB;
503 | node[shape=record]
504 |
505 | Users -- RootUser
506 | Users -- IAM
507 |
508 | RootUser[label=]
509 | IAM[label=]
510 |
511 | }
512 |
513 |
514 |
515 | graph architecture {
516 |
517 | node[style=filled,color="#59C8DE"]
518 | //node [style=filled,color="#D14D28", fontcolor=white];
519 | rankdir = TB
520 | node[shape=record, width=2]
521 | edge [width=0]
522 | graph [pad=".75", ranksep="0.05", nodesep="0.25"];
523 |
524 | Applications -- Software [style=invis]
525 | Software -- OS [style=invis]
526 | OS -- Hardware [style=invis]
527 |
528 | }
529 |
530 |
531 | graph architecture {
532 |
533 | node[style=filled,color="#59C8DE"]
534 | //node [style=filled,color="#D14D28", fontcolor=white];
535 | rankdir = TB
536 | node[shape=record, width=3]
537 |
538 | Containers, LocalImages [height=1]
539 |
540 | DockerClient -- Daemon
541 | Daemon -- Containers
542 | Daemon -- LocalImages
543 | Daemon -- ImageRegistry
544 |
545 | DockerClient[label=]
546 | ImageRegistry[label=nginx
mysql
eureka
your-app
>];
547 | Daemon[label=]
548 |
549 |
550 | }
551 |
552 |
553 | graph architecture {
554 |
555 | node[style=filled,color="#59C8DE"]
556 | //node [style=filled,color="#D14D28", fontcolor=white];
557 | rankdir = TB
558 | node[shape=record, width=2]
559 | Hypervisor,HostOS, Hardware[shape=record, width=6.5, style=filled,color="#D14D28", fontcolor=white]
560 | edge [width=0]
561 | graph [pad=".75", ranksep="0.05", nodesep="0.25"];
562 |
563 | Application1 -- Software1 [style=invis]
564 | Application2 -- Software2 [style=invis]
565 | Application3 -- Software3 [style=invis]
566 |
567 | Software1 -- GuestOS1 [style=invis]
568 | Software2 -- GuestOS2 [style=invis]
569 | Software3 -- GuestOS3 [style=invis]
570 | GuestOS1 -- Hypervisor [style=invis]
571 | GuestOS2 -- Hypervisor [style=invis]
572 | GuestOS3 -- Hypervisor [style=invis]
573 | Hypervisor -- HostOS [style=invis]
574 | HostOS -- Hardware [style=invis]
575 |
576 | }
577 |
578 |
579 | graph architecture {
580 |
581 | node[style=filled,color="#59C8DE"]
582 | //node [style=filled,color="#D14D28", fontcolor=white];
583 | rankdir = TB
584 | node[shape=record, width=2]
585 | HostOS, CloudInfrastructure, DockerEngine[shape=record, width=6.5, style=filled,color="#D14D28", fontcolor=white]
586 | edge [width=0]
587 | graph [pad=".75", ranksep="0.05", nodesep="0.25"];
588 | Container1,Container2,Container3[height=2]
589 |
590 | Container1 -- DockerEngine [style=invis]
591 | Container2 -- DockerEngine [style=invis]
592 | Container3 -- DockerEngine [style=invis]
593 | DockerEngine -- HostOS [style=invis]
594 | HostOS -- CloudInfrastructure [style=invis]
595 |
596 | }
597 | ```
598 |
599 | ### Troubleshooting
600 | - Refer our TroubleShooting Guide - https://github.com/in28minutes/in28minutes-initiatives/tree/master/The-in28Minutes-TroubleshootingGuide-And-FAQ
601 |
602 | ## Youtube Playlists - 500+ Videos
603 |
604 | [Click here - 30+ Playlists with 500+ Videos on Spring, Spring Boot, REST, Microservices and the Cloud](https://www.youtube.com/user/rithustutorials/playlists?view=1&sort=lad&flow=list)
605 |
606 | ## Keep Learning in28Minutes
607 |
608 | in28Minutes is creating amazing solutions for you to learn Spring Boot, Full Stack and the Cloud - Docker, Kubernetes, AWS, React, Angular etc. - [Check out all our courses here](https://github.com/in28minutes/learn)
609 |
--------------------------------------------------------------------------------