Skip to content

Commit afe19e2

Browse files
authored
add spring-petclinic-microservices to this repo (#49)
1 parent 5a19daa commit afe19e2

169 files changed

Lines changed: 17456 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# top-most EditorConfig file
2+
root = true
3+
4+
[*]
5+
charset = utf-8
6+
end_of_line = lf
7+
insert_final_newline = true
8+
indent_style = space
9+
10+
[*.{java,xml}]
11+
indent_size = 4
12+
trim_trailing_whitespace = true
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Maven
2+
target/
3+
!.mvn/wrapper/maven-wrapper.jar
4+
5+
# Jenv
6+
.java-version
7+
8+
# Eclipse
9+
.settings/
10+
.classpath
11+
.project
12+
13+
# IntelliJ IDEA
14+
.idea
15+
*.iml
16+
17+
# Branch switching
18+
generated/
19+
20+
# Skip scripts
21+
.scripts/
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* Copyright 2007-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
import java.net.*;
17+
import java.io.*;
18+
import java.nio.channels.*;
19+
import java.util.Properties;
20+
21+
public class MavenWrapperDownloader {
22+
23+
private static final String WRAPPER_VERSION = "0.5.4";
24+
/**
25+
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
26+
*/
27+
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
28+
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + " .jar";
29+
30+
/**
31+
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
32+
* use instead of the default one.
33+
*/
34+
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
35+
".mvn/wrapper/maven-wrapper.properties";
36+
37+
/**
38+
* Path where the maven-wrapper.jar will be saved to.
39+
*/
40+
private static final String MAVEN_WRAPPER_JAR_PATH =
41+
".mvn/wrapper/maven-wrapper.jar";
42+
43+
/**
44+
* Name of the property which should be used to override the default download url for the wrapper.
45+
*/
46+
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
47+
48+
public static void main(String args[]) {
49+
System.out.println("- Downloader started");
50+
File baseDirectory = new File(args[0]);
51+
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
52+
53+
// If the maven-wrapper.properties exists, read it and check if it contains a custom
54+
// wrapperUrl parameter.
55+
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
56+
String url = DEFAULT_DOWNLOAD_URL;
57+
if(mavenWrapperPropertyFile.exists()) {
58+
FileInputStream mavenWrapperPropertyFileInputStream = null;
59+
try {
60+
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
61+
Properties mavenWrapperProperties = new Properties();
62+
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
63+
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
64+
} catch (IOException e) {
65+
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
66+
} finally {
67+
try {
68+
if(mavenWrapperPropertyFileInputStream != null) {
69+
mavenWrapperPropertyFileInputStream.close();
70+
}
71+
} catch (IOException e) {
72+
// Ignore ...
73+
}
74+
}
75+
}
76+
System.out.println("- Downloading from: " + url);
77+
78+
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
79+
if(!outputFile.getParentFile().exists()) {
80+
if(!outputFile.getParentFile().mkdirs()) {
81+
System.out.println(
82+
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
83+
}
84+
}
85+
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
86+
try {
87+
downloadFileFromURL(url, outputFile);
88+
System.out.println("Done");
89+
System.exit(0);
90+
} catch (Throwable e) {
91+
System.out.println("- Error downloading");
92+
e.printStackTrace();
93+
System.exit(1);
94+
}
95+
}
96+
97+
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
98+
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
99+
String username = System.getenv("MVNW_USERNAME");
100+
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
101+
Authenticator.setDefault(new Authenticator() {
102+
@Override
103+
protected PasswordAuthentication getPasswordAuthentication() {
104+
return new PasswordAuthentication(username, password);
105+
}
106+
});
107+
}
108+
URL website = new URL(urlString);
109+
ReadableByteChannel rbc;
110+
rbc = Channels.newChannel(website.openStream());
111+
FileOutputStream fos = new FileOutputStream(destination);
112+
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
113+
fos.close();
114+
rbc.close();
115+
}
116+
117+
}
49.5 KB
Binary file not shown.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip
2+
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.4/maven-wrapper-0.5.4.jar
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#!/usr/bin/env bash
2+
3+
# ==== Resource Group ====
4+
export SUBSCRIPTION=subscription-id # customize this
5+
export RESOURCE_GROUP=resource-group-name # customize this
6+
export LOCATION=SouthCentralUS #customize this
7+
export COSMOSDB_NAME=mycosmosdbaccname # customize this
8+
export REDIS_NAME=myredisname #customize this
9+
export KEYVAULT_NAME=myend2endkv #customize this
10+
export APP_NAME_FOR_KEYVAULT=myappforkeyvault #customize this
11+
12+
# ==== Create ResouceGroup ====
13+
echo "Creating ResouceGroup, it may take a few minutes"
14+
az group create --name ${RESOURCE_GROUP} \
15+
--location ${LOCATION}
16+
17+
# ==== Create CosmosDB Account ====
18+
echo "Creating CosmosDB Account, it may take a few minutes"
19+
az cosmosdb create --name $COSMOSDB_NAME --resource-group $RESOURCE_GROUP
20+
COSMOS_KEYS=$(az cosmosdb keys list --name $COSMOSDB_NAME --resource-group $RESOURCE_GROUP --type keys)
21+
COSMOS_PRIMARY_KEY=$(echo $COSMOS_KEYS | jq -r .primaryMasterKey)
22+
COSMOS_SECONDARY_KEY=$(echo $COSMOS_KEYS | jq -r .secondaryMasterKey)
23+
COSMOSDB_URI=$(az cosmosdb show --name $COSMOSDB_NAME --resource-group $RESOURCE_GROUP | jq -r .documentEndpoint)
24+
25+
# ==== Create Redis Cache Account ====
26+
echo "Creating Redis Cache Account, it may take a few minutes"
27+
az redis create --name $REDIS_NAME --resource-group $RESOURCE_GROUP --sku Basic --vm-size c0 --location $LOCATION
28+
REDIS_HOSTNAME=$(az redis show --name $REDIS_NAME --resource-group $RESOURCE_GROUP | jq -r .hostName)
29+
REDIS_PASSWORD=$(az redis list-keys --name $REDIS_NAME --resource-group $RESOURCE_GROUP | jq -r .primaryKey)
30+
31+
# ==== Create KeyVault Account ====
32+
echo "Creating KeyVault Account, it may take a few minutes"
33+
az keyvault create --location $LOCATION --name $KEYVAULT_NAME --resource-group $RESOURCE_GROUP
34+
35+
SERVICE_PRINCIPAL=$(az ad sp create-for-rbac --name ${APP_NAME_FOR_KEYVAULT} --role Contributor)
36+
37+
AZURE_KEYVAULT_URI=$(az keyvault show --name $KEYVAULT_NAME --resource-group $RESOURCE_GROUP | jq -r .properties | jq -r .vaultUri)
38+
AZURE_KEYVAULT_CLIENTID=$(echo $SERVICE_PRINCIPAL | jq -r .appId)
39+
AZURE_KEYVAULT_TENANTID=$(echo $SERVICE_PRINCIPAL | jq -r .tenant)
40+
AZURE_KEYVAULT_CLIENTKEY=$(echo $SERVICE_PRINCIPAL | jq -r .password)
41+
42+
# set keyvault policy
43+
az keyvault set-policy -n $KEYVAULT_NAME --key-permissions get list \
44+
--certificate-permissions get list \
45+
--secret-permissions get list \
46+
--resource-group $RESOURCE_GROUP \
47+
--spn $AZURE_KEYVAULT_CLIENTID
48+
49+
# ==== add keys to keyvault ====
50+
echo "add keys to keyvault"
51+
az keyvault secret set --vault-name $KEYVAULT_NAME --name cosmosdburi --value $COSMOSDB_URI
52+
az keyvault secret set --vault-name $KEYVAULT_NAME --name cosmosdbkey --value $COSMOS_PRIMARY_KEY
53+
az keyvault secret set --vault-name $KEYVAULT_NAME --name cosmosdbsecondarykey --value $COSMOS_SECONDARY_KEY
54+
az keyvault secret set --vault-name $KEYVAULT_NAME --name redisuri --value $REDIS_HOSTNAME
55+
az keyvault secret set --vault-name $KEYVAULT_NAME --name redispassword --value $REDIS_PASSWORD
56+
57+
58+
# ==== Create Kevvault environment file for Docker containers ====
59+
cat > keyvault.env << EOF
60+
AZURE_KEYVAULT_URI=$AZURE_KEYVAULT_URI
61+
AZURE_KEYVAULT_CLIENTID=$AZURE_KEYVAULT_CLIENTID
62+
AZURE_KEYVAULT_TENANTID=$AZURE_KEYVAULT_TENANTID
63+
AZURE_KEYVAULT_CLIENTKEY=$AZURE_KEYVAULT_CLIENTKEY
64+
EOF
65+
echo "environment configuration complete"
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
language: java
2+
jdk: openjdk8
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Copyright 2002-2020 the original author or authors.
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# Distributed version of the Spring PetClinic Sample Application built with Spring Cloud
2+
3+
[![Build Status](https://travis-ci.org/spring-petclinic/spring-petclinic-microservices.svg?branch=master)](https://travis-ci.org/spring-petclinic/spring-petclinic-microservices/) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
4+
5+
This microservices branch was initially derived from [AngularJS version](https://github.com/spring-petclinic/spring-petclinic-angular1) to demonstrate how to split sample Spring application into [microservices](http://www.martinfowler.com/articles/microservices.html).
6+
To achieve that goal we use Spring Cloud Gateway, Spring Cloud Circuit Breaker, Spring Cloud Config, Spring Cloud Sleuth, Resilience4j, Micrometer
7+
and the Eureka Service Discovery from the [Spring Cloud Netflix](https://github.com/spring-cloud/spring-cloud-netflix) technology stack.
8+
9+
## Starting services locally without Docker
10+
11+
Every microservice is a Spring Boot application and can be started locally using IDE or `../mvnw spring-boot:run` command. Please note that supporting services (Config and Discovery Server) must be started before any other application (Customers, Vets, Visits and API).
12+
Startup of Tracing server, Admin server, Grafana and Prometheus is optional.
13+
If everything goes well, you can access the following services at given location:
14+
* Discovery Server - http://localhost:8761
15+
* Config Server - http://localhost:8888
16+
* AngularJS frontend (API Gateway) - http://localhost:8080
17+
* Customers, Vets and Visits Services - random port, check Eureka Dashboard
18+
* Tracing Server (Zipkin) - http://localhost:9411/zipkin/ (we use [openzipkin](https://github.com/openzipkin/zipkin/tree/master/zipkin-server))
19+
* Admin Server (Spring Boot Admin) - http://localhost:9090
20+
* Grafana Dashboards - http://localhost:3000
21+
* Prometheus - http://localhost:9091
22+
23+
You can tell Config Server to use your local Git repository by using `native` Spring profile and setting
24+
`GIT_REPO` environment variable, for example:
25+
`-Dspring.profiles.active=native -DGIT_REPO=/projects/spring-petclinic-microservices-config`
26+
27+
## Starting services locally with docker-compose
28+
In order to start entire infrastructure using Docker, you have to build images by executing `./mvnw clean install -P buildDocker`
29+
from a project root. Once images are ready, you can start them with a single command
30+
`docker-compose up`. Containers startup order is coordinated with [`dockerize` script](https://github.com/jwilder/dockerize).
31+
After starting services it takes a while for API Gateway to be in sync with service registry,
32+
so don't be scared of initial Spring Cloud Gateway timeouts. You can track services availability using Eureka dashboard
33+
available by default at http://localhost:8761.
34+
35+
The `master` branch uses an Alpine linux with JRE 8 as Docker base. You will find a Java 11 version in the `release/java11` branch.
36+
37+
*NOTE: Under MacOSX or Windows, make sure that the Docker VM has enough memory to run the microservices. The default settings
38+
are usually not enough and make the `docker-compose up` painfully slow.*
39+
40+
## Understanding the Spring Petclinic application
41+
42+
[See the presentation of the Spring Petclinic Framework version](http://fr.slideshare.net/AntoineRey/spring-framework-petclinic-sample-application)
43+
44+
[A blog bost introducing the Spring Petclinic Microsevices](http://javaetmoi.com/2018/10/architecture-microservices-avec-spring-cloud/) (french language)
45+
46+
You can then access petclinic here: http://localhost:8080/
47+
48+
![Spring Petclinic Microservices screenshot](docs/application-screenshot.png)
49+
50+
**Architecture diagram of the Spring Petclinic Microservices with CosmosDB**
51+
52+
![Spring Petclinic Microservices architecture](docs/microservices-architecture-diagram-cosmosdb.jpg)
53+
54+
## In case you find a bug/suggested improvement for Spring Petclinic Microservices
55+
56+
Our issue tracker is available here: https://github.com/spring-petclinic/spring-petclinic-microservices/issues
57+
58+
## Custom metrics monitoring
59+
60+
Grafana and Prometheus are included in the `docker-compose.yml` configuration, and the public facing applications
61+
have been instrumented with [MicroMeter](https://micrometer.io) to collect JVM and custom business metrics.
62+
63+
A JMeter load testing script is available to stress the application and generate metrics: [petclinic_test_plan.jmx](spring-petclinic-api-gateway/src/test/jmeter/petclinic_test_plan.jmx)
64+
65+
![Grafana metrics dashboard](docs/grafana-custom-metrics-dashboard.png)
66+
67+
### Using Prometheus
68+
69+
* Prometheus can be accessed from your local machine at http://localhost:9091
70+
71+
### Using Grafana with Prometheus
72+
73+
* An anonymous access and a Prometheus datasource are setup.
74+
* A `Spring Petclinic Metrics` Dashboard is available at the URL http://localhost:3000/d/69JXeR0iw/spring-petclinic-metrics.
75+
You will find the JSON configuration file here: [docker/grafana/dashboards/grafana-petclinic-dashboard.json]().
76+
* You may create your own dashboard or import the [Micrometer/SpringBoot dashboard](https://grafana.com/dashboards/4701) via the Import Dashboard menu item.
77+
The id for this dashboard is `4701`.
78+
79+
### Custom metrics
80+
Spring Boot registers a lot number of core metrics: JVM, CPU, Tomcat, Logback...
81+
The Spring Boot auto-configuration enables the instrumentation of requests handled by Spring MVC.
82+
All those three REST controllers `OwnerResource`, `PetResource` and `VisitResource` have been instrumented by the `@Timed` Micrometer annotation at class level.
83+
84+
* `customers-service` application has the following custom metrics enabled:
85+
* @Timed: `petclinic.owner`
86+
* @Timed: `petclinic.pet`
87+
* `visits-service` application has the following custom metrics enabled:
88+
* @Timed: `petclinic.visit`
89+
90+
## Looking for something in particular?
91+
92+
| Spring Cloud components | Resources |
93+
|---------------------------------|------------|
94+
| Configuration server | [Config server properties](spring-petclinic-config-server/src/main/resources/application.yml) and [Configuration repository] |
95+
| Service Discovery | [Eureka server](spring-petclinic-discovery-server) and [Service discovery client](spring-petclinic-vets-service/src/main/java/org/springframework/samples/petclinic/vets/VetsServiceApplication.java) |
96+
| API Gateway | [Spring Cloud Gateway starter](spring-petclinic-api-gateway/pom.xml) and [Routing configuration](/spring-petclinic-api-gateway/src/main/resources/application.yml) |
97+
| Docker Compose | [Spring Boot with Docker guide](https://spring.io/guides/gs/spring-boot-docker/) and [docker-compose file](docker-compose.yml) |
98+
| Circuit Breaker | [Resilience4j fallback method](spring-petclinic-api-gateway/src/main/java/org/springframework/samples/petclinic/api/boundary/web/ApiGatewayController.java) |
99+
| Grafana / Prometheus Monitoring | [Micrometer implementation](https://micrometer.io/), [Spring Boot Actuator Production Ready Metrics] |
100+
101+
Front-end module | Files |
102+
|-------------------|-------|
103+
| Node and NPM | [The frontend-maven-plugin plugin downloads/installs Node and NPM locally then runs Bower and Gulp](spring-petclinic-ui/pom.xml) |
104+
| Bower | [JavaScript libraries are defined by the manifest file bower.json](spring-petclinic-ui/bower.json) |
105+
| Gulp | [Tasks automated by Gulp: minify CSS and JS, generate CSS from LESS, copy other static resources](spring-petclinic-ui/gulpfile.js) |
106+
| Angular JS | [app.js, controllers and templates](spring-petclinic-ui/src/scripts/) |
107+
108+
109+
## Interesting Spring Petclinic forks
110+
111+
The Spring Petclinic master branch in the main [spring-projects](https://github.com/spring-projects/spring-petclinic)
112+
GitHub org is the "canonical" implementation, currently based on Spring Boot and Thymeleaf.
113+
114+
This [spring-petclinic-microservices](https://github.com/spring-petclinic/spring-petclinic-microservices/) project is one of the [several forks](https://spring-petclinic.github.io/docs/forks.html)
115+
hosted in a special GitHub org: [spring-petclinic](https://github.com/spring-petclinic).
116+
If you have a special interest in a different technology stack
117+
that could be used to implement the Pet Clinic then please join the community there.
118+
119+
120+
# Contributing
121+
122+
The [issue tracker](https://github.com/spring-petclinic/spring-petclinic-microservices/issues) is the preferred channel for bug reports, features requests and submitting pull requests.
123+
124+
For pull requests, editor preferences are available in the [editor config](.editorconfig) for easy use in common text editors. Read more and download plugins at <http://editorconfig.org>.
125+
126+
127+
[Configuration repository]: https://github.com/spring-petclinic/spring-petclinic-microservices-config
128+
[Spring Boot Actuator Production Ready Metrics]: https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-metrics.html

0 commit comments

Comments
 (0)