Maven leaves out a jar from WAR - maven

We use maven 2.2.1 to build project. A master pom lists modules that are built (some WAR project and some "plain" JARs).
Recently we added a new dependency into one of the WAR projects:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.2.6</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
<exclusion>
<artifactId>commons-codec</artifactId>
<groupId>commons-codec</groupId>
</exclusion>
</exclusions>
</dependency>
When built locally from command line (mvn clean package) on a developers machine, it works fine. But when built on the automatic build system (by Hudson) the httpcore JAR (it is a dependency of httpclient) is not packaged into the final WAR. No error is reported, just the JAR is missing.
The maven settings.xml files are identical (except the repo path - the only noticeable non-default option is offline=true). What could be wrong?

The only thing that comes to my mind is that your build machine has old version of one of your modules in m2 repo.
Clear up whole $HOME/.m2/repository (or where you keep the repo) and try again.

Problem found. (and solved)
In short: the httpclient.jar in the repo was without its .pom file. (so maven did not know it had dependencies)
Long:
It is an offline repository, so missing artifacts must be fixed manually. The problem is I first copied the files to the wrong folder and maven did not "see" them. Then "blindly" followed its advice:
Missing:
----------
1) org.apache.httpcomponents:httpclient:jar:4.2.6
Try downloading the file manually from the project website.
Then, install it using the command:
mvn install:install-file -DgroupId=org.apache.httpcomponents -DartifactId=
httpclient -Dversion=4.2.6 -Dpackaging=jar -Dfile=/path/to/file
That would just copy the jar file to the repo, without the pom.
So I just copied the complete folder for httpclient into the repo (and its parent and some other related files that maven then complained about).
It's a form of user error, I guess.

Related

Transitive Dependency How do i exclude. -- Maven

I have the below project structure under lib for project 2.
Project 2 (under lib)
- Maven dependencies (JARs)
- project 1 JAR (it has JARs in lib)
- Maven dependencies of project 1 (JARs)
I want to exclude all JARs under project 1 while preparing project 2.
I'm currently using the below in my POMs (both project 1 and project 2)
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
When building project 1, I want it to build as an executable JAR with lib.
However when building project 2, I want project 1 as only a compiled JAR (meaning with only class files and not having lib (JARs)).
Project 1 is included as a normal dependency in Project 2. Can anyone help me out?
If you want to exclude all dependencies of a given dependencies, use exclusions
https://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html
and do it like
<dependency>
<groupId>sample.ProjectA</groupId>
<artifactId>Project-A</artifactId>
<version>1.0</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
Of course, you have to be sure that the missing transitive dependencies are not needed at runtime.
If I understand correctly project 1 builds a jar which has inside a lib directory with the dependencies.
You could in project 1 have 2 assembly executions, one the basic jar and another with dependencies and execute manifest, normally you use a different "classifier" for multiple artifacts of the same project.
Otherwise you would need to "repackage" the jars to remove the libs you don't want using some plugin like Shade.
I think the first option is much better, also by default if you publish it to a repository both jars will be published so other people can get one or the other.

Excluding transitive dependency not working

Project A references Project B. Project B has included a local dependency. This local dependency unfortunately has a dependency to net.java.dev.designgridlayout in version 1.5.
We want to use net.java.dev.designgridlayout in version 1.11 in Project A but we are not able to "overwrite" the dependency. Eclipse always uses the dependency from Project B.
We already tried to exclude the 1.5 version from the local dependency, but it doesn't work.
The strange thing is, that Eclipse successfully resolves a class that has been added with version 1.11. For an already existing class, however, eclipse resolves it from the transitive dependency from de.someCompany.
Project B:
<dependencies>
<dependency>
<groupId>de.someCompany</groupId>
<artifactId>fs-client</artifactId>
<version>5.1.209</version>
<exclusions>
<exclusion>
<groupId>net.java.dev.designgridlayout</groupId>
<artifactId>designgridlayout</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.java.dev.designgridlayout</groupId>
<artifactId>designgridlayout</artifactId>
<version>1.11</version>
</dependency>
</dependencies>
Project A:
<dependencies>
<dependency>
<groupId>Project-B</groupId>
<artifactId>Project-B</artifactId>
<version>1503.01</version>
</dependency>
</dependencies>
I also tried to include the 1.11 dependency in Project A.
We even tried to install the DesignGridLayout V. 1.11 in the local dependency and to change the groupID and artifactId to something different, but it cannot even be found by Eclipse for some reason. If it would be possible to include the DesignGridLayout with another groupId and artifactId, I think it would work.
mvn install:install-file -Dfile=lib\designgridlayout.jar -DgroupId=com.company.designgridlayout -DartifactId=design-grid-layout -Dversion=1.11 -DgeneratePom=true -Dpackaging=jar -DlocalRepositoryPath="%USERPROFILE%\.m2\repository"
Not sure - but:
Your project A has a dependency to itself? Shouldn't it use project-b?
Its not a good idea to change group or artifact id's as maven can no longer detect its the same artifact. If you do a custom version the version number should be enough.
If you add the dependency in your own pom then you don't need to exclude the artifact, since the groupId and artifactId are the same. The version in your own pom will win in project-b. If project a defines that dependency again itself that version will win.
I would do a mvn dependency:tree on project-a pom to see where the dependencies come from.
For eclipse: it indexes the local repository. In the maven settings there is a re-index button. So if you manually copy jars in there that may help eclipse to find the artifact. But that workaround would need to be done on every machine. I would not count that as solution. In the maven world artifact-resolution is an infrastructure issue and should not be handled per project. The way this is done should be transparent through the settings.xml

