Stephen
Stephen

Reputation: 8820

how does a Java program find its Maven packages?

I have a Java program in IntelliJ which has a pom.xml and uses Maven. The packages were downloaded and currently they are found by IntelliJ.

I'm a little confused though because the Maven repository is not part of the CLASSPATH as far as I can tell. So does IntelliJ just do a bit of magic where it looks into its Maven repository to find the packages? (I think that IntelliJ has its own Maven repo. I separately have Maven 3 installed, but I think it isn't using it.)

But more generally: If you build a JAR using Maven then I guess it will put the dependencies in the JAR where the Java program can find them, so there won't be a problem. But if you just run a Java program directly, do you need to add the Maven repository to your classpath or does something else happen?

Thanks for any information you can provide to lessen my confusion :)

Upvotes: 4

Views: 1162

Answers (2)

Jasper Huzen
Jasper Huzen

Reputation: 1573

All the required dependencies, defined in the pom.xml file(s), are downloaded from Maven Central (or others if configured) to the local Maven repository. That repository is located at <user home>/.m2/repository.

Maven generates/calculates a dependency tree to know all the required dependencies for the project. (you can also dump that tree with the command mvn dependency:tree. I always pipe the result to a file, because the tree can be large mvn dependency:tree > deptree.txt). Maven put them all on the classpath when executing a maven command like mvn compile

IntelliJ also use/calculate the dependency tree and add all the jar files to the projects classpath (point to the files in the <user home>/.m2/repository folder). You can see them all in the list with External Libraries, and they will be used / on the classpath for compilation and running the application.

When building a JAR file the dependencies are NOT added to the JAR. Only the bytecode (java classes) and resources from your own project are packaged into the JAR file. (Source files can also be packaged if you configure that) By adding a Maven plugin (maven-shade-plugin) you can configure your project to also pack dependencies into the JAR. SpringBoot projects also will do that.

Upvotes: 2

Karol Dowbecki
Karol Dowbecki

Reputation: 44960

When you start the program from IntelliJ using a runtime configuration for your main() method IntelliJ constructs the classpath from all the project dependencies. You can see this in the Run window, the first log line is the java command used to start the main(). It's a long line but it usually looks similar to:

java -javaagent:/opt/idea/idea-IC-173.3727.127/lib/idea_rt.jar=40165:/opt/infra/idea/idea-IC-173.3727.127/bin -Dfile.encoding=UTF-8 -classpath /home/ [...]

IntelliJ constructs the -classpath argument adding both the module target directory and the Maven dependencies referenced from the local Maven repository.

When you package the project using Maven mvn clean package usually it becomes a standalone JAR with just your code (unless you changed the defaults). Now you have a few choices how to provide dependencies needed to start your main():

  1. Provide them using -classpath parameter just like IntelliJ.
  2. Add maven-shade-plugin and use shade goal to the build a runnable Uber JAR. This creates a fat JAR which doesn't require -classpath.
  3. Use some other Maven plugin to perform point 2 e.g. Spring Boot spring-boot:repackage goal.

Upvotes: 4

Related Questions