Read POM values in external application properties - java

I have the following properties in the pom file
<name>DemoApplication</name>
<description>Demo spring project</description>
<version>1.0.0-SNAPSHOT</version>
And I have a class that reads the properties from application.yml
But instead of using the application.yml under src/main/resources I am specifying the properties through an external file as follows
java -jar DemoApplication-1.0.0-SNAPSHOT.jar --spring.config.location=application.yml
In this external application properties, I have the following attributes
swagger:
apiTitle: '#project.name#'
apiDescription: '#project.description#'
apiVersion: '#project.version#'
The issue is that the #project.name# and other properties are not being replaced as expected, but are read as-is.
How should the problem be approached?

According that section of the official documentation of Spring Boot v2, you can configure it with :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<configuration>
<delimiters>
<delimiter>#</delimiter>
</delimiters>
<useDefaultDelimiters>false</useDefaultDelimiters>
</configuration>
</plugin>
With useDefaultDelimiters set to false or to true depending on your configuration.
The others sections of that official documentation will be helpful for your use case, especially these one : "77.5 Use YAML for External Properties".
If nothing is working, why don't you are loading a custom Properties file ? It could be loaded as you need without any problem. Just reference it with the correct path when you are starting your program, and inside your program, test if your file config.properties is available and contains what you need to work with.
Of course, the Maven way of loading resources files is the best easy way to go, and it should be a simple Properties file too. I have done exactly that way inside the software I am released to manage my configuration :
Writing a app.properties
Loading that file with Maven at runtime with resource configuration
Expanding properties with classical syntax ${my.prop}
Run the program with a Maven task.
Of course, when you distribute your app as a jar, it is a bit different.
Maybe you can try to write your properties files within a Maven goal.

Related

SpringBoot: How to make profile specific resources

I have profiles: dev, prod.
And my homepage located at /src/main/resources/static/index.html
How to make different homepage with different profile?
For example, /src/main/resources/static-dev/index.html and /src/main/resources/static-prod/index.html.
Any advice?
Finally I got a simple solution.
Use different config file application.properties and application-prod.properties.
Each of them I config a different resource location. For example spring.resources.static-locations=classpath:/static-dev/.
If your project supports the Maven dependency manager, Maven's build profiles may be able to help you:
<profile>
<id>live</id>
<properties>
<environment>live</environment>
</properties>
<build>
<resources>
<resource>
<directory>src/main/resources/${environment}</directory>
</resource>
</resources>
</build>
</profile>
The code above should be in your pom.xml. In your Spring properties you can specify the active profile in one line:
spring.profiles.active=live
This should be enough to conditionally load any resources.
Both resources should be put under /src/main/resources/static (since this is the default static resource folder IIRC) and then categorized into /prod and /dev. Then in your #GetMapping controller, choose to return /prod/index or /dev/index based on your condition
You can create a Filter that changes the request URL from /index.html to /dev/index.html or /prod/index.html as needed.
The filter can also do the /dev or /prod prefixing for .css and .js files.
Unless all your files are split between dev and prod, you'd probably need an explicit list of which requests should be prefixed.

Find which JKS through code

I think its a basic question but I could not find anything regarding it on the internet.
I am writing a small webservice in a monolithic application. I wanna programmatically find out which Java Key Store is being used.
Inside my pom file I can see something like this:
<artifactId>maven-surefire-plugin</artifactId>
<version>2.16</version>
<configuration>
<systemProperties>
<property>
<name>javax.net.ssl.trustStore</name>
<value>keystore/kc.jks</value>
</property>
</configuration>
Now is the Keystore mentioned in pom file being used or the internal Java one.
NOTE: I want to write some Code to find which keystore rather than just checking some configurations.
The systemProperties setting in your pom file only applies to your tests, and only applies if you also configure surefire to fork, which you haven't. So it's having no effect. If you set surefire to fork, so that system properties would take effect, you could see the setting with:
System.getProperty("javax.net.ssl.trustStore")

Specify pom properties via a properties file?

