Unable to use external configuration with Quarkus - java

I am having trouble to use external configuration properties for my Quarkus application.
I want to override the database properties. The application.properties inside the project has properties for dev and test, not for prod. The values for prod are inside the external application.properties.
I read the official guide (https://quarkus.io/guides/config#overriding-properties-at-runtime) and tried to place an application.properties file in a folder next to the runner-jar called config. That didn't work. But just passing the properties on the command line didn't work either.
C:.
│ 0.1.0-SNAPSHOT-runner.jar
│ 0.1.0-SNAPSHOT.jar.original
│
├───config
│ application.properties
Internal:
%dev.quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/postgres
%dev.quarkus.datasource.username=postgres
%dev.quarkus.datasource.password=postgres
%dev.quarkus.datasource.db-kind=postgresql
%dev.quarkus.hibernate-orm.database.generation=none
%test.quarkus.datasource.jdbc.url=jdbc:h2:mem:test
%test.quarkus.datasource.username=sa
%test.quarkus.datasource.password=
%test.quarkus.datasource.db-kind=h2
%test.quarkus.hibernate-orm.database.generation=none
External:
quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/postgres
quarkus.datasource.username=postgres
quarkus.datasource.password=postgres
quarkus.datasource.db-kind=postgresql
quarkus.hibernate-orm.database.generation=none
With java -jar .\0.1.0-SNAPSHOT-runner.jar I get the following error:
2020-07-24 16:58:16,666 ERROR [io.qua.application] (main) Failed to start application: java.lang.IllegalArgumentException: Parameter 'dataSource' may not be null
at org.wildfly.common.Assert.checkNotNullParamChecked(Assert.java:71)
at org.wildfly.common.Assert.checkNotNullParam(Assert.java:49)
at org.wildfly.security.auth.realm.jdbc.QueryConfiguration.<init>(QueryConfiguration.java:40)
at org.wildfly.security.auth.realm.jdbc.QueryBuilder.buildQuery(QueryBuilder.java:76)
at org.wildfly.security.auth.realm.jdbc.JdbcSecurityRealmBuilder.build(JdbcSecurityRealmBuilder.java:51)
at io.quarkus.elytron.security.jdbc.JdbcRecorder.createRealm(JdbcRecorder.java:42)
at io.quarkus.deployment.steps.ElytronSecurityJdbcProcessor$configureJdbcRealmAuthConfig-173765586.deploy_0(ElytronSecurityJdbcProcessor$configureJdbcRealmAuthConfig-173765586.zig:76)
at io.quarkus.deployment.steps.ElytronSecurityJdbcProcessor$configureJdbcRealmAuthConfig-173765586.deploy(ElytronSecurityJdbcProcessor$configureJdbcRealmAuthConfig-173765586.zig:36)
at io.quarkus.runner.ApplicationImpl.doStart(ApplicationImpl.zig:524)
at io.quarkus.runtime.Application.start(Application.java:90)
at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:91)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:61)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:38)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:106)
at io.quarkus.runner.GeneratedMain.main(GeneratedMain.zig:29)
2020-07-24 16:58:16,730 ERROR [io.qua.run.Application] (main) Error running Quarkus application: java.lang.RuntimeException: Failed to start quarkus
at io.quarkus.runner.ApplicationImpl.doStart(ApplicationImpl.zig:649)
at io.quarkus.runtime.Application.start(Application.java:90)
at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:91)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:61)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:38)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:106)
at io.quarkus.runner.GeneratedMain.main(GeneratedMain.zig:29)
Caused by: java.lang.IllegalArgumentException: Parameter 'dataSource' may not be null
at org.wildfly.common.Assert.checkNotNullParamChecked(Assert.java:71)
at org.wildfly.common.Assert.checkNotNullParam(Assert.java:49)
at org.wildfly.security.auth.realm.jdbc.QueryConfiguration.<init>(QueryConfiguration.java:40)
at org.wildfly.security.auth.realm.jdbc.QueryBuilder.buildQuery(QueryBuilder.java:76)
at org.wildfly.security.auth.realm.jdbc.JdbcSecurityRealmBuilder.build(JdbcSecurityRealmBuilder.java:51)
at io.quarkus.elytron.security.jdbc.JdbcRecorder.createRealm(JdbcRecorder.java:42)
at io.quarkus.deployment.steps.ElytronSecurityJdbcProcessor$configureJdbcRealmAuthConfig-173765586.deploy_0(ElytronSecurityJdbcProcessor$configureJdbcRealmAuthConfig-173765586.zig:76)
at io.quarkus.deployment.steps.ElytronSecurityJdbcProcessor$configureJdbcRealmAuthConfig-173765586.deploy(ElytronSecurityJdbcProcessor$configureJdbcRealmAuthConfig-173765586.zig:36)
at io.quarkus.runner.ApplicationImpl.doStart(ApplicationImpl.zig:524)
... 6 more
With java -Dquarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/postgres -Dquarkus.datasource.username=postgres -Dquarkus.datasource.password=postgres -Dquarkus.datasource.db-kind=postgresql -jar .\0.1.0-SNAPSHOT-runner.jar I get this:
Error: Could not find or load main class .datasource.jdbc.url=jdbc:postgresql:..localhost:5432.postgres
Caused by: java.lang.ClassNotFoundException: /datasource/jdbc/url=jdbc:postgresql://localhost:5432/postgres
I could only find two similar threads (How can I override properties in Quarkus? and https://github.com/quarkusio/quarkus/issues/1218). Both mention the method with the application.properties in the config folder. Since this does not work for me and I cannot find any new information, I am somewhat lost ...
I would be grateful for any help!

Ok, so it turns out there are several properties which you can not override at runtime. Those are marked on the offical overview of all properties (https://quarkus.io/guides/all-config). There is a little hint about this at the top of the page.
quarkus.datasource.db-kind is one of those properties. So all I had to do is include this property in my main application.properties. After that the external file was found and I could use those values for url, password, and username.

Max is right when he says that quarkus.datasource.db-kind is a runtime property.
The only way I got it to work so that I have
%dev
quarkus.datasource.db-kind=postgres
%qa
quarkus.datasource.db-kind=h2
%prod
quarkus.datasource.db-kind=<otherDBKind>
is to, either use profiling:
gradle/maven quarkusDev -Dquarkus-profile=[dev,qa,prod]
or, if you want to deploy the application and run it through java -jar, you have to compile it with the profile context
gradle/maven quarkusBuild -Dquarkus-profile=[dev,qa,prod]
a build for each profile with a different db-kind

Related

Spring boot - How to provide environment variables to app context to avoid unit test failure

I have a spring boot REST API app. I am using environment variables in application.properties file. Some settings are as shown below:
logging.level.springframework.web=${WEB_LOG_LEVEL}
logging.level.org.hibernate=${HIBERNATE_LOG_LEVEL}
In my unit test, I use annocation #TestPropertySource("classpath:application-test.properties"). However, when I run mvn clean install, build fails because of unit test failure. I provided the error log. When I ran in IDE, I can provide those environment vairables. Any suggestions on how to pass them in mvn clean install? Or any other approaches you would recommend? Thanks much in advance!
***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to bind properties under 'logging.level.springframework.web' to org.springframework.boot.logging.LogLevel:
Property: logging.level.springframework.web
Value: ${WEB_LOG_LEVEL}
Origin: class path resource [application.properties] - 44:35
Reason: failed to convert java.lang.String to org.springframework.boot.logging.LogLevel (caused by java.lang.IllegalArgumentException: No enum constant org.springframework.boot.logging.LogLevel.${WEB_LOG_LEVEL})
Action:
Update your application's configuration. The following values are valid:
DEBUG
ERROR
FATAL
INFO
OFF
TRACE
WARN
We have many options!
Best is we (roughly) understand the 2 Externalized Configuration and PropertySource:
Leaving our application.properties as it is, we can:
(As tgdavies commented), introduce src/test/resources/application...
Here we can:
call it application.properties, and it will override (existing settings/"sensible") of src/main/resources/application.properties, then we don't need #PropertySource or #Profiles on our test.
call it application_test.properties, then work rather with #Profile("test") + #ActiveProfiles("test") (on our test class(es), with even higher precedence as the above).
don't use #PropertySource (some_custom_name.properties file) for this use case, it has too low precedence!
...in these properties we will write (without placeholders):
logging.level.springframework.web=warn
logging.level.org.hibernate=warn
# or the log level(s) of our choice, overriding(!) the "main ones"
SET/EXPORT these properties in our (dev) environment! (with our cli/OS dialog/MAVEN_OPTS/...)
Using #TestPropertySource (2nd highest precedence, in spring-boot configuration hierarchy!, no profiles):
like (override property):
#TestPropertySource(properties = "logging.level.springframework.web=warn", ...)
or (using/trying relaxed binding):
#TestPropertySource(properties = "web.log.level=warn", ...)
or (using a file):
#TestPropertySource(locations = "classpath:/some/properties.properties", ...)
But a slight modification of our (src/main/...)application.properties can also be very helpful: Fallback! - looks like:
logging.level.springframework.web=${WEB_LOG_LEVEL:warn}
logging.level.org.hibernate=${HIBERNATE_LOG_LEVEL:warn}
It tries for the environment variables, and falls back to warn. With this, we can omit #PropertySource/#Profile and/or an additional test-application-properties.
And even better with relaxed binding:
logging.level.springframework.web=${web.log.level:warn}
logging.level.org.hibernate=${hibernate.log.level:warn}
This will accept the above environment variables, but also (previously defined)"properties" + fall back to "warn".
Conflict-free combinations of the proposed.
... -> Chapter 2, Relaxed Binding(, Profiles!) and Spring Boot How To: Properties and Configuration.

Kubernetes client (certificate) exception is thrown when spring-cloud-starter-kubernetes-config added as a dependency

I encountered the following error when added spring-cloud-starter-kubernetes-config dependency to my pom.xml:
io.fabric8.kubernetes.client.KubernetesClientException: An error has occurred. Caused by: java.security.cert.CertificateException: Could not parse certificate: java.io.IOException: Empty input Caused by: java.io.IOException: Empty input
To disable k8s, I added in bootstrap.yml following param:
spring:
cloud:
kubernetes:
enabled: false
But even after that nothing changed and the error remained.
Where else should I look? What parameter should I add so that if I have this dependency in pom.xml, I disable Kubernetes when running tests?
That problem could happen due to the installed kubectl. The easiest way to avoid this problem - rename ~/.kube (directory with configs) to some other name like ~/.kube-hide
mv ~/.kube ~/.kube-hide
And when you will need to use your kubectl rename it back
As stated on the Spring Cloud Kubernetes documentation
Also note that these properties: spring.cloud.kubernetes.config.enabled and spring.cloud.kubernetes.secrets.enabled only take effect when set in bootstrap.{properties|yml}
https://docs.spring.io/spring-cloud-kubernetes/docs/current/reference/html/#kubernetes-ecosystem-awareness
So, to actually disable this property, it has to be set in bootstrap.{properties|yml} and not in application.{properties|yml}.
Also, you can pass the value as a VM option:
-Dspring.cloud.kubernetes.enabled=false
if you want to run the application locally.

running junit testcase application from command line causes initialization errors

I have a testing application running as expected when executed on Eclipse IDE.
We want to export it to a jar and execute it via command line.
After executing, and running the application with the following comand, i encounter an error
java -jar testclient.jar -info
Error: Unable to initialize main class testclient.Main
Caused by: java.lang.NoClassDefFoundError: org/junit/runners/model/InitializationError
( -info) is an argument for the main method in the class.
Manifest file is pointing to the correct class.
On research of this topic, i checked whether the required libraries are added to the path. They are correctly added.
Could anyone provide some guidance

Elastic Beanstalk fails creating

I finally reached the point where my Elastic Beanstalk Instance / Environment got launched. (Java Corretto 11 Platform) Now it fails starting up the provided .jar file.
In the eb-engine.log file, I am not able to find any more error than this:
2021/05/27 11:36:25.889735 [INFO] Executing instruction: StageJavaApplication
2021/05/27 11:36:25.889871 [ERROR] An error occurred during execution of command [app-deploy] - [StageJavaApplication]. Stop running the command. Error: staging java app failed due to invalid zip file
The jar file is a Spring Boot application built with mvn -B package.
Locally the whole thing starts, but crashes afterwards because of not given environment variables (Expected behaviour).
But it seems AWS is not even starting the application..
Any suggestions on this?
Spring Boot apps run nicely on Elastic Beanstalk. However, you do need to set some variables. For example, have you set server-port variable to 5000?
And as you stated, to successfully use a Service Client, you can set environment variables for your creds. Here is an end to end walkthrough that shows how to successfully put a Spring BOOT app that invokes several AWS Services on Elastic Beanstalk.
Creating your first AWS Java web application
PS - your log file mentions a ZIP file. Be sure to create the JAR properly as discussed in the above example.
Just in case someone arrive here looking for an answer about this guy:
Error: staging java app failed due to invalid zip file
I was renaming my service jar in Gradle, using:
tasks.withType<org.springframework.boot.gradle.tasks.bundling.BootJar> {
archiveFileName.set("service.jar")
launchScript()
}
And ElasticBeanstalk was not happy about the renaming.
When I let it have the default name, then no zip issues and all worked like a charm.

Deploy war to JBOSS

I tried to deploy a Vaadin hello world application in JBOSS. The application is as simple as it can be.
My development environment is eclipse for java EE + tomcat
java.lang.RuntimeException: Error configuring property: includeWebInfInClasspath for WarClassLoaderDeployer
at org.jboss.kernel.plugins.dependency.ConfigureAction.dispatchSetProperty(ConfigureAction.java:112)
at org.jboss.kernel.plugins.dependency.ConfigureAction.setAttributes(ConfigureAction.java:85)
(...)
Caused by: java.lang.IllegalArgumentException: No such property includeWebInfInClasspath for bean org.jboss.web.tomcat.service.deployers.WarClassLoaderDeployer available [java2ClassLoadingCompliance, parentFirst, requiredInputs, filteredPackages, allInputs, deploymentRegistry, class, stage, wantComponents, componentsOnly, input, inputs, relativeOrder, output, useUnitName, outputs, topLevelOnly]
I have tried to google this error with no success.
Does anyone have any clues?
Is it a web server configuration or my *.war is missing something?
EDIT:
This error occur when I start the server after placing my *.war in the folder.
My JBOSS version is 5
I guess, you're using an old JBoss 5.
The WarClassLoaderDeployer is configured in the file server/default/deployers/jbossweb.deployer/META-INF/war-deployers-jboss-beans.xml. (The 'default' directory should be changed to whatever you passed as -c parameter) Open the file, find the WarClassLoaderDeployer bean and drop the line defining the property with name includeWebInfInClasspath.

Categories