I have a Lib-A that has a dependency on com.atlassian.oai:swagger-request-validator-core. This dependency has a properties file messages.properties.
I have an App-A that has a dependency on Lib-A. If I place the messages.properties file in App-A, I am able to overwrite the properties, but if I place it in Lib-A, it doesn’t overwrite. How do I overwrite the properties from Lib-A?
There seems to be no way of changing the path as well: https://bitbucket.org/atlassian/swagger-request-validator/src/master/swagger-request-validator-core/src/main/java/com/atlassian/oai/validator/report/MessageResolver.java#lines-26
Advertisement
Answer
Easy peasy:
demo/pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.32</version> </dependency> <dependency> <groupId>com.atlassian.oai</groupId> <artifactId>swagger-request-validator-core</artifactId> <version>2.22.0</version> </dependency> </dependencies> </project>
demo/src/main/resources/swagger/validation/messages.properties (case sensitive):
validation.request.path.missing=FOO '%s'. # an existing key from ... # ...swagger-validator with custom message (and complying parameters)
demo/src/main/java/com/example/demo/Main.java:
package com.example.demo; import com.atlassian.oai.validator.report.MessageResolver; import com.atlassian.oai.validator.report.ValidationReport.Message; import org.slf4j.Logger; import static org.slf4j.LoggerFactory.getLogger; public class Main { private static final Logger log = getLogger(Main.class); public static void main(String[] args) { MessageResolver mr = new MessageResolver(); Message m = mr.get("validation.request.path.missing", "bar"); log.info("got message: {}", m == null ? null : m.getMessage()); } }
(with these 3 files only, Execute) In your terminal (or in an IDE):
>cd demo >mvn clean process-classes exec:java -Dexec.mainClass="com.example.demo.Main"
Output:
[INFO] ... [INFO] --- exec-maven-plugin:3.0.0:java (default-cli) @ spring-data-demo --- [com.example.demo.Main.main()] INFO com.example.demo.Main - got message: FOO 'bar'. [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 4.775 s [INFO] Finished at: 2021-11-11T17:33:39+01:00 [INFO] ------------------------------------------------------------------------
If we delete/rename/move our messages.properties, we get (the original) No API path found that matches request 'bar'
.
I.e. by only placing the file in the correct location (classpath:/swagger/validation/messages.properties
), we could change the message(s) of a (default) MessageResolver
.
Edit1:
I think this will “always work”, since the files in your bin/target folder will have precedence over “resources in jars”, but it depends on classpath/-loader/execution details. But under these conditions any (default) MessageResolver created in “your jvm”, will prefer that/your messages.properties
If you do so, ensure all keys are available in your messages.properties
(+ match parameter count(&semantics)), since when trying this:
// message key not present in (our!) swagger/validation/messages.properties log.info("got other message: {}", mr.get("validation.request.operation.notAllowed", "foo", "bar") );
,we get ;(;(:
[com.example.demo.Main.main()] INFO com.example.demo.Main - got other message: null
Edit2:
Instead of (effectively)overwriting/replacing the (default) “resource bundle”, you can also have all of the “inheritance and fallback magic”, by addding language, country, platform specific messages (but still falling back to the default ones.)
exemplary folder structure:
demo --src ----main ------resources --------swagger ----------validation ------------messages_en_GB.properties ------------messages_en_US.properties ------------messages_en.properties ------------messages_de.properties ------------...
See also:
- https://www.baeldung.com/java-resourcebundle
- https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/ResourceBundle.html#default_behavior
Edit3:
I got it (replacing as “adding”) also working on a transitive dependency, but i had to ensure, that :
- or
demo
is the only (direct) dependency. - or it appears (locally in the pom) before
swagger-request-validator-core
.
That sounds not really reliable, but that’s what i’ve found/tested.
And “beyond maven” (sorry used it), we can say: the dependency with customized messages, should appear in the class path before swagger-request-validator-core.jar