Spring: overriding one application.property from command line - java

I have an application.properties file with default variable values. I want to be able to change ONE of them upon running with mvn spring-boot:run. I found how to change the whole file, but I only want to change one or two of these properties.

You can pass in individual properties as command-line arguments. For example, if you wanted to set server.port, you could do the following when launching an executable jar:
java -jar your-app.jar --server.port=8081
Alternatively, if you're using mvn spring-boot:run with Spring boot 2.x:
mvn spring-boot:run -Dspring-boot.run.arguments="--server.port=8081"
Or, if you're using Spring Boot 1.x:
mvn spring-boot:run -Drun.arguments="--server.port=8081"
You can also configure the arguments for spring-boot:run in your application's pom.xml so they don't have to be specified on the command line every time:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<arguments>
<argument>--server.port=8085</argument>
</arguments>
</configuration>
</plugin>

To update a little things, the Spring boot 1.X Maven plugin relies on the --Drun.arguments Maven user property but the Spring Boot 2.X Maven plugin relies on the -Dspring-boot.run.arguments Maven user property.
So for Spring 2, you need to do :
mvn spring-boot:run -Dspring-boot.run.arguments="--server.port=8081"
And if you need to pass multiple arguments, you have to use , as separator and never use whitespace between arguments :
mvn spring-boot:run -Dspring-boot.run.arguments="--server.port=8081,--foo=bar"
About the the maven plugin configuration and the way of passing the argument from a fat jar, it didn't change.
So the very good Andy Wilkinson answer is still right.

Quick update:
if you are using the latest versions of spring-boot 2.X and maven 3.X, the below command line will override your server port:
java -jar -Dserver.port=9999 your_jar_file.jar

If not working with comma, to override some custom properties or spring boot properties in multiple mode, use whitespace instead of comma, like this code bellow:
mvn spring-boot:run -Dspring-boot.run.arguments="--server.port=8899 --your.custom.property=custom"

You can set an environment variable to orverride the properties. For example, you have an property name test.props=1 . If you have an environment variable TEST_PROPS spring boot will automatically override it.
export TEST_PROPS=2
mvn spring-boot:run
You can also create a json string with all the properties you need to override and pass it with -Dspring.application.json or export the json with SPRING_APPLICATION_JSON.
mvn spring-boot:run -Dspring.application.json='{"test.props":"2"}'
Or just pass the properties with -Dtest.props=2
mvn spring-boot:run -Dtest.props=2
Tested on spring boot 2.1.17 and maven 3.6.3

Running by Gradle:
Run in default port(8080): ./gradlew bootRun
Run in provided port(8888): ./gradlew bootRun --args='--server.port=8888'
If we have any variable in the application.properties file named PORT, run this: PORT=8888 ./gradlew bootRun
Running by Maven:
Run in default port(8080): mvnw spring-boot:run
Run in provided port(8888): mvnw spring-boot:run -Dspring-boot.run.jvmArguments='-Dserver.port=8085'
Run in provided port(8888): mvn spring-boot:run -Dspring-boot.run.arguments='--server.port=8085'
Run in provided port(8888) with other custom property: mvn spring-boot:run -Dspring-boot.run.arguments="--server.port=8899 --your.custom.property=custom"
If we have any variable in the application.properties file named PORT, run this: SERVER_PORT=9093 mvn spring-boot:run
Using java -jar:
Create the .jar file:
For Gradle: ./gradlew clean build. We will find the jar file inside: build/libs/ folder.
For Maven: mvn clean install. We will find the jar file inside:target folder.
Run in default port(8080): java -jar myApplication. jar
Run in provided port(8888): java -jar myApplication.jar --port=8888
Run in provided port(8888): java -jar -Dserver.port=8888 myApplication.jar
Run in provided port(8888) having variable SERVER_PORT in application.properties file: SERVER_PORT=8888 java -jar target/myApplication.jar

In Spring Boot we have provision to override properties as below
mvn spring-boot:run -Dspring-boot.run.arguments=--server.port=8082

