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.
Before start explaining my issue, it's worth mentioning that although I am trying to work how to use Maven Jib plugin in conjunction with Spring Boot and Kubernetes, the issue is the same even if I try to use a normal docker.
I have used Kubernetes configMap to create the application.yml file and mount it as an external file to the Pod (/config/application.yml). The issue I have been facing is my application does not able to find the application.yml file and throw a typical exception:
ERROR [main] org.springframework.boot.SpringApplication: Application run failed
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.example.Application]; nested exception is java.io.FileNotFoundException: class path resource [application.yml] cannot be opened because it does not exist
I have tried different approaches with Jib by using different arguments such as below.
<container>
<extraClasspath>/config/*</extraClasspath>
<args>
<arg>--spring.config.location=file:/config/application.yml</arg>
</args>
<jvmFlags>
<jvmFlag>-Dspring.config.location=classpath:/,classpath:/config/,file:./,file:./config/,file:/config/</jvmFlag>
</jvmFlags>
</container>
None of them has worked for me. I have also tried to use the SPRING_CONFIG_NAME environment variable and set it to file:/config/application.yml for the pod, but still the same issue.
I can verify that the config file exists in the specified location and there are no permission issues (as far as I can tell).
Interestingly, when I create just an empty application.yml file in the default classpath (src/main/resources) then it passes the first verification and the application loads successfully (with using the actual values from /config/application), so whatever the issue is it is being impacted by an initial verification of Spring Boot before even passing the application file to the corresponding classes.
It turns out that the only item I need to have is the following:
<container>
<extraClasspath>/config</extraClasspath> <!-- No need to have * at the end -->
</container>
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...
I've read some questions here about how to set a property (most of them talked about the version number for an application) from a maven plugin.
It seems there's no easy way of doing this and the best solution I found is to have a filter.properties file which is updated from the plugin and used by the main pom file to filter the desired resources.
I tried another solution after I read this from the Maven documentation (Maven filter plugin):
Variables can be included in your resources. These variables, denoted
by the ${...} delimiters, can come from the system properties, your
project properties, from your filter resources and from the command
line.
I found interesting that variabled can be read from system properties. So, I modified my plugin to set a system property like this:
System.setProperty("currentVersion", appCurrentVersion);
However, filtered resources don't seem to read this value.
Could anybody tell me what's wrong with this approach?
UPDATE: I'm running my plugin in the validate phase.
Thanks a lot.
Don't set it as System Property, set it as Maven Project property
// inject the project
#Parameter(defaultValue = "${project}")
private org.apache.maven.project.MavenProject project;
// and in execute(), use it:
project.getProperties().setProperty("currentVersion", appCurrentVersion);
See:
Mojo Developer Cookbook
MavenProject javadoc
An edit suggested using Properties.put() instead of Properties.setProperty(). While technically, Properties implements Map, this usage is discouraged explicitly in the Properties javadoc.
Maven sets properties in initialize phase. I assume that in that phase maven loads system properties. And after that maven doesn't load system properties again. If you try to add a system property after this phase than it's not loaded.
Try to run your plugin in validate phase.
When I configure the scmchangelog-plugin, as written in the examples/tutorial, and run the site-generation, the username and password I have set are ignored.
The documentation says that username and password which should be used to access the SCM can be configured in the plugin-configuration. This looks like this:
<reporting>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>scmchangelog-maven-plugin</artifactId>
<version>1.3</version>
<configuration>
<grammar>REMY</grammar>
<connectionUrl>scm:svn:svn+ssh://repo.lan/repo/project/trunk</connectionUrl>
<username>user</username>
<password>password</password>
</configuration>
</plugin>
</plugins>
</reporting>
When i run the site-generation (mvn site), the output on the commandline says
[INFO] Executing: /bin/sh -c cd /tmp && svn --username user --password '*****'
--non-interactive list --xml svn+ssh://repo.lan/repo/project/tags/
But I'm still prompted for the the password and the user used to access the SCM is the one running the mvn command.
Any ideas what could be wrong?
Update:
I tracked down the problem to the svn command line client now.
the problem is, that when i run a command like the following
svn list --username foo --password bar --non-interactive svn+ssh://host/repo/project
the command line tool seems to ignore the given options. i'm still questioned for a password, and the user used to access the URL is the one who executes the command, and not the one set in the options.
i'm using svn version 1.4.6 here.
any ideas what might go wrong here ?
This is a known bug. The correct behavior would be to show an error that states that the --username and --password options are not supported when using an external authentication mechanism like SSH, instead of silently ignoring those options.
To fix your issue, pass your 'foo' username as part of the URL:
svn+ssh://foo#host/repo/project
and use something like ssh-agent to cache your credentials, thus avoiding the password prompt.
Do you mean the scm:changelog goal of the Maven SCM plugin? If this is the case you have two choices to ensure the SCM is passed your credentials.
Preferred approach
Some SCM providers allow you to specify a settings file below M2_HOME/conf/.scm, for example Subversion's is svn-settings.xml and CVS's is cvs-settings.xml
Your SCM provider should define how to define the configuration settings. For Subversion I end up with a file like this:
<svn-settings>
<user>[username]</user>
<password>[password]</password>
</svn-settings>
If needed, you can specify the SCM settings file in another location by passing a command-line parameter to the file:
-Dmaven.scm.svn.config_directory=your_configuration_directory
Other approach
The other (undesirable) option is to configure the scm section of the POM so that the urls contain the username and password. The implementation of this is provider-specific, but is generally of a similar form to this example for Subversion:
scm:svn:http://[user]:[password]#host/path
So your scm section in the POM would look something like this:
<scm>
<connection>scm:svn:http://[user]:[password]#host/path</connection>
<developerConnection>
scm:svn:http://[user]:[password]#host/path
</developerConnection>
<url>http://somerepository.com/viewsvn</url>
</scm>
This is obviously undesirable as your SCM credentials end up in your installed POM, you should really only use this for testing the connection in my opinion. For more information see the SCM URL Format page and details for specific SCM providers
Check if there's an alias clobbering your use of the "svn" command.
Also check if the destination host allows password-mode authentification. Might also be worth to check that the desktop doesn't fool around with some handy "keyring agent", those can interfere with svn+ssh.