there. I'm new to Java Spring Boot and I'm trying to set environment variables in application.yml.
I've added dotenv maven dependency:
<!-- https://mvnrepository.com/artifact/io.github.cdimascio/java-dotenv -->
<dependency>
<groupId>io.github.cdimascio</groupId>
<artifactId>java-dotenv</artifactId>
<version>5.1.3</version>
</dependency>
I've set variables in the .env file:
SPRING_DATABASE_URL = jdbc://db_url
SPRING_DATABASE_USERNAME = username
SPRING_DATABASE_PASSWORD = password
And in my application.yml:
spring:
datasource:
url: ${SPRING_DATABASE_URL}
username: ${env.SPRING_DATABASE_USERNAME}
password: ${env.SPRING_DATABASE_PASSWORD}
While running application I'm getting jdbc error:
java.lang.RuntimeException: Driver org.postgresql.Driver claims to not accept jdbcUrl, ${SPRING_DATABASE_URL}
I've tried some solutions like:
export SPRING_DATABASE_URL = jdbc://db_url
or in application.yml:
url: ${env.SPRING_DATABASE_URL}
or
url: ${env.SPRING.DATABASE.URL}
or
url: ${SPRING.DATABASE.URL}
Am I doing something wrong or missing? I appreciate your help, thank you.
I recently ran in a similar issue and wanted to set environment variables via .env with application.yml - here is what I found out:
First, as you mentioned you have to add the java-dotenv dependency to pom.xml:
<dependency>
<groupId>io.github.cdimascio</groupId>
<artifactId>dotenv-java</artifactId>
<version>2.2.0</version>
</dependency>
Then create your .env file in the root of your project (where pom.xml is located) and write your environment variables like e.g. ENV_PORT=8081.
Before you can use this environment variable, you have to "bind" the content of the .env file with Spring Boot when you start the app to make it globally available. According to this thread, this can be achieved by simply altering your Main entry point of spring (where you init the framework) like so:
#SpringBootApplication
public class MySpringApplication {
public static void main(String[] args) {
Map<String, Object> env = Dotenv.load()
.entries()
.stream()
.collect(
Collectors.toMap(DotenvEntry::getKey, DotenvEntry::getValue));
new SpringApplicationBuilder(MySpringApplication.class)
.environment(new StandardEnvironment() {
#Override
protected void customizePropertySources(MutablePropertySources propertySources) {
super.customizePropertySources(propertySources);
propertySources.addLast(new MapPropertySource("dotenvProperties", env));
}
}).run(args);
}
}
That's it, now you can reference to your environment variables in application.yml like so:
server:
port: ${ENV_PORT}
Hope this helps! If you are interested, here is also a full working example where I am using this approach.
java-dotenv you use has been renamed to kotlin-dotenv. If you look at its documentation, you'll see how it's used:
With Java
import io.github.cdimascio.dotenv.Dotenv;
Dotenv dotenv = Dotenv.load();
dotenv.get("MY_ENV_VAR1")
That's not what spring boot does - spring boot will not use any dotenv to fetch environment variables, so naturally the plugin won't work for your use case so .env files will not work.
If you start your app defining the environment variable when starting it app, it will work. To see how environment variables are passed using vscode, see this thread.
Related
I created an spring boot application that makes API calls. I have been given an API key that I added to my system environment variables as API_KEY
At first, I had my urls as
String uri = "http://api-site.com/.../key="+System.getenv("API_KEY")+"&..."
and this works just fine when I run it locally.
However, when I build and run the image, I get 403 error.
My Dockerfile looks like:
FROM maven:3.5.4-jdk-8-alpine AS builder
COPY pom.xml pom.xml
COPY src/ src/
RUN mvn clean package
FROM openjdk:11 AS runner
**ENV API_KEY $API_KEY**
EXPOSE 8080
COPY --from=builder target/app-0.0.1.jar app.jar
ENTRYPOINT [ "java", "-jar", "app.jar" ]
I'm guessing System.getenv("API_KEY") does not work in containers.
Is there a way to get it to work?
I've tried the other syntax for the environment variable in the Dockerfile: ENV API_KEY=${API_KEY}
I have also tried using application.properties but I have not been able to get that to work (this might need to be a whole other question). I can't even get test variables to print.
I have test.name=testname in applications.properties
In a class I have:
#Component
#PropertySource("classpath:application.properties")
public class AC {
#Value("${test.name}")
public String test;
public static void main(String[] args){
System.out.println(test);
}
}
This just prints out null every time.
Thank you in advance!
Trying to do the swagger OAuth configuration in the latest version of Micronaut, as per the micronuat documentation
https://micronaut-projects.github.io/micronaut-openapi/latest/guide/index.html#enableendpoints
swagger-ui.oauth2RedirectUrl
swagger-ui.oauth2.clientId
swagger-ui.oauth2.clientSecret
swagger-ui.oauth2.realm
swagger-ui.oauth2.appName
swagger-ui.oauth2.scopeSeparator
swagger-ui.oauth2.scopes
swagger-ui.oauth2.additionalQueryStringParams
swagger-ui.oauth2.useBasicAuthenticationWithAccessCodeGrant
swagger-ui.oauth2.usePkceWithAuthorizationCodeGrant
When setting any of those properties, Micronaut will generate not only a swagger-ui/index.html file, but also a swagger-ui/oauth2-redirect.html one
I can see it has created the file oauth2-redirect.html with below code
tasks.withType(JavaCompile).all {
options.forkOptions.jvmArgs << '-Dmicronaut.openapi.views.spec=swagger-ui.enabled=true,swagger-ui.theme=flattop,swagger-ui.oauth2RedirectUrl=http://localhost:8080/swagger-ui/oauth2-redirect.html,swagger-ui.oauth2.clientId=myClientId,swagger-ui.oauth2.scopes=openid,swagger-ui.oauth2.usePkceWithAuthorizationCodeGrant=true'
}
For the oauth2.clientId, oauth2RedirectUrl and oauth2.clientSecret these values differs for each environment PROD, TEST, DEV, UAT. By setting the value like above code it is hard to configure for each enviroment. Is there any better way to do this?
In my project it was solved by creating different property files for each env and steering the compilation with parameters
tasks.withType(JavaCompile) {
String openapiPropertyFile = 'openapi/openapi-dev.properties'
if(project.hasProperty("openapiPropertyFile")){
openapiPropertyFile = project.property('openapiPropertyFile')
}
options.fork = true
options.forkOptions.jvmArgs << "-Dmicronaut.openapi.config.file=$openapiPropertyFile"
}
and then you build it like this
$ sh ./gradlew clean jib -PopenapiPropertyFile=openapi/openapi-uat.properties -PimageSuffix=-uat
Although I'd like to know how to do this post compilation because in my case it forces creation of separate docker images where I'd like to have one and mount those properties afterwards.
I have jasypt password and the encrypted password defined in application.yml like this:
jasypt:
encryptor:
password: ${secretKey}
spring:
datasource:
password: ENC(${password})
And using #Value for it:
#Value("${spring.datasource.password}")
private String springPassword;
I have defined both secretKey and password in my environment variable. But when I start this spring boot application, it throws error:
Caused by: org.springframework.cache.Cache$ValueRetrievalException: Value for key 'spring.datasource.password' could not be loaded using 'com.ulisesbocchio.jasyptspringboot.caching.CachingDelegateEncryptablePropertySource$$Lambda$209/172678484#5ae15'
If I hardcode both of the keys, than it's working fine.
Any help would be appreciated.
I had similar issue. The reason in my case was that I had jasypt-1.9.2.jar and jasypt-1.9.4.jar on the class path.
jasypt-1.9.4.jar came as dependency from jasypt-spring-boot 2.1.1.
jasypt-1.9.2.jar came as dependency from wss4j-ws-security-common 2.2.2.
Changing to jasypt-spring-boot 2.1.0 solved the issue in my case.
I know it's too late but still. For me passing the ENC() method as part of environmental variable worked.
jasypt:
encryptor:
password: ${secretKey}
spring:
datasource:
password: ${PASSWORD}
while setting environmental variable
export PASSWORD=ENC(yourPassword)
I have a dropwizard question. I use Dropwizard with SBT (which works pretty fine).
If I run my application i package it with:
$ sbt clean assembly
And than run the application with:
$ java -jar APPLICATION.jar server
The problem is with this command Dropwizard doesnt load my config file (config.yaml), which is in the resources located.
Regarding the Dropwizard Docs I always have to give the config file as parameter like:
$ java -jar APPLICATION.jar server config.yaml
This works fine and it loads the application but is there any possibility to tell Dropwizard to load directly the config.yaml file, because my configuration in the config.yaml file is static and it is always the same. Settings like Database etc which are changing from Server Stage to Server Stage are made as Enviroment Variable which I load with EnvironmentVariableSubstitutor.
Thanks
Use class ResourceConfigurationSourceProvider:
#Override
public void initialize(final Bootstrap<ExampleConfiguration> bootstrap) {
bootstrap.setConfigurationSourceProvider(new ResourceConfigurationSourceProvider());
// The rest of initialize...
}
And then invoke the application like:
java -jar APPLICATION.jar server /resource-config.yaml
(note the initial /)
While this answer is very late, just thought I'd put this here. There is a dirty little hack to make it work so that you don't have to provide config.yaml in your application arguments.
Basically, you can submit a new String[] args to the run() method in the dropwizard application.
public class ApplicationServer extends Application<Config> {
public static void main(String[] args) {
String[] appArgs = new String[2];
appArgs[0] = args[0]; // This will be the usual server argument
appArgs[1] = "config.yaml";
new ApplicationServer().run(appArgs);
}
#Override
public void run(Config configuration, Environment environment) {
// Configure your resources and other application related things
}
}
I used this little trick to specify which config file I wanted to run with. So instead of specifying config.yaml, I would give my second argument as DEV/UAT/STAGE/PROD and pass on the appropriate config file to the run method.
Also interesting to have a look at:
earlye/dropwizard-multi-config
<dependency>
<groupId>com.thenewentity</groupId>
<artifactId>dropwizard-multi-config</artifactId>
<version>{version}</version>
</dependency>
It allows overriding and merging multiple config-files passed on the java command-line like:
java -jar sample.jar server -- sample.yaml override.yaml
Here you pass (1) sample.yaml as the primary configuration (e.g. having default values) and (2) override.yaml as the override. The effective config is a result from merging both in order of appearance: (1) defaults will be overwritten and merged with (2).
Is it possible to set the contents of Spring's bootstrap.properties at execution time?
I have a client application for Spring's cloud config which holds a line to point to the config server:
spring.cloud.config.url = http://localhost:8888
And I would like to set this config. I tried setting it like application.properties can be set:
java -jar ./config-client.jar --spring.cloud.config.url=http://localhost:8888
But it didn't work. So my question is, how can I set this property at execution time?
It seems to be caused by wrong properties name. url should be uri.
Try to change your property in bootstrap.properties like below.
spring.cloud.config.uri = http://localhost:8888
And then try again like below.
java -jar ./config-client.jar --spring.cloud.config.uri=<something else>
http://localhost:8888 is the default value of spring.cloud.config.uri. That's probably the reason why you didn't recognize the wrong property name.