Run java -jar and also specify the configuration path - java

A standalone(spring boot)jar can be run like this:
java -jar springboot.jar
How can I configure the configuration path as well in the command above ?
Like this below: ?
java -jar springboot.jar --configuration:/some-path-here
n.b. My configuration is external.
Thanks!

By default, Spring Boot will look in the working directory for external application.properties and application.yml files. For example, if you start your Spring Boot app in the same directory as the JAR:
java -jar myapp.jar
Then this will look for application.properties (or application.yml or application-{profile}.properties etc.) in the same directory as your JAR file. This means if you set up your directory like so:
myapp/
| - myapp.jar
| - application.properties
And start the app within that directory, then it will automatically pick up the application.properties there.
If this isn't an option for you, the spring.config.location property can be specified on the command to give it additional locations to use when looking for configuration files, e.g.:
java -jar myapp.jar --spring.config.location=file:/etc/myapp/
For more info, read up on Spring Boot's Externalized Configuration documentation.

As per Spring docs:
java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
Use file instead of classpath to specify external configuration file.

Related

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

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.

SpringBoot can't read application.properties when running outside jar folder

I have created a SpringBoot Application, and I placed the application.properties in the same folder of the jar file. This is the content of the file:
server.port=8081
When I run /bin/java -jar /opt/apl/org.web.exemplo-java-maven.1.0.0-90/org.web.exemplo-java-maven-1.0.0-90.jar outside the jar folder it doesn't read the application.properties and runs the program in port 8080.
When I run /bin/java -jar /opt/apl/org.web.exemplo-java-maven.1.0.0-90/org.web.exemplo-java-maven-1.0.0-90.jar inside the jar folder (or inside any folder with the application.properties) it reads the file and runs in port 8081.
What is happening? I thought the properties file needed to be in the same place of the jar file. But it happens that it needs to be in the same folder where I'm running the command.
By convention at application startup Spring Boot looks for the application.properties file at classpath root, e.g. top-level of directory structure in your JAR file. You can customize this behaviour and configure a different application.properties location using a Spring specific environment property when starting the application from cmdline:
/bin/java -jar /opt/apl/org.web.exemplo-java-maven.1.0.0-90/org.web.exemplo-
java-maven-1.0.0-90.jar --spring.config.location=classpath:/other-
application.properties
Check this: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-application-property-files

Fetch application properties from an embedded jar - Spring Boot

I have a dependent jar file which I have added as a dependency. Is there a way to fetch use the application.properties file present in the dependent jar?
Let the property spring.config.location point to that application.properties
like
spring.config.location=classpath:com/company/whatever/application.properties
You can set spring.config.location on the command line when starting the application
$ java -jar myproject.jar --spring.config.location=classpath:com/company/whatever/application.properties
You find this explained in the spring boot docs

Spring Boot Executable Jar with Classpath

