===== Spring Boot ======
Spring boot - is a Java framework, which claims to retrieve the default configurations from the libraries loaded to the path.
==== Rest Controller ====
Logging the exposed endpoints.
To log the exposed endpoints the change in the application.properties is required:
application.properties
logging.level.web=TRACE
logging.level.org.springframework.web=TRACE
Example output
12:14:48.398 [main] TRACE o.s.w.s.m.m.a.RequestMappingHandlerMapping
i.d.l.d.g.RestGroupController:
{GET [/rest/, /rest/groups]}: index(String,Optional)
{POST /rest/groups, consumes [application/json]}: createGroup(Group)
{POST /rest/groups/{groupId}/member}: addUserToGroup(String,String)
{DELETE /rest/groups, consumes [application/json]}: deleteRole(String)
{GET [/rest/, /rest/groups/member/{memberId}]}: groupsByMember(String)
{GET [/rest/, /rest/groups/{id}]}: groupById(String)
{DELETE /rest/groups/{groupId}/member}: removeUserFromGroup(String,String)
12:14:48.418 [main] TRACE o.s.w.s.m.m.a.RequestMappingHandlerMapping
i.d.l.d.r.RestRoleController:
{GET [/rest/, /rest/roles]}: index(String,Optional)
{POST /rest/roles/{roleId}/member}: addMemberToRole(String,String,String)
{DELETE /rest/roles, consumes [application/json]}: deleteRole(String)
{POST /rest/roles, consumes [application/json]}: createRole(Role)
{DELETE /rest/roles/{roleId}/member}: removeUserFromRole(String,String,String)
===== New project =====
Use [[https://start.spring.io/|Spring Initializr]] to generate a new project.
Import it to the Idea IDE via:
{{https://lh3.googleusercontent.com/-eDxwVOJ3dzs/Wpp5XRC7hkI/AAAAAAAAADw/L4JVWKY-81gPOnyjZekGnsZt44ccnP6UgCHMYCw/s0/2018-03-03_11-30-52.png}}
===== Gradle =====
Spring boot is normally either
* packaged to an executable jar, together with dependencies, or
* packaged as a deployable war, so that it may be deployed to a Tomcat etc.
== Running the app ==
Running the app with gradle, choosing the port
./gradlew bootRun --args='--server.port=8888'
== Building a JAR ==
To create a Jar with gradle - add the following to build.gradle
to automagically resolve dependencies within the current spring boot version - you must apply a special plugin. \\
The dependencies will be resolved acording to the BOM - bill of materials. \\
Check https://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/gradle-plugin/reference/html/#packaging-executable-jars
apply plugin: 'io.spring.dependency-management'
Build the jar by using **gradlew**. \\ This will produce a JAR e.g. under **build\libs\PROJECTNAME\complete.jar**
../../gradlew BootJar
Start the jar
java -jar complete.jar
{{https://lh3.googleusercontent.com/-nSi9oHOqYxY/Wphe7hn3NKI/AAAAAAAAADY/Pc9ecqMiTpIkSgR9VfKIcDAft7SrIN8wQCHMYCw/s0/2018-03-01_21-13-31.png}}
== Building a WAR ==
build.gradle
apply plugin: 'io.spring.dependency-management'
apply plugin: 'war'
Build the jar by using **gradlew**. \\ This will produce a JAR e.g. under **build\libs\PROJECTNAME\complete.war**
../../gradlew BootWar
===== Spring Profiles ======
Spring profiles can be activated in multiple ways, e.g.
by setting the environment variable
export spring_profiles_active=dev
by passing an argument to the java virtual machine
-Dspring.profiles.active=dev
When activated - you get the option to create a profile dependant properties files.
* .properties files are located in /resources/application-{profile}.properties
* ./resources/application-dev.properties
* ./resources/application-stage.properties
* ./resources/application-prod.properties *
* ./resources/application.properties - is the default file, which is active
* .properties files are additive
To pick a default profile - you need to set in in applicaiton.properties
application.properties
# the default profile which is used. Can be overridden by specifying the Spring profile as -Dspring.profiles.active or in another way.
# without that the "spring.profiles.active" will not fall back to the value "default"
spring.profiles.active=dev
==== Continous build ====
Spring boot applications - can be configured to
- react on file changes
- rebuild the application e.g. to a jar
- redeploy the jar, e.g. to the ThomCat
== Step 1 ==
Add dev-tools to the dependencies,
so that the rebuilt app is hot-swaped on the app server.
In **build.gradle**
dependencies {
// makes Spring boot hot swap rebuilt jar to tomcat
developmentOnly 'org.springframework.boot:spring-boot-devtools'
}
== Step 2 ==
In a separate terminal, start the continuous build of application.
Do that in a separate terminal, because the command doesn't come back, but listens for file changes.
It works in **Vagrant**, in a **Ubuntu guest-VM**, on **host-Windows**, on a "shared-folder".
But unfortunately, changes, originating form **vagrant-host-machine** - are NOT recognized.
To trigger rebuild, hot-swap - one needs to change some file in the **vagrant-guest-machine**.
Starts continuos build skipping the tests
./gradlew build -xtest --continuous
To propagate a change triggering a rebuild - you need to modify the file on the guest-system
echo "" >> HelloController.java
== Step3 Launch the app ==
The app will be built and propagated
./gradlew bootRun --args='--server.port=8888'
====== Native Image ======
# Prerequisites
Install java
# java open GraalVM from liberica "native image kit"
sdk install java 22.3.r17-nik < /dev/null
# switch
sdk use java 22.3.r17-nik
# set the Java_home
source "~/.sdkman/bin/sdkman-init.sh"
# Quickstart
Build a native image
./gradlew nativeCompile
[native-image-plugin] Native Image written to: /PROJECTDIR/throttling-enforcer/build/native/nativeCompile
Run
/PROJECTDIR/throttling-enforcer/build/native/nativeCompile/demo
===== Rest Controller ====
CRUD repositories ''CrudRepository''
can create queries by convention.
Just name the methods according to the convention https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation
and they will be mapped to queries.
===== API Versioning ====
URI Versioning - Twitter
* http://localhost:8080/vl/person
* http://localhost:8080/v2/person
Request Parameter versioning - Amazon
* http://localhost:8080/person?version=l
* http://localhost:8080/pcrson?vcrsion=2
(Custom) headers versioning - Microsoft
* SAME-URL headers=(X-API-VERSION=l]
* SAME-URL headers=[X-API-VERSION=2]
Media type versioning - GitHub
* SAME-URL produces=application/vnd.company.app-vl+json
* SAME-URL produces=application/vnd.company.app-v2+json
===== Libs =====
==== Hystrix - Circuit Breaker ====
https://www.baeldung.com/spring-cloud-netflix-hystrix
==== Feign - declarative REST client ====
Reduces the glue-code to the minimum.
Need only to express - what to call and receive the response DTO
https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-feign.html
package com.in28minutes.microservices.currencyconversionservice;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(name = "currency-exchange-service", url = "localhost:8000")
public interface CurrencyExchangeServiceProxy {
@GetMapping("/currency-exchange/from/{from}/to/{to}")
public CurrencyConversionBean retrieveExchangeValue
(@PathVariable("from") String from, @PathVariable("to") String to);
}
==== Ribbon - Client based load balancer ====
Exposes multiple deployments under one URL
{{https://s3.eu-central-1.amazonaws.com/alf-digital-wiki-pics/sharex/K9ELIqz2Uf.png}}
{{https://s3.eu-central-1.amazonaws.com/alf-digital-wiki-pics/sharex/Od4LgsV7Ij.png}}
==== Zuul API Gateway ====
API Gateway in SPring
==== EUreka Namingserver ====
Allows to register / discover services on a naming server.
Has a GUI to list available services.
{{https://s3.eu-central-1.amazonaws.com/alf-digital-wiki-pics/sharex/qVkyO04yvD.png}}
==== Cloud Sleuth - unique tracing id to requests ====
adds a unique tracing id to requests
==== Zipkin - Distributed Tracing Server ====
Central tracing server.
* Like ELK.
* and CloudWatch
{{https://s3.eu-central-1.amazonaws.com/alf-digital-wiki-pics/sharex/ce868zFAte.png}}
{{https://s3.eu-central-1.amazonaws.com/alf-digital-wiki-pics/sharex/EG0bVz0lrr.png}}
==== Spring Cloud Bus ====
Can use it to refresh the configs of all services,
by sending a message via the bus.
===== Docker =====
== Build manually without gradle ==
docker build --build-arg JAR_FILE=build/libs/\*.jar -t springio/demo-consume-api -f src/main/docker/Dockerfile .
== Build with Gradle ==
You can build a tagged docker image with Gradle in one command:
sudo su
./gradlew bootBuildImage --imageName=springio/demo-consume-api
sudo docker images
== And run ==
sudo docker run -p 8080:8080 springio/demo-consume-api