Warning about config property after migrated to Quarkus 2.8.0 - quarkus

I have migrated an extension from quarkus 2.7.5 to quarkus 2.8.0.
After the migration, I run mvn clean install and the console shows me weird warnings about all (maybe 100) config properties (some of them are defined by me, other not like java.specification.version):
[WARNING] [io.quarkus.config] Unrecognized configuration key "my.property" was provided; it will be ignored; verify that the dependency extension for this configuration is set or that you did not make a typo
I think my integration-tests module causes this issue.
Here is my class in runtime folder:
import java.util.Optional;
import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConfigPhase;
import io.quarkus.runtime.annotations.ConfigRoot;
#ConfigRoot(phase = ConfigPhase.RUN_TIME, prefix="", name = "myApp")
public class MyAppConfig {
#ConfigItem(defaultValue = "defaultValue")
String firstProperty;
#ConfigItem(defaultValue = "")
Optional<String> secondProperty;
#ConfigItem(defaultValue = "defaultValue")
String thirdProperty;
// Getters ...
}
Here is my test:
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.junit.jupiter.api.Test;
import io.quarkus.test.junit.QuarkusTest;
#QuarkusTest
public class MyAppIntegrationTest {
#ConfigProperty(name="myApp.first-property")
String firstProperty;
#ConfigProperty(name="myApp.second-property")
String secondProperty;
#ConfigProperty(name="myApp.third-property")
String thirdProperty;
#Test
public void testConfig() {
assertEquals("firstValue", firstProperty);
assertEquals("secondValue", secondProperty);
assertEquals("thirdValue", thirdProperty);
}
}
Can someone help me on this ? For instance, do I need a BuildItem for that ?
Thanks for your help

After spending hours on those warnings, I found that they was caused by the empty prefix field of the ConfigRoot annotation.
Setting name field to "" and prefix to "myApp" fixed the issue

Related

How to read secret key and value from Kubernetes volume mount using Spring Boot

