Finding unused (compile-scoped) jars in multiple projects using maven ? - java

I have a webapp that consists of multiple projects. We assemble using Ant and we suspect that some of the jars in /java directory are unneeded.
To find unneeded jars I ran
mvn dependency:analyze -DignoreNonCompile
to get a list of unused declared jars for each project. However it is possible that a jar unused by one project is still used by another. To check this, I ran
mvn dependency:tree
to get the dependency structure of all projects.
Using information from these commands, I will now use a script to check if a jar exists such that it is unused in all projects that declare it. Is this a reasonable approach for compile-scoped jars? What about jars in other scopes?
Thanks.

However it is possible that a jar unused by one project is still used
by another.
I recommend to declare all needed dependencies as direct dependencies and not rely on transitive dependencies which might get removed in a newer version.
Define the versions of the dependencies in the DependencyManagement section of the common parent POM and omit the versions later when declaring the dependcies. Like this you can make sure you're using the same version of the dependencies in all your projects.

Related

How to find if I need to exclude dependencies in a maven java project?

I use both Intellij IDEA (2018.3.5) & Eclipse IDEs, but I prefer Intellij. I have a maven based Java project with multiple poms. I added some dependencies to one of the pom files. I need to find out if there are any dependency conflicts which could prevent the build from running when its deployed, and then exclude them. I tried the steps given below to find conflicts which could cause problems. Are they enough or do I need to do more ?
Check if there are any compile time dependency conflicts with mvn clean install -DskipTests. Build was successful with no errors.
Check if Intellij shows no problems under File > Project Structure > Problems. There are no problems.
I also saw the dependency tree with mvn dependency:tree -Dverbose. It has a lot of "omitted for duplicate" and "omitted for conflict with" items, but the build was successful. I don't see any errors though. Does this mean that everything is okay or do I have to do something more about these conflicts ?
The best way to tell if everything is fine with your application is to have good tests.
However normally one doesn't exclude transitive dependencies from project's <dependency> libraries. Doing it can potentially break the dependency in a subtle and hard to notice way. It's usually safer to remove the whole <dependency>.
There are few scenario when one should use <exclude>:
Dealing with incompatible transitive dependencies between different libraries e.g. A requires library C-1.0 but library B requires library C-2.0 while C-1.0 and C-2.0 can't coexist on the classpath.
Having transitive dependencies already provided by system e.g. deploying to Tomcat with additional JARs in the TOMCAT_HOME/lib directory.
If you decide to exclude a dependency it's important that you check the final artifact because sometimes plugins do weird things e.g. there were versions of maven-assembly-plugin affected by a bug that resulted in different dependencies being resolved during shaded JAR creation than maven-dependency-plugin used for compilation.

Maven repackage transitive dependencies

