Spring Gateway deployment on external tomcat - spring

I am developing a micro-service solution with spring boot. I have 3 micro services:
authentication services (manages users, roles, permissions)
project service (services used to do CRUD actions on Project entity)
gateway (used as entry point of the solution, also used to validate token and route to services)
I want to deploy these on a tomcat server as war placed in the webapps (knowing that they have an embedded tomcat).
I am able to deploy the authentication and project services and they are reachable over the URI ** localhost:8080/authentication/* ** and ** /project/* *, but I'm unable to reach the gateway on ** localhost:8080/gateway/ **, it returns a 404
I am sure that the gateway is running cause it created the tables in the DB after deployment.
**Knowing that in eclipse it works fine (since i run each service on a port specified in the application.yml) i don't understand why when deploying the gateway on tomcat it is unreachable and always return a 404. I can see it in the tomcat manager as deployed.
Here is the pom.xml of the gateway :
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.1</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.myProject</groupId>
<artifactId>gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gateway</name>
<description>Gateway</description>
<profiles>
<profile>
<id>dev</id>
<properties>
<activatedProperties>dev</activatedProperties>
</properties>
</profile>
</profiles>
<properties>
<java.version>11</java.version>
<springfox-swagger.version>3.0.0</springfox-swagger.version>
</properties>
<dependencies>
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>21.1.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</project>
and here is my application.yml file :
spring:
cloud:
gateway:
routes:
- id: incident
uri: http://localhost:8080/project
predicates:
- Path=/gateway/v1/project/**
filters:
- RewritePath=/gateway/(?<RID>.*), /$\{RID}
- JwtFilter
- RemoveRequestHeader=Authorization
- id: authentication
uri: http://localhost:8080/auth
predicates:
- Path=/gateway/auth/**
filters:
- RewritePath=/gateway/(?<RID>.*), /$\{RID}
- id: userManagement
uri: http://localhost:8080/auth
predicates:
- Path=/gateway/v1/user/**,/gateway/v1/permission/**,/gateway/v1/role/**,/gateway/v1/role-permission/**,/gateway/v1/user-role/**
filters:
- RewritePath=/gateway/(?<RID>.*), /$\{RID}
- JwtFilter
- RemoveRequestHeader=Authorization
datasource:
url: jdbc:oracle:thin:#//xxx.xxx.xxx.xxx:1521/ORCLCDB.localdomain
username: xxx
password: xxx
jpa:
hibernate:
ddl-auto: update
id:
new_generator_mappings=true
properties:
hibernate:
temp:
use_jdbc_metadata_defaults: false
dialect: org.hibernate.dialect.Oracle12cDialect
physical_naming_strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
show-sql: true
logging:
level:
org.springframework: TRACE
org.hibernate.type: TRACE
org.apache.tomcat: INFO
org.apache.catalina: INFO
pattern:
console: "%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"
file: "%d %p %c{1.} [%t] %m%n"
file:
name: ./tomcat-logs/gateway
path: ./tomcat-logs/gateway

Spring Cloud Gateway is itself a Spring Boot WebFlux application. It's support only embedded server. Please check spring documentation
https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto-traditional-deployment

Related

Traefik throwing error 502 with Kotlin Spring Boot application

Ok so I'm facing an annoying issue with Traefik in Docker: it constantly throws an error 502: Bad Gateway when I'm trying to reach my HTTP service.
All I'm trying to do is add it as a simple load balancer to build 3 replicas of my Spring Boot app. The app works well when I remove anything concerning Traefik.
My Spring Boot Controller maps /api/v1 endpoint, which is working well without load balancing. I'm trying to map this same endpoint to Traefik, which is using port :80.
Dashboard at :8080 works just fine, I have no error whatsoever about my configuration mentioned in it; only problems when I'm reaching anything under :80.
I have to mention that this exact same configuration (docker-compose, traefik conf, postgres db, and spring boot app) DOES WORK fine with the exact same docker-compose.yml AND traefik.yml, which makes my problem even weirder. Maybe the issue comes from the fact that my Spring Boot app is made of Kotlin and not the one where it's working?. Anyway, here are my files:
# Dockerfile (default one generated)
FROM maven:latest
WORKDIR /usr/src/app
COPY . /usr/src/app
RUN mvn package
ENV PORT 5000
EXPOSE $PORT
CMD [ "sh", "-c", "mvn -Dserver.port=${PORT} spring-boot:run" ]
# docker-compose.yml (works as-is in my other app)
version: "3.8"
services:
project:
build: .
deploy:
replicas: 3
labels:
- "traefik.http.routers.project.rule=PathPrefix(`/api/v1`)" # same endpoint as in my Spring controller
- "traefik.http.middlewares.project.stripprefix.forceSlash=false"
- "traefik.http.routers.project.middlewares=project#docker"
traefik:
image: traefik:latest
restart: unless-stopped
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./traefik.yml:/etc/traefik/traefik.yml
postgres:
image: postgres:latest
container_name: postgres
ports:
- "5432:5432"
environment:
POSTGRES_PASSWORD: example
# rabbitmq:
# image: rabbitmq:management-alpine
# container_name: rabbitmq
# ports:
# - "5672:5672" # AMQP
# - "15672:15672" # HTTP (Management)
# traefik.yml
global:
checkNewVersion: true
sendAnonymousUsage: false
providers:
docker: {}
log:
level: DEBUG # temporarily
api:
insecure: true
entryPoints:
insecure:
address: ":80"
secure:
address: ":443"
# src/main/resources/application.yml
spring:
sql.init.mode: always
datasource:
url: jdbc:postgresql://localhost:5432,postgres:5432/postgres
username: postgres
password: example
jpa:
open-in-view: false
<!-- pom.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>project</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.4</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>17</java.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<kotlin.version>1.6.10</kotlin.version>
</properties>
<dependencies>
<!-- Kotlin -->
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
</dependency>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- PostgreSQL -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
</dependencies>
<build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<args>
<arg>-Xjsr305=strict</arg>
</args>
<compilerPlugins>
<plugin>spring</plugin>
</compilerPlugins>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
I'm using JDK 17, and docker-compose up --build to start everything. Thanks!

How to run flyway migration for reactive r2dbc driver on sprintboot stratup

I am working on springboot webflux project with non-blocking database driver r2dbc,
But when Springboot application start Flyway does not run migrations.
Below are my spring-boot pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>r2dbmigration</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>r2dbmigration</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot.experimental</groupId>
<artifactId>spring-boot-starter-data-r2dbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>io.r2dbc</groupId>
<artifactId>r2dbc-postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot.experimental</groupId>
<artifactId>spring-boot-test-autoconfigure-r2dbc</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot.experimental</groupId>
<artifactId>spring-boot-bom-r2dbc</artifactId>
<version>0.1.0.M3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
</project>
My migration file is : V1.1__create_file_import_table.sql
with content of
DROP TABLE IF EXISTS file_import;
CREATE TABLE file_import
(
id BIGINT GENERATED ALWAYS AS IDENTITY,
file_key CHARACTER VARYING(255) NOT NULL,
created_at TIMESTAMP without time zone NOT NULL,
created_by BIGINT NOT NULL,
PRIMARY KEY (id)
);
application.properties
spring.r2dbc.url= r2dbc:postgresql://localhost:5432/import
spring.r2dbc.username=postgres
spring.r2dbc.password=password
My application starts smoothly but there is no migration run.
Can someone please help me ?
Github URL
Thanks
The following Java implementation is based on #Sim's Kotlin example.
Example pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.RC1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>flyway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>flyway</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-r2dbc</artifactId>
</dependency>
<dependency>
<groupId>dev.miku</groupId>
<artifactId>r2dbc-mysql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
</project>
Example application.yml
---
spring:
r2dbc:
url: r2dbc:pool:mysql://localhost:3306/defaultdb
username: <user>
password: <pass>
flyway:
url: jdbc:mysql://localhost:3306/defaultdb
user: ${spring.r2dbc.username}
password: ${spring.r2dbc.password}
baseline-on-migrate: true
Add the following Spring Boot configuration - FlywayConfig.java
package com.example.flyway;
import org.flywaydb.core.Flyway;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
// https://stackoverflow.com/a/61412233
#Configuration
public class FlywayConfig {
private final Environment env;
public FlywayConfig(final Environment env) {
this.env = env;
}
#Bean(initMethod = "migrate")
public Flyway flyway() {
return new Flyway(Flyway.configure()
.baselineOnMigrate(true)
.dataSource(
env.getRequiredProperty("spring.flyway.url"),
env.getRequiredProperty("spring.flyway.user"),
env.getRequiredProperty("spring.flyway.password"))
);
}
}
First execution:
: Bootstrapping Spring Data R2DBC repositories in DEFAULT mode.
: Finished Spring Data repository scanning in 7ms. Found 0 R2DBC repository interfaces.
: Flyway Community Edition 6.4.1 by Redgate
: Database: jdbc:mysql://localhost:3306/defaultdb (MySQL 5.5)
: Successfully validated 1 migration (execution time 00:00.006s)
: Creating Schema History table `defaultdb`.`flyway_schema_history` ...
: DB: Name 'flyway_schema_history_pk' ignored for PRIMARY key. (SQL State: 42000 - Error Code: 1280)
: Current version of schema `defaultdb`: << Empty Schema >>
: Migrating schema `defaultdb` to version 1.0.001 - Initialise database tables
: Successfully applied 1 migration to schema `default` (execution time 00:00.036s)
: Netty started on port(s): 8080
:Started Application in 1.829 seconds (JVM running for 2.343)
Second execution:
: No active profile set, falling back to default profiles: default
: Bootstrapping Spring Data R2DBC repositories in DEFAULT mode.
: Finished Spring Data repository scanning in 11ms. Found 0 R2DBC repository interfaces.
: Flyway Community Edition 6.4.1 by Redgate
: Database: jdbc:mysql://localhost:3306/defaultdb (MySQL 5.5)
: Successfully validated 1 migration (execution time 00:00.009s)
: Current version of schema `defaultdb`: 1.0.001
: Schema `defaultdb` is up to date. No migration necessary.
: Netty started on port(s): 8080
: Started Application in 1.273 seconds (JVM running for 1.695)
A bit late answer, but you can also set up a Spring bean manually to handle the migration.
Add flyway config to application.yml (or .properties):
spring:
flyway:
url: jdbc:postgresql://localhost:5432/<db-name>
user: <user>
password: <password>
This code is Kotlin, but it can easily be translated to Java:
import org.flywaydb.core.Flyway
import org.springframework.boot.autoconfigure.flyway.FlywayProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
#Configuration
class FlywayConfig(private val flywayProperties: FlywayProperties) {
#Bean(initMethod = "migrate")
fun flyway(): Flyway? {
return Flyway(Flyway.configure()
.baselineOnMigrate(true)
.dataSource(flywayProperties.url, flywayProperties.user, flywayProperties.password)
)
}
}
Solved this by using the combination of Flyway + JDBC, and R2DBC for the rest of DB interactions.
application.properties
my.database.url=postgresql://localhost:5432}/my_database
spring.r2dbc.url=r2dbc:${my.database.url}
spring.r2dbc.username=user
spring.r2dbc.password=pass
spring.flyway.locations=classpath:db/migration
spring.flyway.enabled=true
spring.flyway.validate-on-migrate=true
spring.flyway.user=${spring.r2dbc.username}
spring.flyway.password=${spring.r2dbc.password}
spring.flyway.url=jdbc:${my.database.url}
build.gradle
dependencies {
...
implementation 'org.springframework.boot:spring-boot-starter-data-r2dbc'
runtimeOnly 'org.flywaydb:flyway-core:7.9.1'
runtimeOnly 'org.postgresql:postgresql:42.2.20'
runtimeOnly 'io.r2dbc:r2dbc-postgresql'
runtimeOnly 'org.springframework.boot:spring-boot-starter-jdbc'
...
}
Location of flyway migration SQL scripts:
src/main/resources/db/migration/V1__create_my_table.sql
It seems like there is no "official" solution for this problem yet, but there is a temporary solution to solve that: "R2DBC migration tool".
#Nikita Konev provide us a good temporary solution for this problem. I have been using that and works well.
Please check:
R2DBC support - Flyway: https://github.com/flyway/flyway/issues/2502
R2DBC migration tool: https://github.com/nkonev/r2dbc-migrate
Example project (you can play around): https://github.com/nkonev/r2dbc-migrate-example
Thanks to Nikita Konev
This might be delayed response, but personally, I prefer to just add the spring starter.
This worked for me:
// build.gradle.kts
implementation("org.flywaydb:flyway-core:7.9.1")
runtimeOnly("org.springframework.boot:spring-boot-starter-jdbc")
runtimeOnly("org.postgresql:postgresql:42.2.20")
Then your application.yml file can look like:
# application.yml
spring:
r2dbc:
url: r2dbc:postgresql://user:pass#host/db
flyway:
enabled: true
validate-on-migrate: true
user: user
password: pass
url: jdbc:postgresql://host:5432/db
schemas: ["schema"]
As mentioned in the comments: R2DBC and Flyway are not compatible yet.
A workaround is to execute Flyway migration using the Maven Flyway plugin, note that you need to provide a JDBC-URL.
In your case, you can trigger the migration via
mvn flyway:migrate -Dflyway.url=jdbc:postgresql://localhost:5432/import -Dflyway.user=postgres -Dflyway.password=password
or via
mvn flyway:migrate
if you add the plugin+configuration in your pom.xml
<plugin>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-maven-plugin</artifactId>
<version>6.1.3</version>
<configuration>
<url>jdbc:postgresql://localhost:5432/import</url>
<user>postgres</user>
<password>password</password>
</configuration>
</plugin>
execute the migration via

Access log not created

I'm trying to enable SpringBoot's embedded Tomcat access logs. When the application starts I'm not seeing the log file at all. When I make requests to the application from browser I still get nothing. What am I missing?
This should be really straight forward. I'm wondering if there's stuff in my project that's interfering with Tomcat logging to the access_log.log file. Within the project I've done the following:
enable ssl and changed port
Via #Configuration, I created a #Bean EmbeddedServletContainerCustomizer that adds a TomcatConnectorCustomizer.
Added Spring Security to request authentication for /secure/** URL patterns.
From what I've read none of that should require anything special regarding Tomcat access logs. With my set up I expect the logging to be in my-tomcat/access_log.log at the same location I ran the java -jar command. Correct me if that's wrong.
Using...
SpringBoot 1.5.9.RELEASE
Win 7 Enterprise
application.yml
server:
port: 8443
ssl:
# 6.2 Ensure SSLEnabled is set to True for Sensitive Connectors (Not Scored)
enabled: true
key-store: classpath:keystore.p12
key-store-password: password
key-store-type: PKCS12
key-alias: tomcat
# 6.5 Ensure SSL Protocol is set to TLS for Secure Connectors (Scored)
protocol: TLS
tomcat:
basedir: my-tomcat
accesslog:
enabled: true
pattern: '%t %a "%r" %s (%D ms)'
security:
require-ssl: true
# 7.1 Application specific logging (Scored)
logging:
level.com.esd.springbootdemo: DEBUG
# 7.2 Specify file handler in logging.properties files (Scored)
file: logs/springbootdemo.log
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.esd.springboot</groupId>
<artifactId>springboot-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springboot-demo</name>
<description>Spring Boot security and hardening POC</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Your tomcat YAML block is currently a child of the ssl YAML block - so you need to fix the indentation

Missing AWS properties when creating AWS application

I'm struggling to figure out how to add AWS properties to my application.properties (or application.yml) file, and I'm not sure what I have set up incorrectly in STS.
I can reproduce this creating a simple AWS app using Spring Initializr. I'm adding AWS, Consul and REST because that's what the real app is using. Here's the POM it generates.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>edu.dkist</groupId>
<artifactId>staging-service-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>staging-service-demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Dalston.SR4</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-aws</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
I'm not adding any code to the application for this sample, only the code that is generated. This was a test to see if something was wrong with the app I was working on. When I try to add an application property, nothing shows for AWS. The same is true if I create a YAML file.
If I force the issue, and add it anyway STS says the property is unknown.
Compiling the app throws an exception:
Caused by: java.lang.IllegalStateException: There is not EC2 meta data available, because the application is not running in the EC2 environment. Region detection is only possible if the application is running on a EC2 instance
The app is not running on an EC2 instance, it's running locally. From what I've read I need to add the aws.region.auto if it's not running on EC2, but I can't get the app to acknowledge the property exists. Same happens with the access key and secret key.
So... after lots of tinkering and reading other posts it looks like the properties will work if you add them, even if STS doesn't recognize them.
I added
cloud:
aws:
credentials:
instanceProfile: false
region:
static: eu-west-1
stack:
auto: false
and the program will run.
The other thing that was tripping me up is the inconsistency in the paths for the properties. For example Consul properties are at
spring.cloud.consul.*
where as AWS is at
cloud.aws.*
There's no "spring" to start the AWS properties. I'm sure there is a reason for the inconsistency, I just don't know it.

How to externalise spring application configuration using config server?

I have written my own config server to centralise configuration management and exposing application configuration using APIs. Now i want to consume configuration properties from spring and spring-boot applications. But i am not able to figure out the correct way for that. I tried placing my config server client code to listen for application context start event and reading configuration from config server. But i am not able to inject this configuration into other beans.
How can i read application configuration from config server (using rest client) and inject this read config to application environment for further processing ?
create an application that for config and your application
#SpringBootApplication
#EnableConfigServer
public class ConfigApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(ConfigApplication.class, args);
}
}
application.yml in config server
spring:
cloud:
config:
server:
native:
search-locations: classpath:/shared
profiles:
active: native
security:
user:
password: pass
server:
port: 8888
and create shared folder in src/main/resources/shared and your-service.yml like this
spring:
security:
basic:
enabled: false
server:
port: 8083
maven pom.xml in config server
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<finalName>config</finalName>
</configuration>
</plugin>
</plugins>
</build>
in your-service spring boot application add /src/main/resources/bootstrap.yml
like this
spring:
application:
name: your-service
cloud:
config:
uri: http://localhost:8888
fail-fast: true
username: user
password: pass
and add this dependency to your service
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
first run config server and then your spring boot service

Resources