How does maven find the Java compiler?
I am new to learning maven following this example provided by sonata book. This is a simple pom.xml file (works great). But my question is, how does maven (mvn install) find the Java compiler (javac) installed on my machine? This POM file does not specify the JDK. Thanks for the explanation.
EDIT:
For comparison, I am following the next example in the book and this time I got a compilation error because I cannot find the javax.My java file as suggested in the book:src/main/java/org/sonatype/mavenbook/web/SimpleServlet.java
Now when I run mvn compilation I got the error below. Why now maven can't find the compiler:
ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project simple-webapp: Compilation failure: Compilation failure:
[ERROR] /home/abigail/study/simple-webapp/src/main/java/org/sonatype/mavenbook/web/SimpleServlet.java:[4,1] package javax.servlet does not exist
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven- v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.sonatype.mavenbook.simpleweb</groupId>
<artifactId>simple-webapp</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>simple-webapp Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>simple-webapp</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
source to share
If you take this path say maven version 3.2.3
apache-maven-3.2.3-bin\apache-maven-3.2.3\bin
opne mvn.bat you can see below
@REM Maven2 Initial batch script
@REM Required ENV barbarians:
@REM JAVA_HOME is the location of the JDK home directory
It is clear that it picks JAVA_HOME
from your environment variables. Below is a snippet of code from a file.
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto chkMHome
:chkMHome
if not "%M2_HOME%"=="" goto valMHome
for release, javax.servlet
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
or any available
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
source to share
Since maven itself is a java application, it will just use jdk by default, which starts the maven target.
For more compilation options, you will need to use:
http://maven.apache.org/plugins/maven-compiler-plugin/
Look at this also:
http://maven.apache.org/plugins/maven-compiler-plugin/examples/compile-using-different-jdk.html
EDIT:
To your follow-up question: If you look in the mvn executable (default: / usr / bin / mvn), you can see that this is a rather long bash script that spends a significant amount of time looking for where jdk is located. You can of course set the JAVA_HOME system property and "help" the script, but even if you don't have it, it will try to find it, and only when it fails will it throw an error.
From / usr / bin / mvn:
if [ -z "$JAVA_HOME" ]; then
javaExecutable="`which javac`"
if [ -n "$javaExecutable" -a ! "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
javaExecutable="`readlink -f \"$javaExecutable\"`"
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
and
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`which java`"
fi
fi
Actually, most of the script code is concerned with determining which java to use and where that Java is located. However, once you run the mvn executable, this does not restrict it from using the same compile / run jdk that it itself runs from . This is where the mvn compiler plugin comes in, where you can specify additional jdk installations to use.
source to share
So, I just got maven to choose a different default Java location:
Java8
[tomek:~] $ java -version
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)
but maven took Java9
[tomek:~] $ mvn -version
Apache Maven 3.3.9
Maven home: /usr/share/maven
Java version: 9-internal, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-9-openjdk-amd64
JAVA_HOME was not set:
[tomek:~] $ echo "Java HOME: $JAVA_HOME"
Java HOME:
So, I suspect it would be easy to bring the first ubuntu alternative (ignoring user choices):
[tomek:~] $ sudo update-alternatives --config java
There are 3 choices for the alternative java (providing /usr/bin/java).
Selection Path Priority
Status
------------------------------------------------------------
0 /usr/lib/jvm/java-9-openjdk-amd64/bin/java 1091 auto mode
* 1 /opt/java/jdk1.8.0_144/bin/java 1 manual mode
2 /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java 1081 manual mode
3 /usr/lib/jvm/java-9-openjdk-amd64/bin/java 1091 manual mode
source to share