If you have the jar file after doing mvn clean install, you can override any property that you have in your application.yml using the double -, like this:
java -jar name_of_your_jar_file.jar --parameter=value
For example, if you need to change your server port when starting you server, you can write the following:
java -jar name_of_your_jar_file.jar --server.port=8888

I Was making a mistake with the syntax of commandline command , while passing command-line arguments, I was wrapping multiple arguments between " " and this was the issue. I simply ran the same command having multiple arguments separated by a space without wraaping them between "" and it worked just fine.
Please note this answer is for cases where we are trying to run this scenario from a jar file(not using mvn).
Correct Command: java -jar myJar.jar --com.arg1=10 --com.arg2=1
Incorrect Command: java -jar myJar.jar "--com.arg1=10 --com.arg2=1"

Related

Cannot run spring boot application using java -cp command

How to reproduce:
Download the default maven/java spring project from https://start.spring.io/ with spring-web, build it and then I'd like to start it using the following command:
java -cp target/demo-0.0.1-SNAPSHOT.jar com.example.demo.DemoApplication
The error I'm getting is:
Error: Could not find or load main class com.example.demo.DemoApplication
I know it works with java -jar, but I explicitly want to put more things on the classpath. Why doesn't it work?
The solution was to use a shadow jar plugin instead of the spring-boot one, because spring-boot plugin creates a jar that puts classes in a subfolder, which makes them inaccessible for the java -cp command.
Assuming (but it is obvious) that you will be putting jar files in class path.
install the jar file which you want to put in class path using mvn install like this below
mvn install:install-file -Dfile=<complete path here for jar.jar> -DgroupId=com.example.groupId -DartifactId=example-artifact -Dversion=1.0 -Dpackaging=jar
Make sure if you have multiple jars to be included in your spring project, you should put different unique groupId, and artifactId, so tha mevn doesn't get confused.
Then add those jars in pom.xml as dependency:
<dependency>
<groupId>groupID from above install command</groupId>
<artifactId>artifact Id from above install command</artifactId>
<version>version from above install command</version>
</dependency>
And then build and run your spring project as you ideally do with
java -jar SpringProject.jar

Not able to do maven release with jasypt encryption

I've a Springboot project handled by maven that contains some secrets encrypted with Jasypt. When I'm running the mvn deploy I'm passing the jasypt password as:
mvn -B clean deploy -Djasypt.encryptor.password=${jasypt_password}
And it is able to run test cases and deploy the jar file to repository. But when I'm doing the same with mvn release the jasypt password is not properly set.
mvn -B clean release:prepare release:perform -Djasypt.encryptor.password=${jasypt_password}
Or
mvn -B release:prepare -Djasypt.encryptor.password=${jasypt_password}
For both these cases, I'm getting following error while running the test cases.
Caused by: java.lang.IllegalStateException: Required Encryption configuration property missing: jasypt.encryptor.password
The plugin configuration I'm using is:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<localCheckout>true</localCheckout>
</configuration>
</plugin>
How should I set jasypt password while running the maven release?
I got the issue solved using following command. Apparently maven release plugin takes configuration parameters in a different way.
mvn -B clean release:prepare release:perform -Darguments="-Djasypt.encryptor.password=${jasypt_password}"
You can check this link which gives more details about the issue.
Basically it states that
Once you enable jasypt-spring-boot the password property is required
as specified in the documentation
They have suggested multiple solutions. One of them being:
Add jasypt.encryptor.password=dummy to your springboot properties file.
And another (if running from command line), run your jar with
-Djasypt.encryptor.password=*******************
If you are using Intellij,
Using
-Djasypt.encryptor.password=${jasypt_password} as Project argument should resolve your issue.
If it doesnot help then try
--jasypt.encryptor.password=${jasypt_password}.
Let me know if this helps.
Thanks,
Manu

What is the purpose of mvnw and mvnw.cmd files?

