Spring Boot not loading the active application.properties file - spring-boot

I'm using Spring Boot to activate profiles based on the environment as documented here
For the most part it works. However, I've hit an odd scenario.
I have three application-{profile}.properties files as follows :
application-dev.properties
application-uat.properties
application-release.properties
When I deploy a war file to uat, Spring is picking up a JDBC connection from the release file. The application.properties file contains one line -
spring.profiles.active=uat
If I change the name of the application-release.properties file to application-release.properties.tmp then Spring picks up the connection from application-uat.properties.
Any ideas.
BTW I'm using Spring.Boot 2.2.0-RELEASE

Solved!
Not sure which of the two changes that I made solved the issue but here it is.
When reading the comments in Daniel Olszewski's article, Marcelo Martins says that it is unnecessary to specify resource filtering in pom.xml when using 'spring-boot-starter-parent' which was further confirmed by Daniel. As I am using 'spring-boot-starter-parent', I removed it.
To solve my problem I re-inserted it.
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
...
</build>
I upgraded the maven plugin to 2.2.0.RELEASE
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.0.RELEASE</version>
</plugin>

Related

Get value from pom.xml into a yaml file

I am using swagger ui and im trying to read some properties in pom.xml into yaml file (Like version, artifactId for example), but i am get this error:
Parser error on line 3
bad indentation of a mapping entry
Full error here
The head of my openapi.yaml file. I need to use the artifactId in the title.
openapi: 3.0.3
info:
title: #artifactId#
Do i need to make something with the pom.xml? Export the file? Or there is another way to retrieve data from pom.xml?
You can use the resource filtering functionality provided by maven. link to doc
Change your openapi.yaml file to:
openapi: 3.0.3
info:
title: ${artifactId}
And add the following section to your pom.xml. (assuming that your openapi.yaml is in the resources directory)
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
Maven build will create an openapi.yaml file with the substituted artifactId in the target directory.
try using single quote:
api:
version: '#project.version#'
and inside the pom.xml,
<project>
...
<version>0.0.1-SNAPSHOT</version>
...
</project>
Another important thing!
If you have using some certificate or binaries files, it's also important to configure something like:
`<plugins>
<!-- allow resource files to contain references to Maven properties like ${prop.name} -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<nonFilteredFileExtensions>
<!-- exclude all binary files from filtering! -->
<nonFilteredFileExtension>p12</nonFilteredFileExtension>
<nonFilteredFileExtension>crt</nonFilteredFileExtension>
<nonFilteredFileExtension>pem</nonFilteredFileExtension>
</nonFilteredFileExtensions>
</configuration>
</plugin>`
Because can be you corrupt your certs if you don't do this.

Accessing module root path from spring cloud config server

I have following modules in my project:
root-mod
+ cloud-config-server
+ cloud-config-server-config-files
+ microservice-1
The directory cloud-config-server-config-files contain configuration files for the application and is a git repository. I would like to access these files from application.yml of cloud-config-server module. The problem here is that the following does not work: ${project.baseDir}/cloud-config-server-config-files/. Is there a way to access the location from application.yml of my config server?
Although not the most elegant solution(will keep this post open so that anyone with a better answer can answer), following worked for me:
I created a property in the pom.xml of cloud-config-server:
<properties>
<git-local-url>${project.basedir}/../cloud-config-server-config-files</git-local-url>
</properties>
Then added the resources directory to the <build> tag:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
...
</build>
Access this variable in application.yml:
uri: #git-local-url#
Ofcourse, this should be done based on the profiles there fore its best if the property is defied in the profile instead.
Cheers!

maven bundle plugin No translation found for macro:

