read ENVIRONMENT_VARIABLE from application-env.yml in plain java - java

I have a simple java web service that uses javalin framework. I want to deploy it in multiple environments, so the env variables are different for each deployment.
I basically want to read
application-env.yml
keystore:
path: ${KEY_STORE_PATH}
password: ${KEY_STORE_PASSWORD}
from application-env.yml without using Spring.
And then use them in java.
Properties properties = PropertiesLoader.loadProperties();
System.out.println(properties.getProperty("keystore.password"));
// ${KEY_STORE_PASSWORD}
System.out.println(System.getenv("KEY_STORE_PASSWORD"));
// hunter2
How do I get hunter2 from properties?
EDIT:
i didnt get what I wanted, ended up doing this:
https://stackoverflow.com/a/73539823/2948875

You could use something like SnakeYAML, ie https://www.baeldung.com/java-snake-yaml

Related

Application Configuration Properties on Payara (how to read them)

I would like to use Application Configuration Properties that you can configure using the user interface of payara (for example):
My question is: how can I access these values on java code side? Through annotation? Through some sort of context instance maybe? Is it even possible?
I naively tried with System.getProperty with no success.
I don't believe there is a way.
An alternative would be to use system properties along with variable substitution via ${} syntax or environment variable via ${ENV.XXX}

Setting spring.profiles.active from an environment variable in Spring Boot with Gradle

My company has a standard way to specifying the environment a web service should run in, specifically 'development' and 'production' by using an environment variable APP_ENV. Each of these environments have a separate config file: application-dev.yml and application-prod.yml.
In spring boot, we can use SPRING_PROFILES_ACTIVE or equivalents to do this, but what I really want to do is grab the VALUE from APP_ENV, and use that as the profile.
I've got some code
SpringApplication app = new SpringApplication(Application.class);
springApp.setAdditionalProfiles(System.getenv("APP_ENV"););
springApp.run(args);
Any tips on how to do this a bit cleaner? I'm getting
java.lang.IllegalStateException: Failed to load ApplicationContext errors on various gradle tasks that make this solution kind of flimsy.
you can use System.getProperty which will always return a String like below,
springApp.setAdditionalProfiles(System.getProperty("APP_ENV", "dev"));
In the above snippet, we use System.getProperty(“APP_ENV”) to extract the value of the property APP_ENV. We also are making use of the default value so if the property is not available in the system, getProperty returns dev.

Use yml configuration instead of standalone.xml

I have lots of microservices and they work in a similar format. What my requirement is to make my confiuration.yml files work also for keycloak instead of working with standalone.xml (because of my requirements from our customers). I did not see any option that I can override when I check keycloak’s source code since the configuration is done before SPIs.
What I will go in worst scenario is to run some program to convert given configuration.yml to standalone.xml. I appreciate to hear any ideas about how to achieve this. Basically I want to work with YML instead of XML either natively importing something in keycloak or having some converters.
Maybe you can ask why you need this (even for customers), since all of our microservices works like;
server:
port: 80
we don’t want to force our clients to learn any different logic to edit our microservices. They will do always in same way to change some basic configurations like above and we can convert these values to proper standalone.xml way. So can I achieve this converter natively extending keycloak or what could be the best option?
It depends on what settings you want to extract to yml. Standalone.xml allows you to specify configuration values as properties like
<socket-binding name="http" port="${jboss.http.port:8080}"/>
so you can provide a properties file or prorety value during startup like
./standalone.sh --properties=foo.properties -Dfoo=bar
but in your case you could store all of this properties in yml and use some startup wrapper for keycloak that will parse your yml and expose all its settings as java properties like:
#!/bin/bash
./standalone.sh $(magictool foo.yml)

how to pass password to a java (Spring boot) application

