Table of Contents

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 Spring Initializr to generate a new project.

Import it to the Idea IDE via:

Gradle

Spring boot is normally either

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

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.

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”.<br> But unfortunately, changes, originating form vagrant-host-machine - are NOT recognized.<br> 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<Entity, Id>

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

Request Parameter versioning - Amazon

(Custom) headers versioning - Microsoft

Media type versioning - GitHub

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

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.

Cloud Sleuth - unique tracing id to requests

adds a unique tracing id to requests

Zipkin - Distributed Tracing Server

Central tracing server.

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