Due to the way my build system is designed (RTC Build Engine), I would like to provide maven with property values via a properties file, instead of specifying -Dkey=value for every property.
I found a couple of questions on S.O. (How to set build properties from a file in Maven POM? and How to read an external properties file in Maven) that relate precisely to this question, but they are relatively old, and both require custom plugins to work (in alpha state).
I realize that passing parameters to Maven like this is probably not the best solution, but the other option is specifying everything on the command line via -D settings which is not ideal either.
Furthermore, given that this properties file is only really used by the build engine (and not by the individual developer), I don't truly believe it belongs in the pom. But I cannot find any other mechanism that would allow me to specify a plugin to use - settings.xml does not permit specifying plugins.
Is my only choice in this case to use a plugin and specify it in the project pom?
in the pom you can place...
<properties>
<core-version>1234</core-version>
<lib-version>1234</lib-version>
<build-version>9999</lib-version>
<build-date>20150101</build-date>
</properties>
with all the properties you require.
Or you can use...
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-2</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>dev.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
and the file dev.properties will contain the properties
core-version=1234
lib-version=1234
build-version=9999
build-date=20150101
...
Or... you can inject the properties using a settings.xml file as shown here
You may also find the Maven build number plugin useful... here
The best in such cases is to upgrade to at least Maven 3.2.1 which supports defining such properties on the command line like the following:
mvn -Drevision=1234 -Dchangelist=WhatEver -Dsha1=XXXX clean package
But you can only use the above names.
Excerpt from release notes:
A simple change to prevent Maven from emitting warnings about versions
with property expressions. Allowed property expressions in versions
include ${revision}, ${changelist}, and ${sha1}. These properties can
be set externally, but eventually a mechanism will be created in Maven
where these properties can be injected in a standard way. For example
you may want to glean the current Git revision and inject that value
into ${sha1}. This is by no means a complete solution for continuous
delivery but is a step in the right direction.

Refreshing static content with Spring MVC and Boot