We have to use ssl certificate for our rest web service which are created through springboot application.
Now, what I came to know that password is necessary in order to use a certificate. So we are changing our available .pem (without password) to .p12 (with password) using openssl. Now we have to provide spring this password.
Problem is the overhead which comes with introducing any new password.
We cannot hard-code this password in our application.properties due to bad design. So we are thinking of finding out the other ways to use password in application. So far I can think of below options. which one is better one and why?
Rather then setting password in application.properties, set it from java code. (I am not sure it will be set as environment variable or system variable)
use environment variable to store the password.
use any text file which stores the password (not preferred again due to bad design)
you can achieve your scenario in the following way.
i am posting sample example.\
In Properties File:
spring.datasource.url=${db.url}
spring.datasource.username=${db.username}
while starting the project,
you can give the following command:
java -jar -Ddb.url=jdbc:postgresql://localhost:5432/postgres -Ddb.username=postgres sample.0.0.1-SNAPSHOT.jar(your jar name)
option 3 seems feasible, but instead of storing it in a plain text file, you can encrypt the file, and put a decryption function in the application when reading the file.
For the provided options, i would go with the option 2, by using environment variables it will be easier to provide and change the password even in containerized environments and clouds.
But you can also consider other options, like using a safe k-v storage like Hashicorp Vault or etcd.
Note that using Vault or etcd, you can also provide and change the certificate dynamically, instead of shipping it with the application.
I can think of 3 ways you can do it
1. You can define password property only in application.properties but pass
the value of the property during application startup.
java -jar -Dmyapp.password=YOUR_PASSWORD myapplication.jar
2. You can put encrypted passwords in application.properties and pass the decryption key during application startup. Jasypt plays very good with spring boot.
java -jar -Dmyapp.decryptKey=YOUR_KEY myapplication.jar
3. You can use spring vault

How to consume properties from configmaps in Java Spring boot application deployed through Helm

I have simple Spring boot application which I need to deploy on development and prod different namespaces on a Kubernetes cluster using Helm.
I was thinking about keeping multiple application.properties (application-dev.properties, application-prod.properties) files for each environment and then create configmaps from them through values.yaml files which also will be different for each environment and specified when I execute Helm upgrade.
Now the question is how do I consume values from config.maps as I understand I can either mount the properties file inside container for example /deployment/application.properties
Or expose each property as an environment variable inside container.
But how do I consume them from Java application?
Also at the moment when I create container image it has current application .properties inside /resources/ files embedded and this is what application is using from default so I need to overwrite this behaviour when application is running inside container as opposite to then when its just build and run manually on developer desktop.
Springboot can automatically infer variables from environment variables. In your application.properties or application.yaml, just use ${MY_ENVIRONMENT_VARIABLE:my-defaultvalue}.
Use helm to populate your configmap.
Use configmap as environment variables into your deployment manifest.
This way you do not need to have multiple application.properties for dev, int ,prod inside your image. Keeping it intact across deployment.
And then in your helm chart, you can have multiple values.yaml example values-dev.yaml or values-int.yaml. you can also dynamically set helm values from command line, overriding the yaml file.
I have a demo app in github https://github.com/balchua/demo, which uses this pattern.
You could certainly use environment variables as Bal Chua suggests. If you do that you can override particular values at install time using --set or if you've a lot of config you can use the '-- values' flag and pass in a custom values.yaml file.
Another approach is to load a whole file using .Files.Glob (example in github) and load the file as part of the chart. You can then mount the file to /config to consume it in your spring boot application. Then your config file would be in the same form as a Spring boot config file, rather than a helm values.yaml. Though in many cases there needn't be much difference.
There's a discussion of how you could do similar for secrets (presumably you'll want to put your passwords in secrets) and use it for CI/CD in https://dzone.com/articles/hunting-treasure-with-kubernetes-configmaps-and-se (which is the article accompanying the github example). Basically you would use .Files.Glob with .AsSecrets instead of .AsConfig so as to encode the content. Many helm charts have the option to generate a random password if not specified but I'd guess you probably don't need that.
I'd recommend mounting the files (application.properties or application.yml) inside the ConfigMap onto somewhere on the file system that Spring Boot can automatically detect - then your app stays nice and simple

Categories