spring boot + docker + kubernetes - java

we have three environment as (dev, test and prod) and we have database configuration as below
spring:
jpa:
hibernate:
ddl-auto: update
datasource:
url: ${URL}
username: ${USERNAME}
password: ${PASSWORD}
What i am trying is that i create the jar and then build the image and when deploying in to the kubernetes , i will be using the dev , test and prod respective deployment.yaml in which i will be loading the url,username and password to env so the application will read it during prod start up
So when i am trying to build jar application try to connect to the database and it failed to create the jar.
Please let me know my understanding is wrong or right if wrong then how to correct it and just one thing is that i can't change the process i.e jar+ image + kubernetes

In Kubernetes you can put your configuration in Configmap or Secret. You can package the spring boot application and provide the Configmap entry as env variable of your container as exposed here
Using Spring Cloud Kubernetes you can also read these properties without any configuration on the container as explained in this article

Related

When restarting Spring Boot I see 'no profiles are currently active'

My Spring Boot version is 2.3.4-RELEASE. I configure DataSource this way in application-dev.yml:
spring:
profiles: dev
datasource:
master:
driver-class-name: com.mysql.jdbc.Driver
url: myUrl
slave:
driver-class-name: com.mysql.jdbc.Driver
url: myUrl
When I activate the 'dev' profile, I can start my Spring Boot container successfully, but when I restart it, I get this error:
Description:
Failed to configure a DataSource: 'url' attribute is not specified and
no embedded datasource could be configured.
Reason:
Failed to determine a suitable driver class
Action:
Consider the following:
If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently
active).
I tried to add the config: spring.datasource.url. It works, but I need to distinguish master and slave. How can I do that?
You must activate your profile using property spring.profiles.active
If you have database settings to be loaded from a particular profile
you may need to activate it (no profiles are currently active).
Read set the active Spring profiles to see how to do it

Monitoring jar application using Spring boot Admin

I have an spring boot application .jar, based on spring batch,and it is not a web application, and I'm using a ksh script to Launch it on my server side.
for some performance observation, we decide to install Spring Boot Admin for this app, using a "sba.war" that is already deployed in another web application on another server, I tried to drop the sba.war beside my applicationBatch.war after updating the application.yml file and import the SBA dependency on my build.gradle file :
spring:
datasource:
# BDD DEV
url: jdbc:oracle:thin:#xxxx:9999:AAAAA
username: xxxxxx
password: xxxxxx
# SBA DEV
boot:
admin:
client:
enabled: true
instance:
service-base-url: https://xxxxx.com
url: https://xxxxx.com/sba
username: username
password: password
so the problem is, that my application is not deployed on a tomcat server, it is runned by the ksh script on it's embeded server.
So can I anyhow use the embeded server of SBA to run it ?

Fallback option in Spring application properties in AWS

