Quarkus - Optaplanner tweaking algorithms - quarkus

I created a new file known as "solverConfig.xml" under resources. I changed in application.properties, to write the following: quarkus.optaplanner.solver-config-xml=src/main/resources/solverConfig.xml. However, Quarkus does not recognize the classpath. It says: Invalid quarkus.optap lanner.solverConfigXML property (src/main/resources/solverConfig.xml): that classpath resource does not exist. I followed the response of Optaplanner and Quarkus solver config update. But, it does not work.
The solverConfig.xml is configured as:
<!-- Domain model configuration -->
<solutionClass>org.acme.optaplanner.domain.TimeTable</solutionClass>
<entityClass>org.acme.optaplanner.domain.Lesson</entityClass>
<!-- Score configuration -->
<scoreDirectorFactory>
<constraintProviderClass>org.acme.optaplanner.solver.TimeTableConstraintProvider</constraintProviderClass>
</scoreDirectorFactory>
<!-- Optimization algorithms configuration -->
<termination>
<minutesSpentLimit>1</minutesSpentLimit>
</termination>
<constructionHeuristic>
<constructionHeuristicType>FIRST_FIT_DECREASING</constructionHeuristicType>
</constructionHeuristic>

The src/main/resources prefix isn't part of the value for that property:
Either don't have a quarkus.optaplanner.solver-config-xml property in application.properties, which means it will pick up src/main/resources/solverConfig.xml (recommended, for standardization only)
Or set it explicitly to quarkus.optaplanner.solver-config-xml=solverConfig.xml to pick up src/main/resources/solverConfig.xml.
PS: solverConfig.xml in Quarkus doesn't need a entityClass, solutionClass or constraintProviderClass. It picks that up automatically.

Related

How to retrieve full endpoint URL in Quarkus test?

I am looking a solution to retrieve full endpoint URLs within Quarkus application to use it in tests to avoid hard-coding the paths.
The official guide suggests using the #TestHTTPEndpoint and #TestHTTPResource annotations.
If I annotate my test class with #TestHTTPEndpoint(MyResource::class), then all calls via RestAssured without specifying the path work just fine. The problem is, when I try to retrieve the endpoint URL like this (let's say, I need to call multiple endpoints in one test):
#TestHTTPEndpoint(MyResource::class)
#TestHTTPResource
lateinit var myResourceUrl: URL
it kind of works, but the injected URL does not include the quarkus.http.root-path value.
Instead of http://localhost:8081/root-path/my-resource I get just http://localhost:8081/my-resource.
Is there a way to retrieve a full endpoint path that includes the quarkus.http.root-path value?
Introduction
Let's consider the following versions as the current versions.
Quarkus: 2.11.2.Final.
Root cause analysis
The io.quarkus.test.common.http.TestHTTPResourceManager (TestHTTPResourceManager for short) class performs the value injection into the fields annotated with the io.quarkus.test.common.http.TestHTTPEndpoint (TestHTTPEndpoint for short) annotation:
The TestHTTPResourceManager class retrieves an instance of the org.eclipse.microprofile.config.Config (Config for short) from the org.eclipse.microprofile.config.ConfigProvider (ConfigProvider for short) class and uses the test.url configuration property value retrieved from the Config instance (the Config.getValue(…) method call) as the base URL.
The retrieved test.url configuration property value seems to correspond to the test.url system property value that was provided by the io.quarkus.test.common.http.TestHTTPConfigSourceProvider (TestHTTPConfigSourceProvider for short) class.
Possible root cause
For some reason the TestHTTPConfigSourceProvider class does not take into account the quarkus.http.root-path property value, when providing the test.url system property value, which seems to be used as the base URL: quarkus/TestHTTPConfigSourceProvider.java at 2.11.2.Final · quarkusio/quarkus:
static final String TEST_URL_VALUE = "http://${quarkus.http.host:localhost}:${quarkus.http.test-port:8081}${quarkus.servlet.context-path:}";
static final String TEST_URL_KEY = "test.url";
Therefore, it looks like a Quarkus issue: a defect (a bug) or a lack of a feature (or a lack of the feature implementation).
Therefore, it is worth reporting it as a Quarkus issue.
OK, so it seems to be a bug in Quarkus and will be fixed soon.
#TestHTTPResource annotation injects endpoint URL without the quarkus.http.root-path segment · Issue #27416 · quarkusio/quarkus · GitHub.
As a workaround, one could set the quarkus.servlet.context-path property in the test/resources/application.properties file like this:
quarkus.servlet.context-path=${quarkus.http.root-path}