I use maven bundle plugin for bundle spring project. I'm use spring property placeholder in my project. When I building my project I take following warnings:
[WARNING] Bundle groupId:artifactId:bundle:1.9-SNAPSHOT : No translation found for macro: spring.property
How I can prevent this warnings message ? May be some maven bundle plugin settings can help me ?
Thanks
It appears that the maven-bundle-plugin (v. 2.5.3 at the time of writing) has its own go at resource filtering after the resource plugin is done. If the resource plugin cannot replace a property it will simply leave it as it is. Which is what you want, of course, if the property is in a Spring context file to be replaced by Spring at run-time. But the left-over properties confuse the bundle plugin.
The only way around this that I could find was to disable resource filtering for the Spring context file. In the build section of your POM add something along the lines of this:
<resources>
<!-- globally enable resource filtering -->
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<!-- then disable it for specific resources -->
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*-context.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
You can also turn it around and explicitly include your to be filtered files in a resource declaration that enables filtering and globally disable filtering.

How to access maven.build.timestamp for resource filtering

I am using maven 3.0.4 and would like to make the build timestamp accessible to my application. For this, I'm putting a placeholder in a .properties file and let maven filter on build. While this is working fine for ${project.version}, ${maven.build.timestamp} is not substituted on filtering.
The property seems to be available on build - I can use it to modify the artifact name:
<finalName>${project.artifactId}-${maven.build.timestamp}</finalName>
So why is it not available for resource filtering? And, more importantly, how do I make it accessible?
I have discovered this article, explaining that due to a bug in maven, the build timestamp does not get propagated to the filtering. The workaround is to wrap the timestamp in another property:
<properties>
<timestamp>${maven.build.timestamp}</timestamp>
<maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
</properties>
Filtering then works as expected for
buildTimestamp=${timestamp}
I can confirm as of Maven 3.x {maven.build.timestamp} is "working" now. They work arounded the problem, apparently. No additional properties workaround needed anymore.
However, be careful your "filtering" plugin (maven-resources-plugin) is up to date. It needs to be relatively new, so if mvn help:effective-pom shows an old version (ex: 2.6), bump it to something newer, fixed it for me, 3.x ex:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<properties><timestamp>... workaround is no longer required...
This also cleared up, kind of, why it was working in IntelliJ but not the command line. IntelliJ probably uses their own "modified/internal" maven constants, so it was working there, but not from maven command line.
Also note if you add a filtering resource directory to you pom, you may need to also "re-add" the default directory, it gets lost, ex:
<resource>
<directory>src/main/resources-filtered</directory> <!-- to get "maven.build.timestamp" into resource properties file -->
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory> <!-- apparently have to add this is you have the other... -->
</resource>
NB if you're using spring boot as your parent, you have to use #maven.build.timestamp# instead. Also note if you're using spring boot there's a file META-INF/build-info.properties that is optionally created by the spring-boot-maven-plugin that you can read (spring provides a BuildProperties bean for convenience reading it).
In order to enrich the Stackoverflow content for others, that like me, found this post as a way to solve the "problem" of ${maven.build.timestamp}. This is not a maven bug, but an expected behavior of m2e, as can be seen in this post.
Therefore, I believe that we can not expect the solution to be "corrected", since, from what I understand, the correction involves conceptual issues.
In my case, what I did was use the plugin (buildnumber-maven-plugin) as described in this other post.
Adding Maven properties at the pom project level doesn't take into account correct local Timezone, so timestamp may appear wrong :
<properties><timestamp>${maven.build.timestamp}</timestamp></properties>
Using the build-helper-maven-plugin applies the correct timezone and current daylight saving to the timestamp :
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.9.1</version>
<executions>
<execution>
<id>timestamp-property</id>
<goals>
<goal>timestamp-property</goal>
</goals>
<configuration>
<name>timestamp</name>
<pattern>yyyy-MM-dd HH:mm:ss</pattern>
<timeZone>Europe/Zurich</timeZone>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
When packaging, Maven will replace any token timestamp in /resources folder, e.g. resources/version.properties :
build.timestamp=${timestamp}
You can then load this properties file in your Application.

How to filter resources when using maven jetty plugin?