extra jar in war in a maven project

One business jar which have been developed by us is present in war. but I don't see in pom.xml.... when I search whole eclipse I found it is in .setting folder(.settings/org.eclipse.wst.common.component) of eclipse of same project.
here is entry of
<dependent-module archiveName="BankAccount-3.0.39.jar" deploy-path="/WEB-INF/lib"
handle="module:/classpath/var/M2_REPO/com/BankAccount/3.0.39/BankAccount-3.0.39.jar">
<dependency-type>uses</dependency-type>
</dependent-module>
If you are sure that jar is not needed by your project, then run mvn dependency:tree and find the origin of the particular jar. Then you can exclude the jar by using
<exclusions>
<exclusion>
<groupId>Group Id</groupId>
<artifactId>jar which you want to exclude</artifactId>
</exclusion>
</exclusions>
under the particular jar through which it got bundled.
You can also remove the jar by using the <exclusion> tag in assembly.xml of the particular project
Do mvn dependency:tree and see how it works.

How do i use a "xxx-bin.tar.gz" file in a maven dependency?

i have some code that needs to work with the shibboleth codebase. The manual install steps i do are to download the shibboleth-identityprovider-2.3.5-bin.tar.gz, then extract it and do some tweaking and adding some jars that i build.
I want to do this in a maven assembly phase. However, since the binary has a "-bin" in it, i don't know what to specify in my pom.xml to download that file. In my pom i have:
<dependency>
<groupId>edu.internet2.middleware</groupId>
<artifactId>shibboleth-identityprovider</artifactId>
<version>2.3.5</version>
<type>tar.gz</type>
<exclusions>
<exclusion>
<artifactId>shibboleth-jce</artifactId>
<groupId>edu.internet2.middleware</groupId>
</exclusion>
</exclusions>
</dependency>
However, the dependency check fails (presumably because the tar file is named "shibboleth-identityprovider-2.3.5-bin.tar.gz" and not "shibboleth-identityprovier-2.3.5.tar.gz".
I'm not sure what i need to specify in my pom to use the proper tar file.

The right way to use maven

I'm new to maven, I got 2 problems here:
1,How to solve missing artifact problem?
I need jcharts-0.7.5, but it's not available in Maven Central Repository. I have the jar file, but seems not easy to put it into a maven project.
2,How to fix wrong dependency scope of artifact?
I have a WAR project depends on artifact axis2-kernel, which is depending on servlet-api-2.3 with the scope of 'compile' (mistake of 'provided'), so mvn install packet the servlet-api-2.3.jar into the war file, and causes a "validateJarFile(...) - jar not loaded." error in Tomcat 7.
Number one: use a maven repository. This can be a simple Apache HTTP site with static content. But I would recommend using Sonatype Nexus or JFrog Artifactory for storing artifacts not found somewhere else.
You may find them in the JBoss repository or IBiblio (both quite big)
Number two: you can add that dependency to your pom and just set the scope you want. If you exclude the artifact you will have to add it again anyway. Maven will always prefer what is directly in you pom:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
To answer your second question: you can exclude transitive dependencies using the < exclusion > tag: http://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html
<project>
...
<dependencies>
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-kernel</artifactId>
<version>...</version>
<exclusions>
<exclusion><!-- declare the exclusion here -->
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
There are many different solutions how to add missing dependencies. For example, you could use the scope system and provide the path (you can put the JAR into the project and use a path relative to ${basedir}).
But a much better solution is to install a server like Nexus or Artifactory because they allow you to create your own repositories and they still work should the Internet fail (for example, when some idiot breaks your router or your ISP has some problems or someone drives a 18 inch double-T steel beam through a bunch of fibres).
Builds will also be much faster since the downloads will be via your local LAN instead of going around half the globe.
You can simply repeat the dependency in your POM with a different scope (your POM always wins) or you can use a dependencyManagement element.
I prefer the dependencyManagement approach because it allows you to set scopes and versions in a single place for all your projects.

Resources