Sharing properties between bootstrap configurations

Problem:
I have two libraries whose purpose is to take properties from their respective sources and provide them to my application at startup. Currently both libraries provide their own PropertySourceLocators as a part of their BootstrapConfiguration.
(Just as described here https://cloud.spring.io/spring-cloud-static/spring-cloud-commons/1.3.3.RELEASE/multi/multi__spring_cloud_context_application_context_services.html#customizing-bootstrap-property-sources)
E.g.
libraryX is responsible for getting properties from SourceX and configuring a respective PropertySourceLocator.
libraryY is responsible for getting properties from SourceY and configuring a respective PropertySourceLocator
These libraries are configured at my bootstrap.yaml. E.g.
libX.enabled: true
libX.password: ${LIB_X_PASS}
libY.enabled: true
libY.password: ${LIB_Y_PASS}
Everything works great as long as these libraries don't use properties from one another.
Unfortunately, in my case libX should be a source of ${LIB_Y_PASS}.
So the bootstrap.yaml is now looking something like this:
libX.enabled: true
libX.password: ${LIB_X_PASS}
libY.enabled: true
libY.password: ${libX.values.lib_y_pass}
In this configuration application no longer starts since resolution of ${LIB_X_PASS} and ${libX.values.lib_y_pass} happens before PropertySourceLocators are called.
Potential solutions:
Use #PropertySource instead of PropertySourceLocator at libX.
Values provided by #PropertySources seem to be available at the moment when resolution of properties in bootstrap.yaml is happening. The only issue is, is that it seems to have the same priority with other application*.yaml/application*.properties files, located in the project. So it is impossible to override existing properties with something that will come from libX.
E.g.
libX.enabled: true
libX.password: ${LIB_X_PASS}
libY.enabled: true
libY.password: ${libX.values.lib_y_pass}
libX.values.lib_y_pass: dummy_password
libY.password will have dummy_password value instead of whatever comes from libX #PropertySource. Possible reason for that is the fact that bootstrap.yaml as propertySource comes before the property source libX created and during resolution spring picks the value from the first propertySource that has it.
Use org.springframework.boot.env.EnvironmentPostProcessor
We can inject libX property source as first property source during environment post processing phase.
E.g.
#Override
public void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application) {
....
environment.getPropertySources().addFirst(libxPropertySource);
}
This seems to work fine and fixes the problem from the solution#1, but I don't know if there are hidden problems that I haven't found yet.
Question
Are there better ways to approach the problem?
It seems like either:
A) My case (when I need properties from one bootstrap PropertySourceLocator in another) goes against the design of PropertySourceLocator and in this case hacks like these is the only way.
B) I'm missing something and the problem can be solved in an much easier way.

Spring ResourceBundleMessageSource multiple properties files configuration in spring xml file?

For example I am having two properties file like message and query. how can configure in the spring xml
Well, you could use the below code snippet.
<context:property-placeholder
location="classpath:dao.properties,
classpath:services.properties,
classpath:user.properties"
ignore-unresolvable="true"/>
In this, the order attribute needs to be specified to fix the order in which these are processed by Spring.
All property placeholders minus the last one (highest order) should have ignore-unresolvable="true" to allow the resolution mechanism to pass to others in the context without throwing an exception

OpenLiberty server.xml boolean variable data-types

OpenLiberty does not seem to support variable substitution of boolean data-types. I have a MicroProfile JWT configuration element (ignoreApplicationAuthMethod) that I would like to tokenize. Are there best practices for externalizing boolean parameters needed in server.xml? To work around this I have pulled the entire mpJwt configuration element up into our parent environment specific xml, but this in not ideal as not every server requires this mpJwt configuration.
What I would like to do:
`<mpJwt audiences="myAud" id="${jwtBuilderName}" ignoreApplicationAuthMethod="${enforceJwt}" issuer="http://openliberty.io" keyName="secretKey" mapToUserRegistry="false"/>`

How to find out if a property is defined in placeholder in Spring?

Due to some backward compatible reasons, some old apps didn't define a new property in its app.properties, which is referred in a shared Spring context.xml thru placeholders. Is there a way in Spring to find out if a property is defined in the placeholder?
There are posts about setting null default values using Spring expression language. But, I don't see an answer on how to determine if a property is defined in the placeholder, or you'd get "Could not resolve placeholder ...".
I'm looking for something like
<constructor-arg value="#{someAPI('my.new.prop') ? ${my.new.prop} : #null}" />
Your input is highly appreciated!

Resources