I have an XML file (urlrewrite.xml) that needs a property placeholder resolved. I enable Maven filtering to achieve this. This works fine for the assembled WAR file.
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
The problem is when trying to run the application in development mode using the maven-jetty-plugin (Maven Jetty Plugin), as maven jetty:run .
The file in question, urlrewrite.xml, is located in the src/main/resources directory, and therefore should (and does) ends up in /WEB-INF/classes (or target/classes for maven jetty:run).
The URLRewriteFilter config specifies the location of the config file as follows:
<filter>
<filter-name>UrlRewriteFilter</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
<init-param>
<param-name>confPath</param-name>
<param-value>/WEB-INF/classes/urlrewrite.xml</param-value>
</init-param>
</filter>
This will work at deployment time. However, Using the jetty maven plugin, URLRewrite will die with a NullPointerException because it uses context.getResourceAsString("/WEB-INF/classes/urlrewrite.xml") in order to load the config file. Jetty returns null for this because when running the application from workspace it resolves /WEB-INF/classes/... to src/main/webapp/WEB-INF/... . The file does not exist there because the WAR has not yet been assembled. It should instead pull the resource from target/classes/urlrewrite.xml.
If that is obscure to you, then you probably won't be able to answer this question because I suspect you will need to be a Jetty guru to figure out a workaround (hint: that's a challenge!).
Does anyone know a way around this? I have also tried the following workarounds to know avail:
Put urlrewrite.xml under a new directory, src/main/webResources and add it to the maven war plugin <webReources> and enable filtering. That will copy it's contents in the appropriate location when the WAR is packaged, but will not make it available for jetty:run
Some other hacks I can't even remember ... (will update if I do)
In summary, maven-jetty-plugin needs the file to be under src/main/resources/webapp/insert path and filename in order to be available for the maven jetty:run command ...
Thanks for you help ...
Sincerely,
Lloyd Force
Answered my own question.
Upgrade maven-jetty-plugin to at least 6.1.12
See this wiki page on 'Configuring Multiple WebApp Source Directory' (available since jetty-6.1.12.rc2 and jetty-7.0.0pre3)
Add some magic to pom.xml:
First, add a new directory (src/main/webResources) for your filtered web resources and add a <resource> element:
<resource>
<directory>src/main/webResources</directory>
<filtering>true</filtering>
<targetPath>../jettyFilteredResources</targetPath>
</resource>
That will copy the files to target/jettyFilteredResources (we will reference this later). This directory will NOT get copied to your packaged WAR file, it is for jetty only!
Add the following element to your maven-war-plugin <configuration> element:
<webResources>
<resource>
<directory>src/main/webResources</directory>
<filtering>true</filtering>
</resource>
</webResources>
That will ensure everything is packaged up for your real WAR file.
Finally, tell jetty to use the resources your copied especially for it, by added the following snippet to your <baseResource> element:
<baseResource implementation="org.mortbay.resource.ResourceCollection">
<resourcesAsCSV>src/main/webapp,target/jettyFilteredResources</resourcesAsCSV>
</baseResource>
Now everything will worketh! (Well, technically I haven't tested the production WAR yet, but ... blah ... it should work too).
If anyone has a better answer, I will accept it provided the answer is provided in a reasonable amount of time (say 1 day).
I think the answer in this other question is better:
Running resource filters when using jetty:run
Basically, instead of running 'mvn jetty:run' you have to use 'mvn jetty:run-exploded'.
The only drawback is that it needs to build the WAR file, which might be expensive in some cases. If that's not an issue for you, then I guess it's better.
add this to pom.xml:
<resources>
<resource>
<directory>src/main/webapp/WEB-INF</directory>
<filtering>true</filtering>
<targetPath>../jettyFilteredResources</targetPath>
</resource>
</resources>
and this is how embedded Jetty server should look like:
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.1.3.v20140225</version>
<configuration>
<webAppConfig>
<descriptor>target/jettyFilteredResources/web.xml</descriptor>
</webAppConfig>
<scanIntervalSeconds>3</scanIntervalSeconds>
</configuration>
</plugin>
woila! thanks #les2 for inspiration ;-)
I found another way.
build the project and add the target folder as extra classpath.
<webAppConfig>
....
<extraClasspath>${basedir}/target/mywebapp</extraClasspath>
....
</webAppConfig>

Resources