If I build a war for a specific platform (e.g. Wildfly), I need to filter out dependencies that are already provided by the platform.
Up to now, we do this by using a special BOM that lists all the provided dependencies with scope provided. Alternatively, one could also use the Maven war plugin to exclude the dependencies when building the war.
What is the preferred way?
Provided scope is there for this specific reason.
From maven documentation
provided
This is much like compile, but indicates you expect the JDK or a container to provide the dependency at runtime. For example, when building a web application for the Java Enterprise Edition, you would set the dependency on the Servlet API and related Java EE APIs to scope provided because the web container provides those classes. This scope is only available on the compilation and test classpath, and is not transitive.
The transitive dependencies of the provided scope will be also be in provided scope unless it is explicitly added in compile scope. If exclution is used it may cause jar conflict unless those jar are also excluded.
Also provided scope works with other packaging like ear
I am quite new to maven and inherited an old application which I need to maintain. It has couple of provided libraries (which are provided by the container). I am wondering whether there is any way to generate a war with all the dependencies (including the provided libs) without modifying the pom.xmls. (there are quite lot) Is there any way to override the scope for all libs from the command line?
My challenge is that I am dealing with an enterprise application with quite deep dependency graph and there are lot of provided dependencies all over the places. As a part of my experimentation I would like to generate a war which is self contained and have all the dependencies. Updating the dozens of poms and changing the scope is not what I am looking for. Is there any way to do this from the command line?
You only have to change the one pom that creates the war. In this pom, specify the dependencies that are currently "provided" with the desired scope.
Maven computes the transitive dependencies for the war project based on the modules that it depends on and is bringing in those particular dependencies with a provided scope. You can think of this as defining the default configuration for those dependencies. You can override the default (inherited) scope by explicitly specifying the dependency in your war module with the desired scope.
In my opinion, the non-war modules probably should not be setting the scope to provided and instead should leave this decision to the module that will actually create the runnable artifact (e.g., your war module). For example, if you were to make a fat jar to execute the code as a standalone app (vs. a war in a container that provides those dependencies), you probably would want to include them in the jar.
With maven we can exclude some transitive dependencies.
But what if we need them at runtime, and still as architect I don't want them to be used and become API dependencies.
Is there tool to define and check for unwanted used dependency (i.e. imported in some Java class)?
A search here gives me hint for maven
In maven, can you disallow usage of transitive dependency in your code but still keep it in the classpath?
But that may be to laborious to define. Maybe IDE tools should be used?
How to disallow import and use of some transitive maven dependencies?
So that code will not be accessing different layers of our stack.
Yes, I understand that some educational work should go as well.
When dealing with maven there is a concept of dependency scope. Typically for Java EE applications you will see 3 scopes leveraged the most:
Compile - This is the default scope used if none is specified. These will be available in all of a project's classpaths.
Provided - This scope is used when the dependency is not needed for compilation, but is expected to be in the container at runtime.
Test - This is a dependency needed for testing, but not required for the normal use of the application
Based off of your use case I believe you are looking to leverage the provided scope for a dependency where the dependency is needed at runtime, but should not be available to the application during compilation. You can read more about dependency scopes at: https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html
I need to check the Maven dependency injection order automatically. In a Maven module I take two dependencies with the same classes name and package. One dependency should always have priority on the other one, this mean it have to be declared first because of the order of dependencies injection of Maven.
It's possible to verify it with the dependency tree but manually, I wish there is a way to check this automatically.
Do you know if it is possible to do this with Maven?
First of all, "dependency injection" is something completely different and unrelated: managed magical mechanisms to pass needed objects from "outside" when constructing objects.
Maven just compiles code with dependency jars in the classpath. Any variant of the monkeypatched classes should allow your code to be compiled identically, so (to minimize breakage) you should avoid duplicate or conflicting Maven dependencies.
Reliably loading your replacement classes at runtime when Maven is no longer involved is an entirely different problem, whose solution depends on how your application is packaged and executed. For example, the order of jars in a typical classpath list should be reliable, and most application servers offer ways to specify and override with one another various global and application-specific classpaths.
I am coming from .NET background and I need to do some JAVA work these days. One thing I don't quite understand is how JAvA runtime resolve its jar dependencies. For example, I want to use javax.jcr to do some node adding. So I know I need to add these two dependencies because I need to use javax.jcr.Node and org.apache.jackrabbit.commons.JcrUtils.
<dependency>
<groupId>javax.jcr</groupId>
<artifactId>jcr</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-jcr-commons</artifactId>
<version>2.8.0</version>
</dependency>
</dependency>
Now I passed the compilation but I get an exception in runtime. Then someone told me to add one more dependency which solves the problem.
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-jcr2dav</artifactId>
<version>2.6.0</version>
</dependency>
From my understanding, jackrabbit-jcr-commons needs jackrabbit-jcr2dav to run. If the jar misses a dependecy, how can it pass the compilation? And also how do I know I miss this particular dependency from jcr-common? This is a general question, it doesn't have to be specific to java jcr.
Java doesn't have any built-in way to declare dependencies between libraries. At runtime, when a class is needed, the Java ClassLoader tries to load it from all the jars in the classpath, and if the class is missing, then you get an exception. All the jars you need must be explicitly listed in the classpath. You can't just add one jar, and hope for Java to transitively load classes from this jar dependencies, because jar dependencies are a Maven concept, and not a Java concept. Nothing, BTW, forbids a library writer to compile 1000 interdependant classes at once, but put the compiled classes in 3 several different jars.
So what's left is Maven. I know nothing about JCR. But if a jar A published on Maven depends on a jar B published on Maven, then it should list B in its list of dependencies, and Maven should download B when it downloads A (and put both jars in the classpath).
The problem, however, is that some libraries have a loose dependency on other libraries. For example, Spring has native support for Hibernate. If you choose to use Spring with Hibernate, then you will need to explicitly declare Hibernate in your dependencies. But you could also choose to use Spring without Hibernate, and in that case you don't need to put Hibernate in the dependencies. Spring thus chooses to not declare Hibernate as one of its own dependencies, because Hibernate is not always necessary when using Spring.
In the end, it boils down to reading the documentation of the libraries you're using, to know which dependencies you need to add based on the features you use from these libraries.
Maven calculates transitive dependencies during compile-time, so compilation passes ok. The issue here is that, by default, maven won't build a proper java -cp command line to launch your application with all of its' dependencies (direct and transitive).
Two options to solve it:
Adjust your Maven project to build a "fat jar" -- jar which will include all needed classes from all dependencies. See SO answer with pom.xml snippet to do this: https://stackoverflow.com/a/16222971/162634. Then you can launch by just java -cp myfatjar.jar my.app.MainClass
For multi-module project, with several result artifacts (that is, usually, different java programs) it makes sense to build custom assembly.xml which will tell Maven how to package your artifacts and which dependencies to include. You'll need to provide some kind of script in resulting package which will contain proper java -cp ... command. As far as I know, there's no "official" Maven plugin to build such a script during compilation/packaging.
There's free Maven book which more or less explains how dependencies and assemblies work.
Your question mixes Maven (a java-centric dependency resolution tool) and Java compile-time and run-time class-resolution. Both are quite different.
A Java .jar is, in simplified terms, a .zip file of Java .class files. During compilation, each Java source file, say MyClass.java, results in a Java bytecode file with the same name (MyClass.class). For compilation to be successful, all classes mentioned in a Java file must be available in the class-path at compile-time (but note that use of reflection and run-time class-name resolution, ala Class.forName("MyOtherClass") can avoid this entirely; also, you can use several class-loaders, which may be scoped independently of each other...).
However, after compilation, you do not need to place all your .class files together into the same Jar. Developers can split up their .class files between jars however they see fit. As long as a program that uses those jars only compile-time refers to and run-time loads classes that have all their dependencies compile-time and run-time available, you will not see any runtime errors. Classes in a .jar file are not recompiled when you compile a program that uses them; but, if any of their dependencies fails at run-time, you will get a run-time exception.
When using Maven, each maven artifact (typically a jar file) declares (in its pom.xml manifest file) the artifacts that it depends on. If it makes any sense to use my-company:my-library-core without needing my-company:my-library-random-extension, it is best practice to not make -core depend on -random-extension, although typically -random-extension will depend on -core. Any dependencies of an artifact that you depend on will be resolved and "brought in" when maven runs.
Also, from your question, a word of warning -- it is highly probable that jackrabit-jcr2dav version 2.6.0 expects to run alongside jackrabbit-jcr-commons version 2.6.0, and not 2.8.0.
If I had to guess (without spending too much time delving into the Maven hierarchies of this particular project), I believe your problem is caused by the fact that jackrabbit-jcr-commons has an optional dependency on jackrabbit-api. That means that you will not automatically get that dependency (and it's dependencies) unless you re-declare it in your POM.
Generally speaking, optional dependencies are a band-aid solution to structural problems within a project. To quote the maven documentation on the subject (http://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html):
Optional dependencies are used when it's not really possible (for
whatever reason) to split a project up into sub-modules. The idea is
that some of the dependencies are only used for certain features in
the project, and will not be needed if that feature isn't used.
Ideally, such a feature would be split into a sub-module that depended
on the core functionality project...this new subproject would have
only non-optional dependencies, since you'd need them all if you
decided to use the subproject's functionality.
However, since the project cannot be split up (again, for whatever
reason), these dependencies are declared optional. If a user wants to
use functionality related to an optional dependency, they will have to
redeclare that optional dependency in their own project. This is not
the most clear way to handle this situation, but then again both
optional dependencies and dependency exclusions are stop-gap
solutions.
Generally speaking, exploring the POMs of your dependencies will reveal this kind of problem, though that process can be quite painful.