Maven WAR plugin and how to manage dependencies
Okay, this may well be a familiar question, however I still remain confused and I'm struggling to find an answer that really clarifies the details.
The scenario I have several Maven projects, the majority create JAR artefacts and one is responsible for creating the WAR artefact. The WAR artefact has dependencies on the JAR artefacts with a scope of compile, in order that these JARs are included within the WEB-INF/lib folder.
The confusion I'm still unclear how this plugin responds to scopes as to which dependencies and transitive dependencies get included within the WARs lib folder. My understand is tha开发者_Go百科t compile will result in a JAR being included along with its dependencies that are also declared with a compile scope (and so on recursively), but the buck stops with provided. A dependency with the provided scope will not get included.
The issue
To take a specific example, the WAR project war-a
has a dependency on an internal JAR project jar-a
with a scope of compile. jar-a
will be included with the WARs lib folder because of the scope. Now jar-a
has a dependency on the 3rd party library log4j with a scope of compile. The log4j JAR also gets included in the lib folder because of its scope. But... so does log4j's dependencies, such as mail, etc. I want log4j but I dont want its dependencies. If I configure log4j with provided, its dependencies wont be included, but neither will itself.
I've considered the options, such as using exclusions, but when there are 40+ internal JAR projects, that's a lot of exclusions in POM files. Also, to use exclusions requires me to know specific knowledge of a 3rd parties dependencies, which feels unnecessary.
Can anyone clarify, expand, answer any of the above? Any input will be most appreciated.
Update Further to the above, I'm stuck with a decision. Should I allow the list of required 3rd party JARs to be bundled within the WAR, be resolved via the compile scope dependencies of the various internal Maven JAR projects we have. Or should I declare all 3rd party dependencies as provided within the internal Maven JAR projects, then specify a clear set with the compile scope on the Maven WAR project.
I prefer the former approach as additional 3rd party dependencies will be automatically added to the WAR artefact via the transitive dependency paths. Yet the second approach provides the certainty of knowing exactly what 3rd party libraries will be included.
In the pom.xml
of the jar-a
project exclude the mail
dependency with the exclusions
tag:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.x</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>mail</artifactId>
</exclusion>
</exclusions>
</dependency>
If your 3rd party lib depends on an unnecessary library that is the best thing you can do. If they are open source projects you can submit a patch which removes the unnecessary libs.
About the 'future proofing': If you would like a repeatable build you should declare exact version numbers for your dependencies like [1.0]
which doesn't let maven to update them whenever a new version come out. In this way a 3rd party library never changes its dependencies because you don't update to a new version which depends on other libs. Of course you should check the dependencies too when you update a 3rd party lib to a new version.
On the other hand your functional tests should report when a new library version broke your application.
I see that it's not too easy with 40+ POMs but it still easier than the old times when you had to download every dependency by hand.
http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Transitive_Dependencies
The subject discussed in this documentation is somewhat an answer to my question. It discusses the use of the <dependencyManagement>
tag.
This tag can be declared within a parent POM file and allows you to specify the details of dependencies, as well as exclusions. Then any POM that inherits from the parent POM can declare a dependency as usual, but it will inherit any configuration from the parent, unless overridden.
For instance, take the parent POM dependency configuration:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>mail</artifactId>
</exclusion>
</exclusions>
<scope>compile</scope>
</dependency>
</dependencies>
</dependencyManagement>
The dependency within the child POM is now made far simpler:
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
</dependencies>
Here the child POM inherits the version, exclusions and scope configuration. This doesn't resolve all the concerns I've mentioned, such as the need to know about the 3rd party library's dependencies, but it does provide a single place for configuring and managing these finer details.
精彩评论