I'm evaluating Spring MVC & Boot and AngularJs for building web applications. I've run into the problem that when I make modifications to my static content (html, js, css), I have to restart the application every time. I hope there is a some way of solving that because restarting the whole application for static content changes is not efficient. Every other web app framework I've tried allows updating static content files on the fly(even just Spring MVC and plain old WAR application).
I've setup my project from "Building a RESTful Web Service with Spring Boot Actuator" guide (http://spring.io/guides/gs/actuator-service/). Basically it uses Spring Boot and MVC controllers to create a REST service. In addition, I've used "Consuming a RESTful Web Service with AngularJS" guide (http://spring.io/guides/gs/consuming-rest-angularjs/) to build a frontend with AngularJS. It creates a web page that displays the response from the REST service. The only change I've made is that the requests are made to my application instead of "http://rest-service.guides.spring.io/greeting". My static content is stored in "src/main/resources/public" folder. This setup works correctly except it doesn't reload static content.
A recap of the original problem
I've run into the problem that when I make modifications to my static content (html, js, css), I have to restart the application every time
I had the same problem and finally solved it by adding
<configuration>
<addResources>true</addResources>
</configuration>
to spring-boot-maven-plugin in the pom.xml
I got confused by this spring-boot-devtools thing, but it had no effect whatever I did.
My static content is stored in "src/main/resources/public" folder.
Your path is just fine. src/main/resources/static is also fine.
Ah ... I came across this issue too.
Instead of putting your static content in the classpath src/main/resources/public folder, put them in src/main/webapp, the same as you would any other Java web app. The embedded Tomcat will automatically reload them whenever they change.
As mentioned in the comments, the default configuration will not include the resources that are in src\main\webapp. To get around this issue, you can just add the following to your pom.xml <build> node:
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/classes/static</outputDirectory>
<resources>
<resource>
<directory>src/main/webapp</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
By using the resources plugin, you are able to do your local development by running the executable JAR:
java -jar target/.jar
While that is running you can use Chrome Dev Tools or whatever IDE you like for modifying the files, without restarts. However, whenever you run your build, then the package generated will include all of the files under src\main\webapp in src\main\resources\static.
The docs say "all modern IDEs allow reloading of static resources and usually also hot-swapping of Java class changes" (https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/html/howto.html#howto-hotswapping). It's true. Eclipse does it more or less by default, and I'm not an IntelliJ user, but from what I understand you can configure it to build automatically as well.
A colleague and I came across this issue as well. We found the answer in the IntelliJ documentation...
On the main menu, choose Run | Reload Changed Classes
My solution (written in Kotlin but is quite obvious):
#Controller
class WebController : WebMvcConfigurerAdapter() {
override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
System.getProperty("resources.local.path")?.let {
registry.addResourceHandler("/**").addResourceLocations(it)
}
}
...
}
Main idea is you can add your own resource handler conditionally. E.g. if some system property is set (resources.local.path) then add resource location with value from the property. Then you set this property in development with some reasonable value like '-Dresources.local.path=file:/Users/andrey/Projects/gsp-test/src/main/resources/static/'.
Do not forget trailing slash.
I am using 1.5.8.RELEASE.
It instantly updates my changes especially static files or jsp files.
If you are using Maven. You need to add this in pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
And you have to start Spring Boot with this:
mvn clean spring-boot:run
Full example and more detail here https://www.surasint.com/spring-boot-with-auto-update-changed-files-example/
#eigil metioned addResources config for maven build. I'm using spring-boot-gradle-plugin in a gradle build, and I found this Spring Boot github issue
, and the Spring Boot doc mentioned this option too. Just add this directive to build.gradle and run Gradle task bootRun, then resource file refreshes immediately when saved. FYI.
I had the same issue , the solution proposed here seems logical and worked for me
in breif :
1- ctrl+shift+A
2- search for registry
3- in the opened dialogue search for "compiler.automake.allow.when.app.running"
and check it
http://garywaddell.com/2015/11/20/spring-boot-intellij-idea-not-reloading-static-content/
For eclipse you have to activate the Project -> "Build Automatically" option as a minimum configuration.
What I ended up using was Browsersync with grunt. browsersync and grunt watches your static resources on disk and updates the browser when you edit the files. It acts as a kind of proxy. This way you can see changes in UI immediately without building or restarting anything.
Grunt, browsersync, spring boot and angularjs are configured for you if you use JHipster which I used to setup my project.
Granted this requires a lot more tools than just an IDE and is a lot more complicated so I wouldn't recommend this for every project.
spring-boot-devtools is not the solution to "hot deploy" of edited static htm/js
I configured a web facet inside intellij so that when I use it to edit html/js file inside resources/static, intellij then knows to copy the updated file to ./target and the spring boot application I have launched inside the automatically displays that content
see
https://www.jetbrains.com/help/idea/2016.2/configuring-static-content-resources.html
The Java version of #viator 's answer:
#Configuration
class WebMvcConfigurer extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/dist/*.js").addResourceLocations(
"file:src/main/typescript/dist/"
);
}
}
You can do it by just adding one more dependency
you Gradle
compile group: 'org.springframework.boot', name: 'spring-boot-devtools', version: '1.3.0.RELEASE'
In you Pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<version>1.3.0.RELEASE</version>
</dependency>
You have two possebilities how to serve static webcontent
From the classpath (per default src/main/resources/static
or src/main/resources/public or META-INF/resources/)
From the file system (per default src/main/webapp)
If you pick solution 1) - you can safely copy the jar around as the static web content is within that jar. If you want that the server picks up changes, you need to do (auto)hotswapping.
If you pick solution 2) - everything will work out of the box, every change will be automatically picked up. HOWEVER - if you copy the final jar to a different location - things will stop working. That is unless you specify an absolute path in application.properties. For example:
spring.resources.static-locations=file:///C:/myspringbootapp/src/main/webapp
So solution 2) is easier but less portable. Solution 1) is portable but more difficult to use(ide config).
For Spring Boot 2+ with gradle Kotlin dsl:
tasks.bootRun {
sourceResources(sourceSets.getAt(SourceSet.MAIN_SOURCE_SET_NAME))
}
thanks to #briskr's answer for the gradle dsl version :)
I had the same problem with live reloading of static contents in my SpringBoot porject: Now from various solutions posted in StackOverflow, I am able to get the solution. Following are the tools I used for development: IntelliJ Idea & Google Chrome in Ubuntu 18.04
I did the following:
Kept the templates folder in resourses folder itself. (Some solutions I found it to be kept in webapp folder under the main, but I did not get the result)
Add this configuration
<addResources>true</addResources>
</configuration>
to spring-maven-plugin in your POM file.
3.Please don't forget to add this dependency to POM file
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
Add the Live Reload extension to your web browser.
Restart the server using ' mvn clean spring-boot:run ' (only then the changes will be reflected in the build). During server startup you can see the message Live Server started at ....
Load the page using localhost:8080/... and click the LiveReload extension to connect it with the server.
Make any change to your static HTML file in the resources/ templates folder. Save it and check the webbrowser again, it will be reflected there...

Adding classpath to jetty running in maven integration-test

I'm trying to set up integration tests for a Maven project that produces a war file. (As seen here http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin/.) However I the war file requires a bunch of .properties files on the classpath, that I don't want to bundle in the war.
Is there a way (preferably through plugin configuration) to add a folder to the classpath used by jetty?
I Googled this and found http://markmail.org/message/awtqrgxxttra3uxx but this, as far as I can tell, does not actually work at all. The .properties files are not found.
This should be possible using the webAppConfig configuration element (sample below taken from this thread):
<webAppConfig>
<contextPath>/nportal</contextPath>
<!-- All I want to do here is add in the /etc/jetty/classes for runtime files. For some reason I have to also add back in the /target/classes directory -->
<extraClasspath>${basedir}/target/classes/;${basedir}/etc/jetty/classes/</extraClasspath>
</webAppConfig>
If you find that the above solution doesn't work for you, consider including the test classpath into your Jetty configuration.
<configuration>
<useTestClasspath>true</useTestClasspath>
...
</configuration>
This will then allow you to place all manner of resources/classes on the test classpath and have them visible to the Jetty server without them creeping into the production code.
You can place your additional configuration files under /src/test/resources and set a property <useTestScope>true</useTestScope> in the plugin configuration as specified here:
useTestScope
If true, the classes from testClassesDirectory and dependencies of scope "test" are placed first on the classpath. By default this is false.

Categories

Resources