SpringBoot project, Environment Variable in application.yml always empty - maven

I'm trying to run a SpringBoot project that runs with docker-compose. i started its dependencies (Redis, MongoDB ,and RabbitMQ) with docker-compose up
and i'm building the project and running it with these commands
mvn clean package -DskipTests && mvn spring-boot:run
I keep having these errors :
Error processing condition on org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2RestOp erationsConfiguration$RequestScopedConfiguration
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'OAUTH_CLIENTID' in value "${OAUTH_CLIENTID}"
In the docker-compose file, the values of the environment variables are defined in the environment section.
environment:
- RABBIT_HOST=rabbitstomp
- RABBIT_USER=guest
- RABBIT_PASS=user
- MONGO_HOST=mongodb://localhost:27017
- OAUTH_CLIENTID=nz-kek
- OAUTH_CLIENT_SECRET=DzXZxeOZOJHFZIUhObSpsne
- SSO_HOST=https://webweb.com
- CORS_HOSTS=HOST1,HOST2
- SES_HOST=ses
- SES_PORT=6000
- REDIS_HOST=localhost
- REDIS_PORT=6379
This is how application.yml looks like :
spring.data.mongodb:
database: ${DB_NAME} #notificationdb
uri: ${MONGO_HOST}
security:
oauth2:
resource:
jwk:
key-set-uri: ${auth-server:${SSO_HOST}}/keys
token-info-uri: ${auth-server:${SSO_HOST}}/userinfo
client:
client-id: ${OAUTH_CLIENTID}
client-secret: ${OAUTH_CLIENT_SECRET}`
So when running the project without docker-compose, am i supposed to put the values in the application.yml ?
i also tried mvn spring-boot:run -Dspring-boot.run.arguments=--path.to.value=value1, but i'm not sure how the path should be with variables like key-set-uri: ${auth-server:${SSO_HOST}}/keys

Spring has support for providing default values in the configuration via the PlaceholderConfigurerSupport. The default value is what comes after the :. In your case, you should write:
client-id: ${OAUTH_CLIENTID:yourDevelopmentDefaultClientID}
If you use the #Value annotation to inject the values, you have support to SpEL for using expressions of the type: #{someExpression} for more complex cases.
UPDATE:
In your case, I believe you are reversing the position of the variables. The correct should be:
key-set-uri: ${SSO_HOST:auth-server}/keys
Here is what it means: first, it will try to use the SSO_HOST environment variable, which is provided to the container through docker-compose. In case this variable is not provided to the process, Spring will use auth-server as the address of the server. It seems to me that this address is visible only inside the docker-compose network, so if you are running your app outside this network, the auth-server address will not be visible. Do you know where is the auth server? Is it another docker container? Is it running on localhost?
Some interesting reference: https://www.baeldung.com/spring-value-defaults

Pass env variables in docker compose as object not a list:
environment:
RABBIT_HOST: rabbitstomp
RABBIT_USER: guest
RABBIT_PASS: user
MONGO_HOST: mongodb://localhost:27017
OAUTH_CLIENTID: nz-kek
OAUTH_CLIENT_SECRET: DzXZxeOZOJHFZIUhObSpsne
SSO_HOST: https://webweb.com
CORS_HOSTS: HOST1,HOST2
SES_HOST: ses
SES_PORT: 6000
REDIS_HOST: localhost
REDIS_PORT: 6379`

Related

Specifying multiple Spring active profiles in k8s deployment yml

I am having two active profiles in my module in Java.
I am trying to specify it in kubernetes like this:
env:
- name: spring_profiles_active
value: ["dev", "shop-module"]
Is the correct way to specify the two active configs?
Multiple active profiles can be configured in the below way:
application.properties
spring.profiles.active=dev,hsqldb
(or)
application.yml
spring:
profiles:
active: "dev,hsqldb"
how do you pass it while on command line ?? it will be supported surely if can be done via command line or you can do outside of kubernetes
try this link,
How can I specify the spring.profiles.active param with a value from an environment variable using fabric8 maven plugin?

Disabling config server for tests

I am using microservice architecture where the services are done with spring boot, to control them, I am using zuul as a proxy, eureka as register and config server as the configuration provider.
In the microservices I configure my bootstrap.yml file as follows:
spring:
application:
name: portal-gca-server-${MYENV:local}
cloud:
config:
uri: http://localhost:9090
As seen above, the config file name that I look for in the config server is according to my environment variable, otherwise I get the local profile.
This works fine, but when I run the tests on the development machine it will never work, because instead of searching for the test profile it searches for the location, because the dev machine has no environment variable.
I know I could register the environment variable to run the tests but that's not the intention or else I would have to do this all the time to run tests and to run the local application.
Is there any way to solve this? I already tried to use the annotations:
webEnvironment = SpringBootTest.WebEnvironment.MOCK
#ActiveProfiles("test")
#TestPropertySource(locations="classpath:application-test.properties")
None of them any good, because the first thing the application does when executed is to fetch the information in git according to bootstrap.yml.
Has anyone ever experienced this?
Go to your bootstrap.yml and then add :
spring:
cloud:
config:
enabled: false

How to create Spring Cloud Config Client with env specific configuration?

