PropertySource property file is being ignored by scanning env property file - java

In my spring boot project, I have env property(application-dev.prop) file placed directly under resources folder, this prop file has some connection properties defined. The same connection properties with different value defined in user.properties file( which needs to be injected in a specific config class)placed under resources/config.I have annotated that specific config class with #PropertySource(value = "classpath:/config/user.properties"). But however this config class takes connection values from env property file but not from user.prop file even if that class annotated with property source user.property class path. This config class only accepts user.property value if a particular field not defined in env property file. In short it checks user.property file only if any field/property not defined in env.property file. But I want this config class to point user.property file always. I already checked spring boot precedence for scanning property file but couldn't resolve. Can anyone help me fix this issue.

As per the doc,
In cases where a given property key exists in more than one .properties file,
the last #PropertySource annotation processed will 'win' and override.
I think a better approach would be to use a profile if that fits your use case.
The link here explains how to add profiles pretty neatly. you can check tht out.
Another approach I would suggest if you think adding a profile is not the right choice, you can make them passed down as environment variables. This gives you flexibility to change it as necessary and you can also give a default value for the environment variables.

Related

Spring #TestPropertySource classpath vs file

Is there way to load test properties like this?
#TestPropertySource("${test.config:'classpath:application.test.properties'}")
The point is to check test.config argument (there could be something like file:c:/test.properties) and if the value is not set, then it will take default properties from classpath.
I was able to load properties from classpath swithing it using argument.
I was unable to combine classpath and file
Solved:
#PropertySource(value = {"classpath:application.test.properties","${test.config}"}, ignoreResourceNotFound = true)
if environment variable test.config is not defined then context will
not be loaded
if environment variable test.config is defined but file
test.properties is not present then also context will loaded.
I think you are not using TestPropertySource as per it's use case.
TestPropertySource is used if you want to override some properties during test cases. If you want to override some properties in test cases, just put those properties in test property file.
Spring will override only those properties which are there in in test property file
Not sure why you want to check test.config environment variable and then do some operations .

Set where to find the config file for audit4j

I've looked all over the documentation, but was unable to find one. How can I achieve this?
According to the Audit4j documentation and javadoc there are multiple ways to specify the configuration:
It can be injected into the Context directly by calling static methods of the Context class (e.g. at application startup before doing any audit!):
Context#initWithConfiguration(Configuration configuration) with the appropriate Configuration
or Context#initWithConfiguration(String configFilePath) to specify the configuration as file.
Other ways to specify the path to the configuration file without manually initializing the Context are:
Setting path in environment variable "AUDIT4J_CONF_FILE_PATH"
Setting path in Java system property variable "audit4j.conf.file.path"
Also the configuration file can be put into the application classpath or the user directory. In this case the name of the configuration file has to be "audit4j.conf.yml" or "audit4j.conf.yaml" for YAML style or "audit4j.conf.xml" for XML style.

Issue overriding application properties in Spring-boot (profile-specific) application launched with PropertiesLauncher

