Continue maven build although dependency is missing - java

Is there a way to tell maven to continue the build although a dependency ist missing?
I tried <optional>true</optional> but this doesn't seem to do it in this scenario.
I have build a costum Maven Plugin for the package phase and it does still have to package even if one or multiple dependencies could not be found.
Thanks in advance.

<optional>true</optional>
Optional means that a client using your library does not necessarily need that dependency. An example is Spring's ORM module, that has optional dependencies to Hibernate, JDO, JPA and mybatis. Nobody will ever use all of these in a project, so each is marked as optional.
Your case is completely different, you are trying to compile something, and you can only do that if the libraries you compile against are present. Sorry, it don't work like that.

If you are trying to build something while the rest of the team finishes their parts, you could use a Mocking framework that creates something that looks like the classes you need . Check out, for example mockito
Otherwise, the only thing you can do is run mvn with -fn (fail-never) but that will mask all your errors and not just the missing dependencies

Related

Spring boot: Will a library get dependency from the parent app/service

I am using spring-retry in my spring-boot service, as well as spring-boot library.
I Noticed this scenario to work:
Use spring retry logic in the library, but the spring retry jars are not imported in the library
Use the library in the parent service as a maven dependency.
The parent service imports spring-retry maven jars.
Is is normal for the library code to use the maven jars from the parent app ? and not need to import the jars itself ? My common intuition says it should, as the resulting compilation unit will have the dependencies injected.. but not sure.
Sorry if this is a super naive question, but my searches did not give a good answer (maybe want using the right keywords)
I'm not sure I've got you right, probably this question should be rephrased.
So you say, that there is a "spring-boot library" that uses spring retry logic.
If so, this library has a maven module and it gets compiled into a regular jar, right?
But if so, if it uses classes/interfaces/annotations from spring retry library and doesn't have it on the compile class path how it gets compiled? I believe you do have this spring retry library in the dependencies but just don't notice (try mvn dependency:tree in the spring boot library module to see the dependencies)
Other than that - usually when you develop a library its intended to be reused by different applications, and if it has dependencies on its own, usually it should list them in the project's library pom. Also usually people who develop the library try to minimize the dependencies list of the library itself.
So if pom.xml of the library doesn't list the required dependencies it won't even compile.
Now in runtime, all the dependencies (including transitive of course) should be available to the spring boot application, otherwise the class that uses these dependencies might not load. But other than that, spring, being a runtime framework, doesn't really care how did the dependency find its way into BOOT-INF/lib folder - its expected to work as long as the dependency is there.

Spring - Missing Required Library - hibernate3-3.2.3.GA.jar

I was following this tutorial to understand the Spring and Hibernate. After I added the hibernate dependency like this:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.2.3.ga</version>
</dependency>
I got this error
Project 'SpringExample' is missing required library: 'C:\Users\gmuniandy\.m2\repository\hibernate\hibernate3\3.2.3.GA\hibernate3-3.2.3.GA.jar' SpringExample Build path Build Path Problem
.
I have downloaded the jar file and placed in the folder manually but the issue still remain. Please advice.
EDIT
I guess it is an wrong writing in thy pom.xml: Instead of "ga" use "GA" as Ragu already wrote.
Did you try already the downloadable project from the Website?
And what looks strange to me, I found no hint about case-sensitivity on maven.org, though maven uses case-sensitive match when matching against property values. Referring to Maven Model
May I suggest, that you follow this tutorial?
Accessing Relational Data using JDBC with Spring
At the bottom of the Article you will see a complete pom.xml which obtains the required and correct versions of libs from a inherited pom.
It should keep your pom short and simple. So you can better concentrate on your task rather than bothering around with libs at an early stage of your project.
Have you tried to clean up your local Maven repository and resolve dependencies again?
version is wrong -correct one 3.2.3.GA , In mvn repository you can search specific jar maven dependency.

How do I check jar file dependencies

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.

Maven and optional runtime dependencies

I'm starting to fix a java project that has used maven and while I've got the project to build, at runtime it fails with missing dependencies. I've had a look and the errors are missing optional dependencies of included compile time dependencies. I can go through and add these but it seems to me that I can have everything building and running nicely only for some piece of code that I missed to use a missing dependency and the whole thing falls apart.
What I really want to know is whether there is an automated way to find optional dependencies that I have chosen to not include. I have used mvn dependency:tree but this only shows the dependencies I have (not sure of the scope it checks) and I have tried mvn dependency:analyze but this seems to show dependencies it thinks I don't use and those that have been pulled down indirectly. What I cannot see is how to see a list of optionals I don't include.
Currently my method of working around this is to read the poms and try to work it out from there, but I don't see this as particularly robust.
For reference, I am fairly new to maven style dependency management and on the face of it like it, but this optional thing is a bit of a stumbling block for me. I understand that optionals stop me pullin down dependencies I won't be using, but it hasn't clicked for me how I can workout what optionals are available and that I do need.
I am using Eclipse Juno, m2Eclipse (also have maven 3.0.5 cli), java 6/7.
Anyone got any ideas of how I can do this better, or what I am completely overlooking?
No the things are - somewhat - just this way. Maven does not do dependency management, it allows you to do dependency management by offering tools to use and analyze them. So the work still is on the developers side. People often mix that up.
This is mainly caused by the fact that projects often have different deployment targets. As a result sometimes they collect a bunch of jar files which are copied once into tomcat and a different set of files for weblogic. So there might be a readme in your project that states what to copy prior to deployment of the maven artifacts. Or it is implicit knowledge - then you're doomed.
dependency:analyze works on bytecode not on sources. therefore it does not see what maven knows.
Maybe mvn help:effective-pom gives a better basis to analyze the whole thing? Or you could try to modify the dependency plugin to show that information as well. Maven plugins are not so hard to work with.
I'm not aware of a plugin that displays all optional transitive dependencies. But since the pom.xml files of dependencies are downloaded into the local maven repo you could do a text search there.
A while ago there was a discussion on optional dependencies as well: Best strategy for dealing with optional dependencies - it might be helpful too.

How check if dependency is used by any of my classes and list them in Maven?

I want to do some clean up in POM.XML. How can I check which dependencies aren't used at all by my code and if one is used then how tell which one is it?
Of course I don't want to simply delete dependency and then search for errors in IDE, because that could take ages when pom has got about 80+ dependencies.
I'm using SpringSource Tools Suite version of Eclipse.
Greetz
Have a look at the Maven Dependency Plugin. When running, it should list the dependencies that you declared but do not use, but also which intransitive dependencies you use without explicitly declaring them. Note that it you use reflection, the report may not be accurate.

Categories

Resources