I am building a software system to interact with an enterprise software system, using Spring Boot. My system depends on some jars and *.ini files from that enterprise system, so I cannot pack all dependencies in Maven. I would like to be able to run Spring Boot as Executable Jar with embedded Tomcat. I would also like to be able to set the classpath via the command line. So something like:
java -classpath /home/sleeper/thirdparty/lib -jar MyApp.jar
However, -classpath and -jar cannot co-exist. I have tried "-Dloader.path". It was able to load all the jar files under the folder, but not other things, like *.ini files in the folder.
So is there a way we can make -classpath to work with an Spring executable jar with embedded Tomcat?
If you just want add external libraries you can use the loader.path property.
java -Dloader.path="your-lib/" -jar your-app.jar
UPDATE
If you also need to read additional files from the classpath you have to create/change the manifest file of your application.
Lets assume that your are initializing your Spring Boot context from the class de.app.Application. Your MANIFEST.MF should looks as follows:
Manifest-Version: 1.0
Main-Class: de.app.Application
Class-Path: your-lib/
And the you can simply start your app with java -Dloader.path="your-lib/" -jar MyApp.jar.
For more information about the MANIFEST.MF please see Working with Manifest Files: The Basics.
On Linux:
java -cp MyApp.jar:/home/sleeper/thirdparty/lib -Dloader.main=myMainApplicationClass org.springframework.boot.loader.PropertiesLauncher
On Windows:
java -cp MyApp.jar;/home/sleeper/thirdparty/lib -Dloader.main=myMainApplicationClass org.springframework.boot.loader.PropertiesLauncher
This will avoid messing with the manifest or the Spring Boot Maven plugin configuration as in the other answers. It will launch your app with the PropertiesLauncher, which allows you to specify the main class in loader.main.
As mentioned earlier, for some reason if you use PropertiesLauncher with loader.path, it will not add resource files to the classpath. This works around the issue by using -cp instead of -jar.
EDIT
As mentioned by Pianosaurus in the comment, use ":" instead of ";" as separator in the classpath on Linux
You mentioned that you needed to load *.ini files from an external folder. I had to do something similar, load CSV files from an external folder.
My file structure looked like this
./myapp.jar
./config/file.csv
I was using the ResouceLoader to load the files as:
Resource res = resourceLoader.getResource("classpath:file.csv");
File csvFile = res.getFile();
Start script:
java -Dloader.path="config" -jar your-app.jar
The resource was not loading from the "config" folder as expected. After some research I found out that I had to change my Maven plugin configuration to use ZIP layout.
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layout>ZIP</layout>
</configuration>
</plugin>
This will direct Spring Boot to use PropertiesLauncher, which allows loading external resources from "loader.path".
See this excellent article for more detail.
java -cp C:\jar-path\your-jar-1.2.0.jar -Dloader.main=package-and-main class -Dloader.path=external dependency jar path org.springframework.boot.loader.PropertiesLauncher -Dspring.profiles.active=profile etc -default,test --spring.config.location=external properties file name
If want to define external memory use
java -ms8g -mx8g -cp
java -cp
Differences between "java -cp" and "java -jar"?
-Dloader.main
Spring Boot’s org.springframework.boot.loader.PropertiesLauncher comes with a JVM argument to let you override the logical main-class called loader.main:
-Dloader.path
Tell the PropertiesLauncher that it should pick up any libraries found in the “lib”
org.springframework.boot.loader.PropertiesLauncher
Spring Boot’s org.springframework.boot.loader.PropertiesLauncher comes with a JVM argument to let you override the logical main-class called loader.main:
java -cp bootApp.jar -Dloader.main=org.khan.DemoApplication org.springframework.boot.loader.PropertiesLauncher
-Dspring.profiles.active
If you are using Spring profile then you need to set profile first
set SPRING_PROFILES_ACTIVE=default,test
or window run type envi and add
spring_profiles_active
default,test
--spring.config.location
Directory is specified then that is where the application.properties is searched for
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
Just to add a simple solution without PropertiesLauncher or too much arguments.
1 - Build your standard executable springboot jar (my-spring-boot-app.jar)
2 - then run it without using the -jar option and using the JarLauncher class as the main class
java -cp "/path/to/jars/*:/path/to/app/my-spring-boot-app.jar" org.springframework.boot.loader.JarLauncher
(relative pathes are also perfectly valid)
that's all
The standard way to add dependencies in Spring Boot project is placing those Jar files into BOOT-INF/lib. This will result in copy that dependencies in the jar or war file generated and with the classpath.idx updated as well.
You can see the official documentation here
The accuracy literature says:
Application classes should be placed in a nested BOOT-INF/classes directory. Dependencies should be placed in a nested BOOT-INF/lib directory
I already do that with external Jar files and everything gone Ok.
One solution that worked for me was to insert the jar with the external classes into the MANIFEST.MF's Class-Path. That's because the -jar switch ignores the -classpath option and the CLASSPATH environment variable.
Procedure:
install the maven-jar-plugin into the POM;
add the lines:
<configuration>
<archive>
<manifestEntries>
<Class-Path>/my/external/jar/absolute/path.jar</Class-Path>
</manifestEntries>
</archive>
</configuration>
Build and run with java -jar myapp.jar. Its manifest will contain the line:
Class-Path: /my/external/jar/absolute/path.jar
This way the external jar will be searched at runtime and not at compile-time (it won't be copied in BOOT_INF/lib).
Sources:
post 1
post 2

Use application configuration over Hadoop configuration

I have built a Java application using Maven. It is packaged as an executable jar using the Maven Shade plugin. This application does several things - one of those is to upload data to a Hadoop cluster. I execute the program using the following:
$ hadoop jar <app_name>.jar <app_arg1> <app_arg2> ...
My application uses SLF4J with the Log4J bindings for logging - and so does Hadoop.
When using the hadoop jar command, Hadoop's own Log4J configuration file overrides my application's Log4J configuration file.
How can I prevent my application's Log4J configuration file from being overriden?
NOTES:
Relevant dependencies: hadoop-core:1.2.1, slf4j-api:1.7.12, and slf4j-log4j12:1.7.12.
I'm using the hadoop jar command, instead of java -jar. My application code that interacts with the Hadoop cluster only works when using the hadoop jar command. I've outlined this issue in a previous SO question.
EDIT 1: (10/02/2015)
I've done a few things.
First, I changed the name of my Log4J configuration file to avoid the name collision with the the default log4j.properties file that Hadoop uses:
log4j-<app_name>.properties
Second, I set the the HADOOP_OPTS environment variable to tell Log4J what the name of my configuration file would be:
HADOOP_OPTS=-Dlog4j.configurationi=log4j-<app_name>.properties
Third, I set the HADOOP_CLASSPATH environment variable to ensure my configuration file that is packaged within the uber jar is picked up by the hadoop jar command:
HADOOP_CLASSPATH=/absolute/path/to/<app_name>.jar
With these changes, my application now uses it's own Log4J configuration file as intended. Feels like a hack (as I would have preferred to use the java -jar command), but it resolved my issue.
By default Hadoop framework jars appear before the users’ jars in the classpath. You can set the preference for your (user) jars using -Dmapreduce.job.user.classpath.first=true parameter in the command. The new command will look below.
hadoop jar <app_name>.jar -Dmapreduce.job.user.classpath.first=true <<app_arg1>> <<app_arg2>> ...
Or You can put the below configuration in your mapred-site.xml for always giving preference to user classpath.
<property>
<name>mapreduce.job.user.classpath.first</name>
<value>true</value>
</property>
You can set this programmatically in the job configuration.
job.getConfiguration().set("mapreduce.job.user.classpath.first", "true");
You can set this via any way, it will never be late.

Categories

Resources