Skip to content

Commit 44625f3

Browse files
pranav-patilPranav Patil
authored andcommitted
Updating sqldb-service to data-service with webflux services
1 parent 2785bbf commit 44625f3

File tree

58 files changed

+924
-195
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+924
-195
lines changed

README.md

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
11
# Spring Micro Services Showcase
2-
[Spring Boot](https://docs.spring.io/spring-boot/docs/1.5.10.RELEASE/reference/htmlsingle/) demonstrates the capabilities of spawning but micro services for all the functionality
3-
including MVC, JPA, Spring Security.
42

5-
In this showcase you'll see the following in action:
3+
[Microservices](https://microservices.io/) is an architectural style that structures an application as a collection of loosely coupled services, where each service implements business capabilities. A microservice runs in its own process and communicates other services via HTTP API. Every microservice can be deployed, upgraded, scaled, and restarted independently of the other services in an application.
4+
It enables continuous delivery/deployment of large, complex applications. It allows better component isolation and high resilience against component failures. Smaller components in microservices can be scaled easily to meet increasing demand for a specific component. It increases developer independence and allows parallel development across multiple smaller teams.
5+
Microservices brings additional complexity as the developers have to mitigate fault tolerance, network latency, and deal with load balancing. Also deployment and testing of such a distributed system is complicated and tedious.
66

7-
* [Zuul Server](https://cloud.spring.io/spring-cloud-netflix/multi/multi__router_and_filter_zuul.html)
8-
* [Eureka Server](https://github.com/Netflix/eureka/wiki/Eureka-at-a-glance)
7+
[Spring Boot](https://docs.spring.io/spring-boot/docs/1.5.10.RELEASE/reference/htmlsingle/) enables to spawn stand-alone, production-grade Spring-based Applications with very little configuration, hence it is widely used in micro services arena. It is preconfigured with the Spring's standard configuration and has an embedded Tomcat or Jetty to provide full fledged server functionality.
8+
[Spring Cloud](http://projects.spring.io/spring-cloud/) framework, provides a collection of tools and solutions to some of the commonly encountered patterns when building distributed systems. It addresses solutions for some of the common problems in distributed systems including Configuration management, Service discovery, Circuit breakers and Distributed sessions.
9+
[Docker](https://www.docker.com/) is a open platform to create, deploy, and run applications as a lightweight, portable, self-sufficient container, which can run virtually anywhere.
10+
These tools and platforms form the foundation for spring micro services project.
911

10-
To run the application:
11-
-------------------
12-
From the command line with Git and Gradle:
12+
The spring micro services showcase contains the following services in action:
1313

14-
$ git clone https://github.com/pranav-patil/spring-microservices.git
15-
$ cd spring-microservices
16-
$ gradle clean build
17-
$ java -jar config-server/build/libs/config-server-0.0.1-SNAPSHOT.jar
14+
* [Elastic Stack](elastic-stack/README.md): ElasticSearch-Logstash-Kibana provides log storage and management.
15+
* [Kafka Broker](kafka-broker/README.md): Kafka Message broker provides messaging capabilities to zipkin trace messages to Zipkin server.
16+
* [Zipkin Service](zipkin-service/README.md): Zipkin enables to trace requests spanning across multiple services.
17+
18+
* [Config Service](config-service/README.md): Configuration service provides access to spring **application.yml** configuration files for corresponding service stored in its centralized (currently local) location.
19+
* [Discovery Service](discovery-service/README.md): Eureka discovery service allows micro services to find and communicate with each other.
20+
* [Authorization Service](authorization-service/README.md): Authorization service is responsible for providing OAuth2 access tokens after authentication and validating request access tokens before allowing access to the authorized services.
21+
* [Data Service](data-service/README.md): Data service provides reactive services using Spring WebFlux to fetch various data (currently stock data).
22+
* [Finance Service](finance-service/README.md): Finance service provides services to fetch financial data especially stock details.
23+
* [Analytics Service](analytics-service/README.md): Analytics services consume data from various sources, mainly finance-service and data-service and provide analytical details regarding the corresponding data.
24+
* [Monitor Service](monitor-service/README.md): Monitor service mainly gathers hystrix circuit breaker data from finance and analytics services, and displays the [Hystrix Dashboard](https://github.com/Netflix-Skunkworks/hystrix-dashboard).

analytics-service/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
Analytics Service
2+
=============
3+
4+
Analytics service provides various services to access analytical data from diverse resources. Currently analytics services for only financial or stock data are available.
5+
It mainly showcases [OpenFeign Clients](https://github.com/OpenFeign/feign), [Netflix Hystrix](https://github.com/Netflix/Hystrix) circuit breakers, [Spring Cloud Sleuth](https://cloud.spring.io/spring-cloud-sleuth/) with Zipkin and [Spring Webflux](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html) clients.
6+
7+
### Running the Analytics Service
8+
9+
The **CONFIG_SERVICE_PASSWORD** is a required parameter to run analytics-service as it enables to access analytics-service.yml configuration file from the [config-service](/../config-service/README.md).
10+
The **ANALYTICS_SERVICE_PASSWORD** is the client secret required to access oauth2 token for client id analytics-service. Use the same **ANALYTICS_SERVICE_PASSWORD** configured in [authorization-service](/../authorization-service/README.md).
11+
Optionally **spring.profiles.active** can be passed with value **prod** which enables logback to send all logs to [Elastic Stack](/../elastic-stack/README.md) instead of logging in the console by default.
12+
13+
$ java -jar analytics-service/build/libs/analytics-service-0.0.1-SNAPSHOT.jar
14+
-DCONFIG_SERVICE_PASSWORD=xxxx
15+
-DANALYTICS_SERVICE_PASSWORD=yyyy
16+
-Dspring.profiles.active=prod

analytics-service/build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ dependencies {
3535
compile('org.springframework.boot:spring-boot-starter-security')
3636
compile('org.springframework.boot:spring-boot-starter-data-rest')
3737
compile('org.springframework.boot:spring-boot-starter-web')
38+
compile('org.springframework.boot:spring-boot-starter-webflux')
3839
compile('org.springframework.cloud:spring-cloud-starter-openfeign')
3940
compile('org.springframework.cloud:spring-cloud-starter-oauth2')
4041
compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
@@ -58,7 +59,7 @@ dependencyManagement {
5859
}
5960

6061
processResources {
61-
filesMatching("**/bootstrap.yml") {
62+
filesMatching("**/application.properties") {
6263
expand(project.properties)
6364
}
6465
}

analytics-service/src/main/java/com/emprovise/service/AnalyticsServiceApplication.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import org.springframework.boot.context.properties.ConfigurationProperties;
77
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
88
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
9+
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
910
import org.springframework.cloud.openfeign.EnableFeignClients;
1011
import org.springframework.cloud.security.oauth2.client.feign.OAuth2FeignRequestInterceptor;
1112
import org.springframework.context.annotation.Bean;
@@ -15,6 +16,7 @@
1516
import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails;
1617
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
1718
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
19+
import org.springframework.web.reactive.function.client.WebClient;
1820

1921
@SpringBootApplication
2022
@EnableDiscoveryClient
@@ -44,4 +46,10 @@ public RequestInterceptor oauth2FeignRequestInterceptor(){
4446
public OAuth2RestTemplate clientCredentialsRestTemplate() {
4547
return new OAuth2RestTemplate(clientCredentialsResourceDetails());
4648
}
49+
50+
@Bean
51+
@LoadBalanced
52+
public WebClient.Builder loadBalancedWebClientBuilder() {
53+
return WebClient.builder();
54+
}
4755
}

analytics-service/src/main/java/com/emprovise/service/api/FinanceController.java

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,49 @@
11
package com.emprovise.service.api;
22

33
import com.emprovise.service.client.FinanceServiceClient;
4+
import com.emprovise.service.dto.StockDetail;
45
import com.emprovise.service.dto.StockDetailDTO;
56
import com.google.gson.Gson;
67
import org.springframework.beans.factory.annotation.Autowired;
78
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
9+
import org.springframework.cloud.netflix.hystrix.HystrixCommands;
10+
import org.springframework.web.bind.annotation.GetMapping;
11+
import org.springframework.web.bind.annotation.PathVariable;
812
import org.springframework.web.bind.annotation.RequestMapping;
913
import org.springframework.web.bind.annotation.RestController;
14+
import org.springframework.web.reactive.function.client.WebClient;
15+
import reactor.core.publisher.Flux;
1016

1117
@EnableEurekaClient
1218
@RestController
19+
@RequestMapping("/finance")
1320
public class FinanceController {
1421

1522
@Autowired
1623
private FinanceServiceClient financeServiceClient;
24+
@Autowired
25+
private WebClient.Builder webClientBuilder;
1726

18-
@RequestMapping("/finance")
19-
public String finance() {
20-
StockDetailDTO stockDetailDTO = financeServiceClient.getFinanceService("MSFT", "60min");
27+
@GetMapping("/stock/{symbol}")
28+
public String getStock(@PathVariable String symbol) {
29+
StockDetailDTO stockDetailDTO = financeServiceClient.getFinanceService(symbol, "60min");
2130
Gson gson = new Gson();
2231
return gson.toJson(stockDetailDTO);
2332
}
2433

25-
@RequestMapping("/greeting/view")
34+
@GetMapping("/stock/summary/{name}")
35+
public Flux<StockDetail> getStockSummary(@PathVariable String name) {
36+
Flux<StockDetail> stockDetailFlux = webClientBuilder.build()
37+
.get().uri("http://data-service/stocks/name/{name}", name)
38+
.retrieve().bodyToFlux(StockDetail.class);
39+
40+
return HystrixCommands.from(stockDetailFlux)
41+
.fallback(Flux.just(new StockDetail()))
42+
.commandName("getStockSummary")
43+
.toFlux();
44+
}
45+
46+
@GetMapping("/greeting")
2647
public String greeting() {
2748
return financeServiceClient.greeting();
2849
}

sqldb-service/src/main/java/com/emprovise/service/sqldbservice/dto/StockDetails.java renamed to analytics-service/src/main/java/com/emprovise/service/dto/StockDetail.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
package com.emprovise.service.sqldbservice.dto;
1+
package com.emprovise.service.dto;
22

33
import java.util.Date;
44

5-
public class StockDetails {
5+
public class StockDetail {
66

77
private String stockName;
88
private Double high;
99
private Double low;
1010
private Double open;
1111
private Double close;
12-
private Date date = new Date();
12+
private Date date;
1313

14-
public StockDetails() {
14+
public StockDetail() {
1515
}
1616

1717
public String getStockName() {
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# ----------------------------------------
2+
# Gradle Project Properties
3+
# ----------------------------------------
4+
5+
info.build.version=${version?:1.0}

analytics-service/src/main/resources/bootstrap.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,3 @@ spring:
88
username: user
99
password: ${CONFIG_SERVICE_PASSWORD}
1010

11-
info.build.version: ${version?:1.0}

authorization-service/README.md

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,59 @@
11
Authorization Service
22
=============
3+
## OAuth 2.0
34

4-
### Running the application
5+
OAuth 2.0 is the industry-standard protocol for authorization. The OAuth 2.0 specification defines a delegation protocol that is useful for conveying authorization decisions (via a token) across a network of web-enabled applications and APIs.
6+
OAuth 2.0 is not an authentication protocol and is not primarily used to identify a user. Although it is essential to authenticate both the user and the client in any authorization flow defined by the protocol.
7+
There are number of grant types/methods for a client application to acquire an access token which can be used to authenticate a request to an API endpoint.
8+
The client authentication enforces the use of the API only by known clients. On contrary, the serialized access token once generated, is not bound to a specific client directly.
9+
10+
## OAuth2 Roles
11+
12+
* **Resource owner (the User)**: An entity capable of granting access to a protected resource. Also referred as an end-user.
13+
* **Resource server (the API server)**: The server hosting the protected resources, capable of accepting and responding to protected resource requests using access tokens.
14+
* **Client**: An application making protected resource requests on behalf of the resource owner and with its authorization.
15+
* **Authorization server**: The server issuing access tokens to the client after successfully authenticating the resource owner and obtaining authorization.
16+
17+
## Grant Types
18+
19+
When a client application wants access to the resources of a resource owner hosted on a resource server, the client application must first obtain an authorization grant. OAuth2 provides [several authorization grants](https://alexbilbie.com/guide-to-oauth-2-grants/). Each grant type serves a different purpose and is used in a different way. Below are OAuth2 grant types:
20+
21+
* **Authorization Code**:
22+
The client redirects the user to the authorization server with parameters, response_type as code, client_id, redirect_uri and scope. The authorization server validates the request and asks user to login. The user login into the authorization server and approves the client. Upon user's approval the client is redirected to the redirect URI with parameters, state and authorization code. The client then sends a POST request to the authorization server with parameters, grant_type as authorization_code, client_id, client_secret, redirect_uri and code with the authorization code from the query string. The authorization server responds with a JSON object containing token_type as Bearer, expires_in, access_token and refresh_token.
23+
24+
* **Implicit**:
25+
The implicit grant is intended to be used for single page web apps which can’t keep client secret because all of the application code and storage is easily accessible. Here the authorization server returns an access token instead of an authorization code. The client redirects the user to the authorization server with parameters, response_type as token, client_id, redirect_uri and scope. The authorization server validates the request and asks user to login. The user login into the authorization server and approves the client. Upon user's approval the client is redirected to the redirect URI with parameters, containing token_type as Bearer, expires_in and access_token. It does not return a refresh token.
26+
27+
* **Resource Owner Password Credentials**:
28+
It is mainly used by trusted first party clients. The client asks the user for their authorization credentials (username and password). The client then sends a POST request to authorization server with parameters, grant_type as password, client_id, client_secret, scope, username and password. The authorization server responds with a JSON object containing token_type as Bearer, expires_in, access_token and refresh_token.
29+
30+
* **Client Credentials**:
31+
It is used for machine-to-machine authentication where no specific user's permission is required to access data. The client sends a POST request to the authorization server with parameters, grant_type as client_credentials, client_id, client_secret and scope. The authorization server responds with a JSON object containing token_type as Bearer, expires_in and access_token.
32+
33+
* **Refresh token**:
34+
It is used to get a new access token after expiration of current access token. The client sends a POST request to the authorization server with parameters, grant_type as refresh_token, refresh_token, client_id, client_secret and scope. The authorization server will respond with a JSON object containing token_type as Bearer, expires_in, access_token and refresh_token.
35+
36+
### Installation and Running of PostgreSQL Server
37+
38+
* Download latest [Windows PostgreSQL Installer](https://www.postgresql.org/download/windows/) and follow windows installation steps.
39+
* Alternatively, can download [Windows PostgreSQL Binary Archive](https://www.enterprisedb.com/download-postgresql-binaries) and extract the zip file. POSTGRE_SQL_HOME is the path to the unzipped PostgreSQL **pgsql** directory.
40+
* Run the below [pg_ctl](https://www.postgresql.org/docs/9.5/static/app-pg-ctl.html) utility commands to register PostGreSQL as service in POSTGRE_SQL_HOME/pgsql/bin directory.
41+
* Create a new user named **appuser** and new database named **testdb** using below **psql** commands. The user and password are added to auth-service.yml configuration file as spring.datasource.username (and password).
42+
* PostGreSQL runs on default port 5432.
43+
44+
45+
createuser --password postgres
46+
pg_ctl.exe register -N postgres -U appuser -P secret -D "POSTGRE_SQL_HOME/pgsql/data"
47+
pg_ctl.exe register -N postgres -D "POSTGRE_SQL_HOME/pgsql/data"
48+
pg_ctl.exe -D "POSTGRE_SQL_HOME/pgsql/data" -l logfile start
49+
psql -U postgres
50+
psql -U appuser postgres
51+
create user root with password 'verysecret';
52+
alter user root createdb;
53+
create database testdb;
54+
\c testdb;
55+
56+
### Running the Authorization Service
557

658
Pass the new AUTH_SERVICE_PASSWORD, CONFIG_SERVICE_PASSWORD from the [config-service](/../config-service/README.md) to access auth-service.yml configuration file, corresponding passwords FINANCE_SERVICE_PASSWORD for finance-service and ANALYTICS_SERVICE_PASSWORD for analytics-service respectively.
759

@@ -125,3 +177,6 @@ Pass the new AUTH_SERVICE_PASSWORD, CONFIG_SERVICE_PASSWORD from the [config-ser
125177
}
126178
}
127179

180+
### Notes
181+
182+
* Authorization service uses [MapStruct](http://mapstruct.org/) for mapping between domain object to DTO object. MapStruct requires [mapstruct-processor](https://github.com/mapstruct/mapstruct) to be configured in gradle to generate the corresponding Mapper implementation for defined MapStruct interface. Hence it is highly recommended to **run gradle build before running authorization-service** to avoid Spring NoSuchBeanDefinitionException for MapStruct autowirings.

authorization-service/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ dependencies {
4242
runtime('net.logstash.logback:logstash-logback-encoder:5.1')
4343
runtime('org.postgresql:postgresql:42.2.2')
4444
testCompile('org.springframework.boot:spring-boot-starter-test')
45-
apt "org.mapstruct:mapstruct-processor:${mapstructVersion}"
45+
apt "org.mapstruct:mapstruct-processor:${mapstructVersion}"
4646
}
4747

4848
dependencyManagement {
@@ -52,7 +52,7 @@ dependencyManagement {
5252
}
5353

5454
processResources {
55-
filesMatching("**/bootstrap.yml") {
55+
filesMatching("**/application.properties") {
5656
expand(project.properties)
5757
}
5858
}

0 commit comments

Comments
 (0)