How to override Java resources when you run Spring Boot fat-jar? - java

How to override Java resources when you run Spring Boot fat-jar?
I've created a Spring Boot far-jar that contains inside as resource a log4j.xml configuration file. Now when I run the fat-jar I'm trying to override it in this way
$ java -cp conf/ -jar target/myapp.jar
and I've put in the conf/ folder a new log4j.xml. But nothing, it continues to use the resource inside the jar.

If your goal is only to define your own log4j.xml configuration file, this could help:
java -Dlogging.config='/path/to/log4j2.xml' -jar target/myapp.jar
(this was mentioned already in How can I change the default location of log4j2.xml in Java Spring Boot? )
If you just want to add resources by classpath addition you could refer to
https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-executable-jar-format.html#executable-jar-property-launcher-features
where I found loader.path :
loader.path can contain directories (which are scanned recursively for
jar and zip files), archive paths, a directory within an archive that
is scanned for jar files (for example, dependencies.jar!/lib), or
wildcard patterns (for the default JVM behavior). Archive paths can be
relative to loader.home or anywhere in the file system with a
jar:file: prefix.

Related

How to specify a profile when deploying a Spring boot war file to Tomcat?

At the moment, all my properties are defined in the file src/main/resources/application.properties. However, I would like to have properties files relating to different profiles in the src/main/resources/config folder, and I want to be able to choose any of them. such as:
application-DEV.properties
application-TEST.properties
application-SERVER1.properties
So, the question is how to select these properties. If I was compiling to a jar file, I could do that easily by specifiying the profile when running the jar file, but here I just copy the generated war file to a Tomcat webapps directory.
Well, I've found a way to do that. In the conf directory of Tomcat, add this line to the file catalina.properties there.
spring.profiles.active=<YOUR_PROFILE>
Replace <YOUR_PROFILE> here of course with your profile's name. For example if you are using application-TEST.properties, it would be the following.
spring.profiles.active=TEST
You can define Jvm Argument -Dspring.profiles.active=<PROFILE> on server start up file (.bat/.sh) depending on your environment.

Take logback.xml to outside of the jar

I am using logback with slf4j in my Maven Java project. Currently logback config file (logback.xml) is in src -> main -> resources folder. And it is working fine.
My issue is, I need to give my client the ability to configure logging as he prefers. For that logback.xml should be outside the jar when I build it. But as xml is inside src folder it is inside the jar and no one can change it after build.
How to achieve this?
Specifying the location of the default configuration file as a system property
You may specify the location of the default configuration file with a system property named "logback.configurationFile". The value of this property can be a URL, a resource on the class path or a path to a file external to the application.
java -Dlogback.configurationFile=/path/to/config.xml -jar myapp.jar
From offcial docs
Logback config file location can be specified in application.properties or application.yml.
application.yml
logging:
config: logback-spring.xml
This allows you to place jar and log-back.xml at the same folder.
Please note that logback-spring.xml file in your project folder should not be included in your jar. This can be achieved setting on build.gradle or pom.xml.
build.gradle
bootJar {
archiveName 'your-project.jar'
exclude("*.xml")
}
The logback.xml file needs to be on the classpath, but it doesn't need to be inside any specific jar. The details of how you want to do this depend on the exact deployment mechanism that's being used: How does whatever's starting this application set the classpath? Whatever that mechanism is, you should be able to configure it to include wherever you're putting the logback.xml file, and then just don't include in in the src/main/resources to be embedded in the jar file.
Depending on the complexity of what you're going for, you may find the maven-assembly-plugin useful for creating your distribution of dependencies.
Using Scala SBT (1.2.1) on Windows:
Batch file:
#cd %~dp0
#set JAVA_OPTS=-Dlogback.configurationFile=logback.xml
#sbt clean run
worked for me (strange ...)

How to add external resource to classpath in a Java web app (Spring, preferably)

In my webapp, I use a jar that accesses a file called env.properties as follows :
ResourceBundle rb = ResourceBundle.getBundle("resources/env.properties");
We are externalizing all our property files (i.e. placing them outside our source code and outside of JBoss folder), but this jar (which we cannot modify) expects this property file on the classpath.
I've read that we can place this folder (resources) on the classpath using JBoss modules, but I don't want to place any property file inside the JBoss folder.
I'm keeping my property files at :
/app/property-files/some.properties
/app/property-files/resources/env.properties
My aim is to either get JBoss to add this location to its classpath, or programmatically add this location to the classpath through Java so that the jar can access this file.

