I\'m new to the maven tool, I have made a project with Spring and Hibernate and they are configured in pom.xml as plugins, but JUnit is tagged under dependency. My questio
Both plugins and dependencies are Jar files.
But the difference between them is, most of the work in maven is done using plugins; whereas dependency is just a Jar file which will be added to the classpath while executing the tasks.
For example, you use a compiler-plugin to compile the java files. You can't use compiler-plugin as a dependency since that will only add the plugin to the classpath, and will not trigger any compilation. The Jar files to be added to the classpath while compiling the file, will be specified as a dependency.
Same goes with your scenario. You have to use spring-plugin to execute some spring executables [ I'm not sure what spring-plugins are used for. I'm just taking a guess here ]. But you need dependencies to execute those executables. And Junit is tagged under dependency since it is used by surefire-plugin for executing unit-tests.
So, we can say, plugin is a Jar file which executes the task, and dependency is a Jar which provides the class files to execute the task.
Hope that answers your question!
If you're coming from a front-end background like me, and are familiar with Grunt and npm, think of it like this:
First you would run, say, npm install grunt-contrib-copy --save-dev
. This is like maven's <dependency></dependency>
. It downloads the files needed to execute a build task.
Then you would configure the task in Gruntfile.js
copy: {
main: {
src: 'src/*',
dest: 'dest/',
},
}
This is like maven's <plugin>/<plugin>
. You are telling the build tool what to do with the code downloaded by npm/<dependency></dependency>
.
Of course this is not an exact analogy, but close enough to help wrap your head around it.
Plug-ins are used for adding functionalities to Maven
itself (like adding eclipse
support or SpringBoot
support to Maven
etc.). Dependencies are needed by your source code to pass any Maven phase (compile
or test
for example). In case of JUnit
since the test code is basically part of your code base and you call JUnit
specific commands inside test suites and those commands are not provided by Java SDK
therefore JUnit
must be present at the time Maven
is in the test phase and this is handled by mentioning JUnit
as a dependency in your pom.xml
file.
Maven itself can be described as food processor which has many different units that can be used to accomplish different tasks. Those units are called plugins. For example, to compile your project maven uses maven-compiler-plugin
, to run tests - maven-surefire-plugin
and so on.
Dependency in terms of maven is a packaged piece of classes that your project depends on. It can be jar, war etc. For example, if you want to be able to write JUnit test, you'll have to use JUnit annotations and classes thus you have to declare that your project depends on JUnit.
One line answer - basic understanding
Plugin is a tool you use at the execution of your maven build
Dependency means kind of any library which you will use in your code
Plugins and dependencies are very different things and these are complementary.
Plugins perform tasks for a Maven build. These are not packaged in the application.
These are the heart of Maven .
Any task executed by Maven is performed by plugins.
There are two categories of plugins : the build and the reporting plugins :
<build/>
element from the POM.<reporting/
> element from the POM. According to the maven goal specified in the command line (for example mvn clean
, mvn clean package
or mvn site
) , a specific lifecyle will be used and a specific set of plugins goals will be executed.
There are three built-in build lifecycles: default
, clean
and site
. The default
lifecycle handles your project deployment, the clean
lifecycle handles project cleaning, while the site
lifecycle handles the creation of your project's site documentation.
A plugin goal may be bound to a specific phase of a specific lifecyle.
For example the maven-compiler-plugin
binds by default the compile
goal to the lifecycle phase: compile
.
Most of maven plugins (both core plugins and third party plugins) favor convention over configuration. So these generally bound a plugin goal to a specific phase to make their usage simpler.
That is neater and less error prone :
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
</plugin>
than :
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
Dependencies are Maven artifacts/components required in the classpath during the Maven build.
These may be packaged in the application but not necessarily (see the scope
below).
The most of dependencies are jar but these may also be other kinds of archives : war, ear, test-jar, ejb-client ... or still POM or BOM.
In a pom.xml, dependencies may be specified at multiple places : the <build><dependencies>
part , the dependencies management
part or still in a plugin
declaration ! Indeed some plugins may need to have some dependencies in the classpath during their execution. That is not common but that may happen.
Here is an example from the documentation that shows that plugin
and dependency
may work together :
For instance, the Maven Antrun Plugin version 1.2 uses Ant version 1.6.5, if you want to use the latest Ant version when running this plugin, you need to add
<dependencies>
element like the following:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.2</version>
...
<dependencies>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant-launcher</artifactId>
<version>1.7.1</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
...
</project>
In Maven, dependencies are referenced in a specific format :
groupId:artifactId:packaging:classifier:version
.
The classifier (that is optional) and the packaging (JAR
by default) are not commonly specified. So the common format in the dependency
declaration is rather : groupId:artifactId:version
.
Here is an example of dependency declared in the <build><dependencies>
part :
<build>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.14.Final</version>
</dependency>
<dependencies>
</build>
Contrary to a plugin, a dependency has a scope.
The default scope is compile
. That is the most commonly needed scope (convention over configuration again).
The compile
scope means that the dependency is available in all classpaths of a project.
The scope defines in which classpaths the dependency should be added. For example do we need it at compile and runtime, or only for tests compilation and execution ?
For example we previously defined Hibernate as a compile
dependency as we need it everywhere : source compilation, test compilation, runtime and so for....
But we don't want that testing libraries may be packaged in the application or referenced in the source code. So we specify the test
scope for them :
<build>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.1.0</version>
<scope>test</scope>
</dependency>
<dependencies>
</build>