I have a REST service built with Spring Boot where I'm using an application.yml file to set up environment variables. The REST service will be deployed to Amazon Elastic Beanstalk. I have set up Environment Properties in the configuration for the Environment (Configuration -> Software Configuration -> Environment Properties)
I would like for the REST service to pick up the environment variables from AWS Environment Properties when they are available and then use environment variables specified in the application.yml file when the Environment Properties are not available as a fallback.
spring:
profiles: default
datasource:
type: org.mariadb.jdbc.MariaDbDataSource
driverClassName: org.mariadb.jdbc.Driver
url: jdbc:mariadb://localhost:3306/someDB
username: someUserName
password: somePassword
What I'm trying to achieve is that I wouldn't have to change the profile used in application.yml when I deploy on AWS or do development locally.
I've tried this which doesn't work
spring:
profiles: aws
datasource:
type: org.mariadb.jdbc.MariaDbDataSource
driverClassName: org.mariadb.jdbc.Driver
url: ${ADDRESS_FOR_RDS:jdbc:mariadb://localhost:3306/someDB}
username: ${USERNAME:someUserName}
password: ${PASSWORD:somePassword}
Trying to specify as ${AWS_PROPERTY_NAME:FALLBACK_OPTION} as per this Stack Overflow answer.
I have been able to get this working using Spring profiles, per this Stack Overflow question.

How to one-off run #DataJpaTest against real database instead of in-memory with Spring Boot

I am using Spring Boot 1.4.3 and have a whole bunch of tests that are annotated with #DataJpaTest. By default, they run against an in-memory database. I would like to be able to run all of them against a local MySQL temporarily. How can I do this in an easy way?
I have found that I can make it work for one by adding #ActiveProfiles("local") where I have an application-local.properties that points to my local MySQL, but it is just too much work to add that everywhere, run the tests and then remove it again (since I only want to run this manually against MySQL, the CI environment will run against the in memory db).
I am using Maven if that would matter.
UPDATE:
So I have an application-local.properties which contains the db properties to connect to my local MySQL database (Which I use already to run my application against the local MySQL)
Then I right-click in IntelliJ on a package and select "Run all tests in package". In the settings of that run configuration, I add -Dspring.profiles.active=local to the "VM options" field.
I would have thought that this would activate the local profile during the tests, but it does not. If I stop the local MySQL, the tests still run fine.
In the docs it states that you are able to remove the autoconfigured h2 datasource with #AutoConfigureTestDatabase(replace= Replace.NONE) on the test class https://docs.spring.io/spring-boot/docs/1.4.2.RELEASE/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications-testing-autoconfigured-jpa-test.
Also you then need to provide your db setup in properties, so that it does not use your app properties e.g.:
# Database
spring.datasource.url=jdbc:mariadb://localhost:3303/test
spring.datasource.username=test
spring.datasource.password=test
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql=true
i put this in application.properties in the test package
You can add the profile with the MySQL datasource properties in the same application.properties (or .yml) as:
application.yml
# Existing properties
---
spring:
profiles: h2
# More h2-related properties
---
spring:
profiles: postgres
database:
driverClassName: org.postgresql.Driver
datasource:
url: jdbc:postgresql://localhost:5432/db_dvdrental
username: user_dvdrental
password: changeit
jpa:
database: POSTGRESQL
generate-ddl: false
# More postgres-related properties
and either use #ActiveProfiles("postgres") in an integration test class or start teh container using VM argument as:
java -Dspring.profiles.active=h2 ...
Add application.yml(properties) with jdbc connection into src/test/resources
Run your JPA test with #AutoConfigureTestDatabase(replace= AutoConfigureTestDatabase.Replace.NONE) - it disables using embedded database (h2), otherwise :
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'dataSource': Invocation of init method
failed; nested exception is java.lang.IllegalStateException: Failed to
replace DataSource with an embedded database for tests. If you want an
embedded database please put a supported one on the classpath or tune
the replace attribute of #AutoConfigureTestDatabase.

How do you properly set different Spring profiles in bootstrap file (for Spring Boot to target different Cloud Config Servers)?

We have different config servers per environment. Each spring boot application should target its corresponding config server. I have tried to achieve this by setting profiles in the bootstrap.properties file, e.g.:
spring.application.name=app-name
spring.cloud.config.uri=http://default-config-server.com
---
spring.profiles=dev
spring.cloud.config.uri=http://dev-config-server.com
---
spring.profiles=stage
spring.cloud.config.uri=http://stage-config-server.com
---
spring.profiles=prod
spring.cloud.config.uri=http://prod-config-server.com
And then I set the cla -Dspring.profiles.active=dev but the loaded config server is always the last one set in the file (i.e. prod config server would be loaded in the above settings, and then if prod is removed, stage would be loaded).
Is it possible to set bootstrap profiles for the cloud config server? I followed this example but can't seem to get it working. For what it's worth, these profiles work great to load the correct config (i.e. app-name-dev.properties will load if the dev profile is active), but aren't being pulled from the proper config server.
Specifying different profiles in a single file is only support for YAML files and doesn't apply to property files. For property files specify an environment specific bootstrap-[profile].properties to override properties from the default bootstrap.properties.
So in your case you would get 4 files bootstrap.properties, bootstrap-prod.properties, bootstrap-stage.properties and bootstrap-dev.properties.
However instead of that you could also only provide the default bootstrap.properties and when starting the application override the property by passing a -Dspring.cloud.config.uri=<desired-uri> to your application.
java -jar <your-app>.jar -Dspring.cloud.config.uri=<desired-url>
This will take precedence over the default configured values.
I solved a similar problem with an environment variable in Docker.
bootstrap.yml
spring:
application:
name: dummy_service
cloud:
config:
uri: ${CONFIG_SERVER_URL:http://localhost:8888/}
enabled: true
profiles:
active: ${SPR_PROFILE:dev}
Dockerfile
ENV CONFIG_SERVER_URL=""
ENV SPR_PROFILE=""
Docker-compose.yml
version: '3'
services:
dummy:
image: xxx/xxx:latest
restart: always
environment:
- SPR_PROFILE=docker
- CONFIG_SERVER_URL=http://configserver:8888/
ports:
- 8080:8080
depends_on:
- postgres
- configserver
- discovery
#LarryW (I cannot answer on the same comment):
I guess the advantage of explicitly adding the property is that it allows you to add a default value (in this case "dev") in case of not setting up the environment variable.

Categories