Spring Boot Jar Execution internal properties files

I have a Spring Boot application that runs properly when I run it from Intellij as maven configurations.
I have a project structure of environments that is defined with properties files.
resources/conf/dev/environment.properties
resources/conf/qa/environment.properties
resources/conf/general.properties
etc.
Our framework works in a way that we are choosing the env with VM arguments.
for example -Denv=dev or -Denv=qa
After packaging the App to an executable JAR and trying to run it, Spring Boot can't identify the properties files under conf path of the project.
When I look inside the JAR the properties files are under {jar-name}.jar\BOOT-INF\classes\conf.
The error is:
java.io.FileNotFoundException: conf\general.properties (The system cannot find the path specified)
2017-07-11 10:52:52.864 INFO 17896 --- [main] n.lifecycle: Can't find configuration file [conf\general.properties]
2017-07-11 10:52:52.865 ERROR 17896 --- [main] n.lifecycle: configuration file [null] not found (use default properties as error handling)
I've tried to work with the documentaion here: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
but nothing seems to fix it.
Also tried to work with this guide - http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#executable-jar-launching but also failed...
The guides are referring to the properties files as "external" but my properties are packed in the JAR.
I've found out what's wrong.
Our in-house framework that's loading the resources are using File.separator to read the path of the resources.
Now for some reason when the jar is created with maven spring boot plugin the classpath is built with '/' for example /C:/Users/MyUser/Projects/MyApp/target/MyApp-1.0.1.jar!/BOOT-INF/classes!/ (the resources are in classes path inside of the jar of course)
And when we are trying to run the jar it's trying to read the resources with '\' so the path that is built is (if we choose "dev" for example) /C:/Users/MyUser/Projects/MyApp/target/MyApp-1.0.1.jar!/BOOT-INF/classes!/conf\dev and that is why the app is failing to load.
I still don't know why this is happening.
Try to put properties files in resources.
Not in resources / conf.
It works so well.

Spring Boot classpath

In the Spring Boot's docs here, about serving static content, it says:
By default Spring Boot will serve static content from a directory
called /static (or /public or /resources or /META-INF/resources) in
the classpath.
I found that all the content in the directory:
src/main/resources
will be copied inside the classpath, so I can put my static content in:
src/main/resources/static
and all will work fine and I'm happy since I can have my static content under the src directory.
But, I have some questions about this:
Why the documentation doesn't say to put static content in src/main/resources/static instead of speaking about the classpath (I think this is a bit confusing)?
Is it good to assume that the content in src/main/resources/ will be always copied in the classpath?
Is there some Spring Boot official documentation explaining what I'm supposed to find in the classpath other than Java classes and packages (up to now I only know I can found all the content from src/main/resources/)?
/src/main/resources is a Maven project structure convention. It's a path inside your project where you place resources. During the build step, Maven will take files in there and place them in the appropriate place for you to use them in your runtime classpath, eg in an executable .jar, some physical file system location used in the classpath (with java's -cp option), etc.
I could choose to build my application myself or with a different build tool. In such a case, /src/main/resources would not exist. However, the intention is for the classpath to be the same, ie. to contain the same resources and .class files.
The Spring boot documentation talks about the classpath because it shouldn't make assumptions about how your project is set up.
The classpath also contains additional libraries (JARs), which also can have a static folder, which would then be included for serving static resources. So if the documentation would only state the folder src/main/resources/static, it would be incomplete.
Ad 2: As long as you don't mess with the default Maven configuration, then it's safe to assume this.
Ad 3: Maybe start with the official Oracle documentation: https://docs.oracle.com/javase/8/docs/technotes/tools/windows/classpath.html. Hint: Of course, it's not only the contents of the resources folder, which are in the classpath, but also of course all compiled classes, hence its name.
To add to previous answers, it's the Spring Boot Maven Plugin (spring-boot-maven-plugin in the pom.xml) that that enables you to run the application using Maven. One of its functions is to ensure contents in the app including dependency libraries are available on the runtime classpath, such as within the the executable JAR file.

Categories

Resources