I have facing an issue with Spring Cloud Config Server and Eureka Server Profiling.
Let's say I have 3 services with their name ("spring.application.name") as :
myapp-svc
myapp-spring-cloud-config-svc
myapp-spring-eureka-svc
I want to deploy each service in 2 regions ( dev and prod ). In Dev region, each service will run on localhost and in prod it will have some different url. 'myapp-spring-cloud-config-svc' in dev region will point to local git repo, while in prod region it will point to remote git repo.I can have 2 configurations:
1) When I start 'myapp-svc' service in local, it should connect to 'myapp-spring-cloud-config-svc' in dev.
I can do this by setting spring.cloud.config.uri = .
But the issue with this set up is that the property needs to be defined in bootstrap.properties.
So, If deploy 'myapp-svc' to prod, I will have to change config uri there to point it to prod config service which in turn would need another build creation.
This doesn't seem like a good solution, what if I have 50 app related services, I can't change this property in each one of them before prod deployment.
I tried setting spring.cloud.config.uri in application-dev.properties of 'myapp-svc' but it doesn't work. As per docs, it must be changed in bootstrap.
So, how do I implement this without having to create new build for prod ?
2) I can first call eureka and then using eureka I can call config service here.
The problem here is also same.
If I use eureka to look up config then "eureka.client.serviceUrl.defaultZone" must be defined in "bootstrap.yml".
See this:https://cloud.spring.io/spring-cloud-config/multi/multi__spring_cloud_config_client.html
So, in this case too, I need to change eureka url before deploying this service to prod.
Please help me on this...!!
Here is how, the properties, yml looks like for each of the above mentioned services:
1) myapp-svc:
1.1)bootstrap.yml
spring:
application:
name: myapp-svc
cloud:
config:
discovery:
enabled: true
serviceId: myapp-spring-cloud-config-svc
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8762/eureka/
server:
port: 8082
2) myapp-spring-cloud-config-svc:
2.1)application-dev.properties:
spring.cloud.config.server.git.uri=file:///C:/config-repo
eureka.client.serviceUrl.defaultZone=http://localhost:8762/eureka
2.2)application-prod.properties:
spring.cloud.config.server.git.uri=https://github.com/<mygit Repo>
2.3)bootstrap.proerties:
spring.application.name=myapp-spring-cloud-config-svc
server.port=8888
3) myapp-spring-eureka-svc
3.1)bootstrap.proerties
spring.application.name=myapp-spring-eureka-svc
server.port=8762
1) You can have profile specific bootstrap-<profile>.properties (like for application-<profile>.properties) for each supported profile to avoid rebuilding your application for each env. Then just pass application profile using to your application during start-up. Spring will load correct bootstrap-<profile>.properties and will connect to proper configuration server (or eureka, etc). Example:
java -jar your-app.jar --spring.profiles.active=dev
2) You can pass your URLs externally as custom properties (same as with profile above) and have smth like this in bootstrap.properties. Example:
spring.cloud.config.uri=${config.server.url}
then pass --config.server.url= ... during start-up.
3) You can pass Spring properties in the same way during start-up. Example:
java -jar your-app.jar --spring.cloud.config.uri= ...
4) You can use system env variables. Example:
spring.cloud.config.uri=${SYSTEM_ENV_CLOUD_CONFIG_URI}

Spring cloud config environment variable interpolation

I'm using spring-cloud-config in my Spring Boot project and I don't understand how to interpolate environment variables.
For example I have MYSQL_PASSWORD variable set in the config server (as environment variable) and I want to get it from other clients, without redefining the variable inside all of them. This is my config:
service.yml (in config-server)
spring:
datasource:
url: jdbc:mysql://mysql:3306/${MYSQL_DATABASE}?autoReconnect=true&useSSL=false
username: ${MYSQL_USER}
password: ${MYSQL_PASSWORD}
bootstrap.yml (into the client)
spring:
application:
name: event-service
cloud:
config:
uri: http://config-service:8888
fail-fast: true
If I start my services with this configuration, placeholder ${MYSQL_***} is not interpolated and I cannot connect to the database obviously.
What I have to do to make it work is to define environment variables like MYSQL_*** also in the client.
This is weird for me as I want config-server to be the central repository for everything. Do you have any advice?
I suggest you try to replace ${MYSQL_USER} and ${MYSQL_PASSWORD} with ${mysql.user} and ${mysql.password} - that way you'll be relying on Spring Boot's default property replacement.
Although I'm not sure that configuration server supports what you're trying to use, I've never tried a similar use case, please write back with a solution if the approach I suggested didn't work :)

How to fix mysql connectivity issues on bosh-lite for a cf.org sample spring boot app?

I am trying to cf push this code from this github repo after running mvn package, but I get a failed app deployment.
I have created a user defined service for mysql since cleardb is not available on my bosh-lite local vm. I created the mysql service and named it as 'mysql' as well as guided by this.
The application.yml in this spring boot app points to localhost. That doesn't work even for a local (non cf) build without corrrecting the jdbc url. Here is the stack trace from the bosh-lite vm when I try to cf push this app and read the logs using cf logs springpong --recent.
Also, why do we need both, the manifest.yml and the application.yml providing database details ?
vagrant#vagrant-ubuntu-trusty-64:~$ cat pong_matcher_spring/src/main/resources/application.yml
---
spring:
datasource:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost/pong_matcher_spring_development
username: springpong
password: springpong
jpa:
hibernate.ddl-auto: none
show_sql: false
vagrant#vagrant-ubuntu-trusty-64:~$ cat pong_matcher_spring/manifest.yml
---
applications:
- name: springpong
buildpack: java_buildpack
path: target/pong-matcher-spring-1.0.0.BUILD-SNAPSHOT.jar
services:
- mysql
vagrant#vagrant-ubuntu-trusty-64:~$
Can someone help me fix this ?
TIA
This was happening as the security groups were not setup to allow for network access. A sample gist of commands can be seen here -> https://gist.github.com/menicosia/2e9c414430138064f945
Caveat: This is only for bosh-lite and development purposes.

Resources