When I created a Spring Boot application I could see mvnw and mvnw.cmd files in the root of the project. What is the purpose of these two files?
These files are from Maven wrapper. It works similarly to the Gradle wrapper.
This allows you to run the Maven project without having Maven installed and present on the path. It downloads the correct Maven version if it's not found (as far as I know by default in your user home directory).
The mvnw file is for Linux (bash) and the mvnw.cmd is for the Windows environment.
To create or update all necessary Maven Wrapper files execute the following command:
mvn -N io.takari:maven:wrapper
To use a different version of maven you can specify the version as follows:
mvn -N io.takari:maven:wrapper -Dmaven=3.3.3
Both commands require maven on PATH (add the path to maven bin to Path on System Variables) if you already have mvnw in your project you can use ./mvnw instead of mvn in the commands.
Command mvnw uses Maven that is by default downloaded to ~/.m2/wrapper on the first use.
URL with Maven is specified in each project at .mvn/wrapper/maven-wrapper.properties:
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.9/apache-maven-3.3.9-bin.zip
To update or change Maven version invoke the following (remember about --non-recursive for multi-module projects):
./mvnw io.takari:maven:wrapper -Dmaven=3.3.9
or just modify .mvn/wrapper/maven-wrapper.properties manually.
To generate wrapper from scratch using Maven (you need to have it already in PATH run:
mvn io.takari:maven:wrapper -Dmaven=3.3.9
The Maven Wrapper is an excellent choice for projects that need a specific version of Maven (or for users that don't want to install Maven at all). Instead of installing many versions of it in the operating system, we can just use the project-specific wrapper script.
mvnw: it's an executable Unix shell script used in place of a fully installed Maven
mvnw.cmd: it's for Windows environment
Use Cases
The wrapper should work with different operating systems such as:
Linux
OSX
Windows
Solaris
After that, we can run our goals like this for the Unix system:
./mvnw clean install
And the following command for Batch:
./mvnw.cmd clean install
If we don't have the specified Maven in the wrapper properties, it'll be downloaded and installed in the folder $USER_HOME/.m2/wrapper/dists of the system.
Maven Wrapper plugin
Maven Wrapper plugin to make auto installation in a simple Spring Boot project.
First, we need to go in the main folder of the project and run this command:
mvn -N io.takari:maven:wrapper
We can also specify the version of Maven:
mvn -N io.takari:maven:wrapper -Dmaven=3.5.2
The option -N means –non-recursive so that the wrapper will only be applied to the main project of the current directory, not in any submodules.
Source 1 (further reading): https://www.baeldung.com/maven-wrapper
short answer: to run Maven and Gradle in the terminal without following manual installation processes.
Gradle example:
./gradlew clean build
./gradlew bootRun
Maven example:
./mvnw clean install
./mvnw spring-boot:run
"The recommended way to execute any Gradle build is with the help of the Gradle Wrapper (in short just “Wrapper”). The Wrapper is a script that invokes a declared version of Gradle, downloading it beforehand if necessary. As a result, developers can get up and running with a Gradle project quickly without having to follow manual installation processes saving your company time and money."
Gradle would also add some specific files corresponding to the Maven files Gradlew and Gradle.bat
In the windows OS, mvnw clean install is used for the maven clean and install activity, and mvnw spring-boot:run is used to run the Spring boot application from Command Prompt.
For Eaxmple:
C:\SamplesSpringBoot\demo>mvnw clean install
C:\SamplesSpringBoot\demo>mvnw spring-boot:run
By far the best option nowadays would be using a maven container as a builder tool. A mvn.sh script like this would be enough:
#!/bin/bash
docker run --rm -ti \
-v $(pwd):/opt/app \
-w /opt/app \
-e TERM=xterm \
-v $HOME/.m2:/root/.m2 \
maven mvn "$#"

What options are available to mimic "sbt run" in Maven?

In a project where I use the scala language, with sbt can launch directly from the terminal the command:
sbt run
Now I switched to use java with maven. If I try to run in the terminal:
mvn run
the command does not work. The error is:
[ERROR] Unknown lifecycle phase "run" ...
There is an alternative way to do it?
Thanks a lot.
Use the maven exec plugin.
mvn exec:java -Dexec.mainClass="com.example.Main" [-Dexec.args="argument1"] ...
You can configure the plugin in your pom.xml to set what the default main class and default arguments should be.

How can I run a Java class inside a Maven artifact, automatically resolving dependencies?

If I know the coordinates of an artifact, and a name of the class inside that artifact, can I make Maven run the class, including all of its dependencies on the Java classpath?
For example, suppose a coworker told me about a tool I can run, which is published to our internal Nexus with the artifact coordinates example:cool-tools:1.0.0. I used this answer to download the artifact. Now, I know that the main class name is example.Main. But if I just go to the artifact's download location and run java -cp cool-tools-1.0.0.jar example.Main, I get NoClassDefFoundErrors for any dependencies of cool-tools.
I'm aware of the maven-exec-plugin, but as far as I can tell that's only for projects where you have the source. Suppose I don't have access to the source, only the Nexus containing the tool (and all its dependencies). Ideally, I'd do something like mvn exec:exec -DmainArtifact='example:cool-tools:1.0.0' -DmainClass='example.Main', but I don't think the exec plugin is actually capable of this.
ETA: To be clear, I do not have a local project / POM. I want to do this using only the command line, without writing a POM, if possible.
There is no out-of-the-box solution for your task. But you can create a simple script to solve it:
Download pom.xml of your tool from the repo.
Download jar of your tool.
Download all its dependencies.
Run java against resolved libraries.
Command line:
> mvn dependency:copy -Dartifact=<tool.group.id>:<tool.artifact.id>:<tool.version>:pom -DoutputDirectory=target
> mvn dependency:copy -Dartifact=<tool.group.id>:<tool.artifact.id>:<tool.version> -DoutputDirectory=target
> mvn dependency:copy-dependencies -f target/<tool.artifact.id>-<tool.version>.pom -DoutputDirectory=target
> java -cp target/* <tool.main.class>
Directory ./target will contain your tool + all dependencies.
See details on dependency:copy and dependency:copy-dependencies mojos.
Edit
As alternative, you can build classpath using libraries in the local repo by:
> mvn dependency:build-classpath -DincludeScope=runtime -f target/<tool.artifact.id>-<tool.version>.pom [-Dmdep.outputFile=/full/path/to/file]
See details on build-classpath mojo.
You could download the pom from the repository using wget, for instance. Then resolve the dependencies, and build the classpath exporting it to a file using Maven. Finally, execute with Java and the built classpath using something like bash backticks to use the content of the file.
Just like in this answer.
For me the first anwer almost worked, but I needed to slightly adjust the script. In the end I came (on windows machine) to following solution:
> mvn dependency:copy -Dartifact=<tool.group.id>:<tool.artifact.id>:<tool.version>:pom -DoutputDirectory=target
> mvn dependency:copy -Dartifact=<tool.group.id>:<tool.artifact.id>:<tool.version> -DoutputDirectory=target
> mvn dependency:copy-dependencies -f target/<tool.artifact.id>-<tool.version>.pom -DoutputDirectory=target
> cd target
> java -cp target/*;<tool.artifact.id>-<tool.version>.jar <tool.main.class>
On Unix/Linux machine in the last command the semicolon ";" must be replaced with colon ":".
When input arguments must be provided, just put them in the last script line:
> java -cp target/*;<tool.artifact.id>-<tool.version>.jar <tool.main.class> arg1 arg2 ...
u can use IDEs like Intellij idea which automatically resolve dependencies as u write them in your pom
As it has been mentioned by others already there is no solution without creating an extra POM.
One solution could be to use the Maven Shade Plugin in this POM: "This plugin provides the capability to package the artifact in an uber-jar, including its dependencies"
I think the Executable JAR is close to that what you'd like to achieve.

Categories

Resources