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

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 "$#"

Related

Installing maven depencies from pom.xml in docker

I am trying to run a spring-boot maven project inside a docker environment. So the setup is as follows:
Docker is set up and installs Java, etc. (done only once)
App is run (can be any number of times)
What I am experiencing
Every time I run the spring-boot project by mvn spring-boot:run, it installs all the required libraries (every time I run the project) from the pom.xml (Java, Maven, etc. are preinstalled from the docker) and then runs the project.
What I am trying to do
This process of reinstalling every time is redundant and time-consuming, so I want to delegate this installation thing to the docker as well. Ideally, using the pom.xml to do the installations, though alternative ways are also welcome.
What I have tried so far
Install npm using a good tutorial, but it fails in Docker as we can't restart the terminal during docker build, while source ~/.bash_profile doesn't seem to work either.
Tried to build that project directly in docker (by RUN mvn clean install --fail-never) and copying both npm and node folders to the directory where I run the app. But it doesn't seem to work either as it's installing them every time without any change.
Can anyone please help me there? This problem has stuck the project. Thanks a lot!
From your question I understand that, in the Dockerfile you just install java, maven, etc. but does not build your project using mvn clean package install before executing mvn spring-boot:run (and that is redundant as well because mvn spring-boot:run does the build for you before staring the application).
You cannot skip installing maven dependency while running on containers as they are spun as they run. So it will be installed either while you call mvn clean install or mvn spring-boot:run.
What the max you can do is, using your devops pipeline, build the jar previously and in the Dockerfile just copy the build jar and execute.
Example Dockerfile in this case:
FROM openjdk:8-jdk-alpine
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
Here the previously build artifact is already available at target/

Want to build project with commandline mvn but have to use Maven update in eclipse first

I'm working with multiple projects in Eclipse. because I want to automate the building I want to script the building process.
Unfortunately I cannot do the same actions on the commandline as in Eclipse.
So a common problem is that when a new function from a referenced project is used, I cannot build the project on the commandline with mvn. I use the command:
mvn clean install -U
But this command will give a build failure until I do a Eclipse Maven Update from the eclipse GUI. After that I can build the project again.
I also tried all the other commands I came across Stackoverflow:
mvn eclipse:eclipse
mvn dependency:resolve
So I just want to that Maven Update command in eclipse from the commandline so I can build from the commandline. If anyone could tell me what I'm doing wrong that would be awesome.
Thx in advance
Update for more clarification:
The project structure is:
Rest-service, Framework-service, Framework-model
Framework-model is referenced in the pom file by Framework-service and Framework-service is referenced by Rest-service. The other projects are not relevant to the problem.
When a function is added to Framework-model and used in Rest-service it gives an compilation error in eclipse and when I build with mvn clean install -U, although Maven install in eclipse is succesful but I think it is still using the old compiled code. After a Maven Update command in eclipse the compilation error is gone. And mvn clean install -U from the commandline also works.
How could I do a Maven Update command in the commandline? If mvn clean install -U should also do a Maven Update command, what settings should I check?
Another update: So this weekend I tried different things and running mvn compile before the mvn clean install -U command gives a different output. And finds the new function. But as I read maven, I thought install should also do the previous steps. How is this possible?
Eclipse's Maven plugin uses the maven version configured in Preferences/Maven/User settings. If you have a different version of maven in your Eclipse's settings than the one on your PATH variable, you could have different outputs. Maybe try and check that.

Unable to configure Maven in Jenkins

Maven version 3.3.3 (Maven is configured in my system. I'm able to get version number by mvn -version.)
Following is my Maven project in Jenkins:
Which basically asks me to configure Maven.
Below are the only fields available when I select Configure System. Though I gave the path of Maven, the error is not removed and unable to build.
Can someone help on this.
Please check "Jenkins => Configuration => Global Tool Configuration". There you can define your maven-installation not only the the environment-variable MAVEN_HOME.
Afterwards you should be able to select your maven-installation in your project-build.
ln -s /opt/apache-maven-3.5.4/bin/mvn /usr/bin/mvn
run echo $PATH in pipeline script and see paths available to Jenkins user. Once linking with maven bin path, maven started working. To check, run mvn -v in the pipeline.
First you should configure a JDK and NOT an JRE. Furthermore the rootPOM location is relative to the Jenkins Job Workspace which means usually only pom.xml nothing more...

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.

Can I build multiple projects with Maven and then run Jetty through m2eclipse?

I have a multi-module project which has a war and multiple jar dependencies. I'd like to be able to build multiple projects (the dependencies) and then launch the war in jetty with a single command. Is this possible? I'd normally make a script to do this, e.g.
mvn clean install
cd project-web/
mvn jetty:run
cd ..
However, this loses the Debug functionality from Eclipse. Is there a way to do this in m2eclipse?
You are gonna want to run configure the MAVEN_OPTS to allow an external debugger and connect to it from eclipse as a Remote Java Application:
http://docs.codehaus.org/display/JETTY/Debugging+with+the+Maven+Jetty+Plugin+inside+Eclipse

Categories

Resources