Michel Feinstein
Michel Feinstein

Reputation: 14266

Understanding Maven dependencies and assembly

I am not very much experienced with Maven and it's compilation and packaging logic gets me confused.

I have some dependencies declares as :

<dependency>
  <groupId>com.dependency_group</groupId>
  <artifactId>dependency_1</artifactId>
  <version>1.0.0</version>
</dependency>


<dependency>
  <groupId>com.dependency_group</groupId>
  <artifactId>dependency_2</artifactId>
  <version>1.0.0</version>
  <scope>provided</scope>
</dependency>

So as far as I understand, dependency_1 will be added to the classpath of my program as something that comes along with my jar, and dependency_2 on the other hand, will be added to the classpath as something that the system runtime will provide upon deployment.

Then I run the package goal of Maven and none of my dependencies are packed with my code (I am using the shade plugin, but even without it nothing changes).

I expected that when some dependency is set as compile scope, it will be exported with my compiled code, since AFAICS, there's no point in setting the classpath saying a dependency will come along with my code, and Maven just don't package that dependency with it. It looks to me as if Maven is not obeying it's contract.

So:

1 - What's the logic behind this?

2 - Do I have to always use the Assembly plugin?

3 - Are there cases where people will define a dependency as compile and will not want it packaged within a jar?

Upvotes: 1

Views: 75

Answers (2)

J Fabian Meier
J Fabian Meier

Reputation: 35785

Let me shed some light on the main point here. There are fundamentally two kinds of java artifacts:

  1. Applications, i.e. ears, wars, executable jars
  2. Libraries, i.e. jars that are meant to be used as dependencies for other artifacts.

For Applications your reasoning makes perfectly sense. Wars and Ears automatically package all their compile dependencies and you need no assembly plugin for that. For libraries, you do not pack the dependencies into the library. Maven handles transitive dependency resolution and would be confused if you put a fat jar on the classpath.

The thing is that packaging jar can be both a libary or an application. If you want a standalone application, you need to tell Maven to package everything, e.g. by using the assembly plugin or shade plugin.

Upvotes: 2

Antoniossss
Antoniossss

Reputation: 32507

You use compile scope when you want some dependencies to come along with your code. For example you want Jackson to be a part of your application if you are using it for json serialization.

You use provided scope, if you want dependency to be on the classpath during the compilation but wont be included within your application. It must be provided by running environment. For example you want Lombok as it is compile only library, or you want to have Servlet Api dependency as provided when you are writing servlet application because such app will be ran on servlet container thus there is no need to pack it within your application (it will be available in container runtime)

Do I have to always use the Assembly plugin

Nobody forces you to do so.

Upvotes: 0

Related Questions