I have mounted one volume which contained username and password inside pod. If I do:
kubectl exec -it my-app -- cat /mnt/secrets-store/git-token
{"USERNAME":"usernameofgit","PASSWORD":"dhdhfhehfhel"}
I want to read this USERNAME and PASSWORD using Spring Boot.
Assuming:
the file (git_token) format is fixed (JSON).
the file may not have an extension suffix (.json).
... we have some Problems!
I tried 2.3.5. Importing Extensionless Files like:
spring.config.import=/mnt/secrets-store/git-token[.json]
But it works only with YAML/.properties yet!(tested with spring-boot:2.6.1))
Same applies to 2.8. Type-safe Configuration Properties. ;(;(
In Spring-Boot we can (out-of-the box) provide JSON-config (only) as SPRING_APPLICATION_JSON environment/command line property, and it has to be the json string, and cannot be a path or file (yet).
The proposed (baeldung) article shows ways to "enable JSON properties", but it is a long article with many details, shows much code and has decent lacks/outdates (#Component on #ConfigurationProperties is rather "unconventional")..
I tried the following (on local machine, under the mentioned assumptions):
package com.example.demo;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Value("""
#{#jacksonObjectMapper.readValue(
T(java.nio.file.Files).newInputStream(
T(java.nio.file.Path).of('/mnt/secrets-store/git-token')),
T(com.example.demo.GitInfo)
)}""" // watch out with #Value and text blocks! (otherwise: No converter found capable of converting from type [com.example.demo.GitInfo] to type [java.lang.String])
)
GitInfo gitInfo;
#Bean
CommandLineRunner runner() {
return (String... args) -> {
System.out.println(gitInfo.getUsername());
System.out.println(gitInfo.getPassword());
};
}
}
#Data
class GitInfo {
#JsonProperty("USERNAME")
private String username;
#JsonProperty("PASSWORD")
private String password;
}
With (only) spring-boot-starter-web and lombok on board, it prints the expected output.
Solution outline:
a pojo for this
the upper case is little problematic, but can be handled as shown.
a (crazy) #Value - (Spring-)Expression, involving:
(hopefully) auto-configured #jacksonObjectMapper bean. (alternatively: custom)
ObjectMapper#readValue (alternatives possible)
java.nio.file.Files#newInputStream (alternatives possible)
java.nio.file.Path#of
When you have your volume mounted, then all you need to do is to read a JSON file from the Spring Boot application. I recommend reading Load Spring Boot Properties From a JSON File.
In short, you can create a class corresponding to your JSON file, something like this one.
#Component
#PropertySource("file:/mnt/secrets-store/git-token")
#ConfigurationProperties
public class GitToken {
private String username;
private String password;
// getters and setters
}
Then, you need to add it to componentScan and you can autowire your class.

Spring cloud config server. Environment variables in properties

I configured Spring Cloud Config server like this:
#SpringBootApplication
#EnableAutoConfiguration
#EnableConfigServer
public class ConfigServer {
public static void main(String[] args) {
SpringApplication.run(ConfigServer.class, args);
}
}
I'm using 'native' profile so properties are picked up from the file system:
server.port=8888
spring.profiles.active=native
spring.cloud.config.server.native.search-locations: classpath:/global
Now the tricky part is that some properties contain environmental variables. Properties in 'global/application-production.properties' are configured like this:
test=${DOCKER_HOST}
When I start up Config Server - everything works fine. However when I access http://localhost:8888/testapp/production I see this:
{
name: "testapp",
profiles: [
"production"
],
label: null,
version: null,
propertySources: [
{
name: "classpath:/global/application-production.properties",
source: {
test: "${DOCKER_HOST}"
}
}
]
}
So value from ENV variable is not replacing ${DOCKER_HOST} put rather returned as is.
But if I access http://localhost:8888/application-production.properties then result is non JSON but rather plain text:
test: tcp://192.168.99.100:2376
Spring documentation says:
The YAML and properties representations have an additional flag (provided as a boolean query parameter resolvePlaceholders) to signal that placeholders in the source documents, in the standard Spring ${…​} form, should be resolved in the output where possible before rendering. This is a useful feature for consumers that don’t know about the Spring placeholder conventions.
For some reason resolvePlaceholders is not working for JSON representation thus server config clients need to be aware of all ENV variables configured on server.
Is it possible to force JSON representation resolvePlaceholders same way as plain text (properties) representation?
I faced the same issue. After looking into Spring Cloud Config Repository I have found the following commit:
Omit system properties and env vars from placeholders in config
It looks like such behavior is not supported.
You can try the Property Overrides feature to override properties from git Environment Repository.
To override property foo at runtime, just set a system property or an environment variable spring.cloud.config.server.overrides.foo before starting the config server.
There was an update in order to accomplish this, in the following merge. 1 I found an implementation for resolvePlaceholders. Which gave me the idea of just creating a new controller which uses the EnvironmentController. This will allow you to resolve configuration, this is a good bootstrap.
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.config.server.environment.EnvironmentController;
import org.springframework.cloud.config.server.environment.EnvironmentRepository;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RestController
#RequestMapping(method = RequestMethod.GET, path = "resolved/${spring.cloud.config.server.prefix:}")
public class ReplacedEnvironmentController {
private EnvironmentController environmentController;
#Autowired
public ReplacedEnvironmentController(EnvironmentRepository repository) {
environmentController = new EnvironmentController(repository, new ObjectMapper());
}
public ReplacedEnvironmentController(EnvironmentRepository repository,
ObjectMapper objectMapper) {
environmentController = new EnvironmentController(repository, objectMapper);
}
#RequestMapping("/{name}/{profiles:.*[^-].*}")
public ResponseEntity<String> resolvedDefaultLabel(#PathVariable String name,
#PathVariable String profiles) throws Exception {
return resolvedLabelled(name, profiles, null);
}
#RequestMapping("/{name}/{profiles}/{label:.*}")
public ResponseEntity<String> resolvedLabelled(#PathVariable String name, #PathVariable String profiles,
#PathVariable String label) throws Exception {
return environmentController.labelledJsonProperties(name, profiles, label, true);
}
}

Spock Stepwise - Keep running testsuite after single failure

When using the Spock #Stepwise annotation, is there any way to configure it to not fail the entire testsuite after a single test fails?
Decided to just create a new extension called #StepThrough. All I needed to do was subclass StepwiseExtension and take out the line of code that was failing the entire test suite. Pasted code below...
StepThrough.groovy
package com.test.SpockExtensions
import org.spockframework.runtime.extension.ExtensionAnnotation
import java.lang.annotation.ElementType
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
import java.lang.annotation.Target
/**
* Created by jchertkov on 6/22/15.
*/
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#ExtensionAnnotation(StepThroughExtension.class)
public #interface StepThrough {}
StepThroughExtension.groovy
package com.test.SpockExtensions
import org.spockframework.runtime.extension.builtin.StepwiseExtension
import org.spockframework.runtime.model.SpecInfo
import java.lang.annotation.Annotation
/**
* Created by jchertkov on 6/22/15.
*/
public class StepThroughExtension extends StepwiseExtension {
public void visitSpecAnnotation(Annotation annotation, final SpecInfo spec) {
sortFeaturesInDeclarationOrder(spec);
includeFeaturesBeforeLastIncludedFeature(spec);
}
}
Notes:
I put the code into a package called com.test.SpockExtensions. You will need to do the same with whatever name you would like.
Java users - just change filetype from .groovy to .java

LinkageError: Loader constraint violation when running junit test with hamcrest in pde enviornment

I am trying to test a class using junit and hamcrest. here is the test that I have:
#Test
public void testConvert()
{
assertNull(converter.convert(null));
assertNull(converter.convert(CommonentityFactory.eINSTANCE.createOrganization()));
OrganizationMID organizationMID = OrganizationMID.create(DOMAIN, 1234L);
String organizationName = "organizationName";
com.demographics.app.commonentity.Organization fromOrganization = CommonentityFactory.eINSTANCE
.createOrganization();
fromOrganization.setMID(organizationMID);
fromOrganization.setNameFormatted(organizationName);
com.search.organization.ui.Organization organization = converter
.convert(fromOrganization);
assertThat(organization.getOrganizationMID(), is(organizationMID));
assertThat(organization.getOrganizationName(), is(organizationName));
}
When I run the test as a pde test, I get,
java.lang.LinkageError: loader constraint violation: loader (instance of org/eclipse/osgi/internal/baseadaptor/DefaultClassLoader) previously initiated loading for a different type with name "org/hamcrest/Matcher"
Here are my imports:
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import org.junit.Test;
And I am using org.junit v4.8.2-v370 , mockito-core v1.8.5 and org.hamcrest.osgi v1.1
I am not sure what's wrong here, but I feel that I dont have the dependencies set up right in my pom.
Can anyone help me in figuring this one out?

Spring 3.0 / AOP / Aspectj:autoproxy intercept any call to getConnection()

I'm trying to intercept any call to getConnection() method to setup the dbms indentifier . I've implemented an aspect to get it but I don't get anything. Any idea? Thanks!
import java.sql.CallableStatement;
import java.sql.Connection;
import javax.servlet.http.HttpSession;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import es.iberia.tryp.model.entities.Usuario;
#Component
#Aspect
public class ConnectionAspect {
#AfterReturning(value = "execution(java.sql.Connection javax.sql.DataSource+.getConnection(..))", returning = "connection")
//#AfterReturning(value = "execution(java.sql.Connection org.springframework.jdbc.datasource.*.*(*))", returning = "connection")
//#AfterReturning(value = "execution(java.sql.Connection java.sql.Connection *(..))", returning = "connection")
//#AfterReturning(value = "execution(java.sql.Connection org.springframework.jdbc.datasource.DriverManagerDataSource.*(..))", returning = "connection")
public void prepare (Connection connection) throws Throwable {
HttpSession httpSession = (HttpSession) RequestContextHolder.currentRequestAttributes().resolveReference(RequestAttributes.REFERENCE_SESSION);
if (httpSession!=null && (Usuario)httpSession.getAttribute("usuario")!=null && ((String)((Usuario)httpSession.getAttribute("usuario")).getNomina())!=null) {
String nomina = (String)((Usuario)httpSession.getAttribute("usuario")).getNomina();
String prepSql = "{ call DBMS_SESSION.SET_IDENTIFIER('" + nomina +"') }";
CallableStatement cs = connection.prepareCall(prepSql);
cs.execute();
cs.close();
}
}
}
Check whether you have added the below tag in your xml file.
aop:aspectj-autoproxy
Also check whether you have added the bean definition inside the xml for this ConnectionAspect class.
Yes, I have an idea: Actually your pointcuts match the desired calls, but they are in the java package which (like the javax package) is excluded from weaving by default.
There is a way to remove that restriction via command line and aop.xml, but please be aware of potential problems concerning classloading. You have to make sure the classloader loading the java classes has a weaver attached, so if you have the option not to use LTW, just weave the JDK class files and use those woven classes, and you will be fine. Otherwise you might have a "hen and egg" problem.

Resources