I'm having difficulty trying to override a property declared in a profile-specific application properties file on the classpath with another value declared in an overrides file on the file system.
I have an auto-configured Spring-boot application (that is, using #EnableAutoconfiguration) that has multiple profiles, which I launch using PropertiesLauncher rather than JarLauncher (the reason having to do with deployment constraints - I need to deploy an exploded directory rather than an archive into a read-only filesystem.)
Within the root of my application, I have some profile-specific application properties, for example:
application-dev.properties
application-qa.properties
application-prd.properties
And let's say, for the sake of argument that application-dev.properties contains:
foo.bar=baz
foo.baz=other
For any environment, it may be necessary to override an existing property, as well as supply an absent one (like a production password, for example), and the issue I'm seeing is with overriding properties already declared in an application-${profile}.properties file on the classpath. (Supplying properties not present in the classpath file works fine, this is not the issue.)
Say I have an overrides properties file in a file system location such as:
/local/appname/dev/overrides/application.properties
and I want to override the property, foo.bar, as well as declare a new property, foo.password.
Therefore the contents of the overrides file are:
foo.bar=overridden-value
foo.password=something
When I launch the application, I use a command line something like this:
java -Dspring.config.location=file:/local/appname/dev/overrides/
-Dspring.profiles.active=dev
org.springframework.boot.loader.PropertiesLauncher
--debug &
The issue I am seeing is that although foo.password, the property not declared in the application-dev.properties file is picked up, the override of foo.bar is ignored - I still see the value, baz from application-dev.properties rather than the value, overridden-value from /local/appname/dev/overrides/application.properties.
With the --debug option enabled, I can see the ConfigFileApplicationListener logging that it has loaded both the overrides file (from the filesystem) and the profile-specific file (from the classpath), in that order.
I'm tempted into the perhaps naïve conclusion that because the overrides file is listed first, it is being loaded first then overridden by the 'default' profile-specific file from the classpath, which is listed later. I do appreciate however, that order of listing in the log doesn't necessarily correlate with behaviour. And I have tried varying the order of paths declared on the spring.config.location property, so that classpath: is listed before file:... but this hasn't helped and I't not convinced it would anyway, given that the Spring-boot documentation clearly states that the default properties locations are always searched even if you supply a value for spring.config.location.
The Spring-boot documentation is very specific about the order that properties are resolved for a Spring-boot executable JAR, in descending order of precedence:
Command line arguments.
Java System properties (System.getProperties()).
OS environment variables.
JNDI attributes from java:comp/env
A RandomValuePropertySource that only has properties in random.*.
Application properties outside of your packaged jar (application.properties including YAML and profile variants).
Application properties packaged inside your jar (application.properties including YAML and profile variants).
#PropertySource annotations on your #Configuration classes.
Default properties (specified using SpringApplication.setDefaultProperties).
Take note of lines 6 and 7 - properties outside over properties inside your jar.
What's not stated, as far as I can see, and which may be the source of my confusion/issue, is what happens when you're not using a JAR but an exploded directory (and therefore PropertiesLauncher.)
If the behaviour of an exploded directory were consistent with what's stated for a JAR, I'd expect that the values of properties declared in /local/appname/dev/overrides/application.properties would override any of the same name declared in classpath:application-dev.properties, but this doesn't seem to be the case.
Also noted from the Spring-boot documentation (appendix C.4 on PropertiesLauncher) is mention of the loader.home property, which is described as '... [the] Location of additional properties file, e.g. /opt/app (defaults to ${user.dir})'.
So I tried using loader.home instead of spring.config.location, but to no avail.
(Update: I also tried using loader.config.location and I have two notes: it seems to want a file rather than a directory (so its behaviour is not analogous with spring.config.location), and when I did supply a file path rather than the parent directory, it still didn't help.)
Can anyone spot what I'm doing wrong, or what incorrect assumption(s) I'm making?
Thanks, Dave, your suggestion was 100% correct.
If I rename the properties file in /local/appname/dev/overrides to application-dev.properties then the property values from that file do override the ones in classpath:application-dev.properties.
I was sure I had tried this combination yesterday, but I think what must have stopped it working was when I was playing around with specifying the spring.config.location and got that wrong so it wasn't looking for the override file in the right place.

Spring value injection - if no env variable then default to system property from file

I am looking for a neat way of injecting values from environment variables to pojo, but with default values for not set env variables. I know about this syntax:
#Value("#{systemProperties['JDBC_CONNECTION_STRING'] ?: \"jdbc:mysql://localhost:3306/mydb?user=root\"}")
But it means that I have to hardcode defaults in java files. And I would prefer to have it in properties file. Is it possible?
I need this because on AWS EBS env variables are only way to pass properties but we don't deploy only there. On other places I want to read props from file.
In your spring.xml config file you add the following:
<context:property-placeholder order="-50"/>
And then
<context:property-placeholder order="0" location="classpath:x.y.z/application.properties"/>
The first property-placholder will load all the values from system properties and the second will load from a properties file.
Notice how the order for the system properties one less than the application properties one so the system properties will take precedence.
Now in your class files you simply do this:
#Value("${JDBC_CONNECTION_STRING}")
private String jdbcConnectionString
And it will inject the value from system properties if present and from application properties if it is not in system properties.
What I also like to do is have another properties file which I load from S3 whose order is between the above two so I can override the default.

Assigning one property to another in Maven

My Maven project has two properties which are used when filtering a persistence configuration file:
<database-url>jdbc:mysql://localhost/${database-name}?autoReconnect=true&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;rewriteBatchedStatements=true&amp;useServerPrepStmts=false&amp;useCursorFetch=true</database-url>
<test-database-url>jdbc:mysql://localhost/${test-database-name}?autoReconnect=true&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;rewriteBatchedStatements=true&amp;useServerPrepStmts=false&amp;useCursorFetch=true</test-database-url>
The properties need to be doubly-XML-encoded since the configuration file itself is an XML document and Maven resolves XML entities during resource filtering.
I'd like to be able to run my tests directly from my IDE, so I created a profile and set one property to another.
<database-url>${test-database-url}</database-url>
The problem is that Maven resolves the entities in the setting of the property, and then again during the filtering of the configuration file, which means that my configuration file is invalid XML.
Is there a way to set one property to another without resolving the XML entities?
Not a direct answer but... why don't you use different values for the same property depending of the profile. For example, a (default) development profile would have:
<database.url>jdbc:mysql://localhost:3306/app_dev</database.url>
And a test profile would have:
<database.url>jdbc:mysql://localhost:3306/app_test</database.url>
And if this is not what you want, maybe having a single database.url property for the url and passing a system property like -Ddatabase-name=app_xxx for the name would do the trick.
But I may be missing something.

Categories

Resources