The app consists of modules and each module is particular maven project with one parent. These modules are used as jars in main app.
Each module uses third party SDK via maven.
These SDKs have many dependencies and these dependencies can be with the same group and artifact but with different versions. It is hard to manage them and we have problems with 'NoSuchMethodError's. As for me the simplest way to fix problem is to get sources of problematic dependencies and source of SDK, change the package (add some prefix) and imports and put it inside sdk jar.
But this approach requires: one more git repository for forked SDK's jars and private maven repository to publish them and a lot of time.
Is there maven plugin that can help with this problem, for example plugin that can build jar (our module jar) with all dependencies included inside it but can change package of all dependencies?
You can try to use the Maven shade plugin which allows you to relocate classes
https://maven.apache.org/plugins/maven-shade-plugin/examples/class-relocation.html
but I have never tried this myself.
In most cases it is better to try to align the dependencies so that you use the same versions in most places and also to reduce dependencies to a minimum.
Congratulations, you are confronted with a classpath problem called "jar hell". The only safely working solution i know is the use of different classloaders for each version of the same class (if it's not backward compatible).
A class is identified by its qualified name (package and class name) and by the classloader it has been loaded. If the application uses the default system classloader and there is the same class in different versions in the classpath only one version will be loaded by the classloader. In the oracle JDK/JRE it is the one which occurred first in the classpath. If you are lucky you can bring the classpath (order and excluding dependencies) in a special order in which your application will run, but i wouldn't recommend it since it relies heavy on the JDK/JRE implementation.
OSGI is a technology which might be helpful for this since it provides a module based framework for using different classloaders.

Is there some way to clean the maven dependencies?

I am working in a Maven project which has about 250 jar dependencies. Approximately Four out of five dependecies are not direct dependencies, I mean, they are dependencies of our dependencies (i.e jasperreport has about 8 dependencies).
Also, I suspect that there are some jar which we don't need to the project because they were old dependencies of old tool that we needed in the past but they were replaced by others.
What I need is:
To detect what jars of my pom.xml are not needed by the
project.
A way of removing the indirect jars from my pom.xml.
*Note: I'd swear that some time ago I manage to the indirect jars were downloaded by the direct dependencias, but I can't find how.
You're after mvn dependency:analyze:
Analyzes the dependencies of this project and determines which are: used and declared; used and undeclared; unused and declared.
This will let you remove any dependency which is not directly used from your pom. The dependencies that are used will still bring in their transitive (indirect) dependencies, as required.
I'm not really sure if you need to remove some dependencies of any of your direct dependencies or just want to clean jars downloaded.
If your problem is the first one, you can use "exclude" for that dependencies -> http://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html
If it's the second one, just remove your .m2/repository content and rebuild again your project

How to find which maven dependencies are missing

I have a web project and a pom.xml file. It has enough dependencies to compile and package but not enough to start the project. In my IDE it's shown that everything is ok, but when a start the application it has errors. When i add external pom.xml from another app, my application launches.
So is there any way i can find out which dependencies are missing and how in future i can determine which dependencies are needed for using this or that?
You can use mvn dependency:analyze for determining which dependencies are used and declared or used and undeclared or unused and declared.
For more information refer to: http://maven.apache.org/plugins/maven-dependency-plugin/analyze-mojo.html.
Hope this helps.
There's no maven command to accomplish this. You need to check which classes are causing NoClassDefFoundError, figure out the dependency (Google) - which JARs they are shipped in, and add them with the runtime scope in your pom.xml.
In web projects specifically you oftentimes compile against servlets or Java EE specification JARs (they would only contain interfaces), but you need actual implementation JARs to be present in runtime. These JARs are typically and presumed to be available in the container you are running in (like Tomcat or JBoss), in this case they would be marked as provided scope in your pom.xml.
You need to check the NoClassDefFoundError in your output logs and add dependencies accordingly.
The best resource to search for missing dependencies is Maven Central Repository
To get a detailed debug log of your build, use -X in the command line.
You can check The dependency tree of your project by following command - mvn dependency:tree. This will only list the information about the deoendencies listed in your pom.xml More on it here
should be able to do it with :
maven dependency resolve

Reduce jar file size

Is there any way to reduce jar file size?
I want a tool that reduces the unused dependencies.
I use maven for dependency management.
A JAR file doesn't normally contain dependencies in the Maven sense. So you must be talking about:
a WAR or EAR or similar file,
a so-called UberJAR file produced by combining lots of JAR files; e.g. using the Maven shade plugin, or
dependencies at a finer granularity than Maven modules.
In the first two cases, you can keep out nominally dependent JARs by excluding them, either in the dependency specification, or in the war or shade plugin build descriptor. IIRC, the shade plugin also allows you to exclude specific packages and classes.
The last may require a separate tool to post-process the JAR file. Getting rid of unused classes is the kind of thing that an obfuscator can do. However, you need to be careful not to eliminate classes or class names that are used reflectively; e.g. by a DI / IoC framework or an AOP framework.
(Generally speaking, this kind of tool tries to figure out what classes are used by analysing the dependencies implied by .class file external references. DI / IoC / AOP and so on introduce other kinds of dependency that are not apparent in the .class file structure.)
If you like to know the dependencies your project uses just check the maven-dependency-plugin which can be used to analyze the used/unused dependencies.
Check your dependencies via:
mvn dependency:analyze
or take a look at the dep tree like this:
mvn dependency:tree
Or you can take a look into your ide (depending which one you use) for example with Eclipse (Indigo) and the m2e plugin you have a tab "Dependency Hierarchy" which shows the tree of dependencies incl. the transitive dependencies.
In some situation you have to be careful about dependencies which are used by DI frameworks which can't be analyzed by maven-dependency-plugin or by ide plugins.
pack200 can drastically reduce the JAR size. But it's hard to use with Maven and impossible to use with an EE container.
Why do you have unused dependencies?

Categories