how to add external jar to maven webapp project - maven

I have a Spring roo project (basically a maven project). I want to add dropbox sdk to the project, problem is it's not in maven. I added the following files
<dependency>
<groupId>com.dropbox</groupId>
<artifactId>dropbox-sdk</artifactId>
<version>1.3.1</version>
<scope>system</scope>
<systemPath>${project.basedir}/libs/dropbox-java-sdk-1.3.1.jar</systemPath>
</dependency>
It solved the compile error, but when i run the project, in Spring Tool Suite, the jar files are not added to war lib folder. How do I make maven add my external jar files to my the war lib folder?
I don't want to install the jar in maven since, I have to install it in all the machines that uses the project

I finally found a neat solution, which is a lot easier to implement. You add an in-project repository inside the java project and link to it in the pom.
You add an in-project repository in maven like this:
<repository>
<id>in-project</id>
<name>In Project Repo</name>
<url>file://${project.basedir}/libs</url>
</repository>
Then create a folder structure in the root folder of your project that looks something like this
/groupId/artifactId/version/artifactId-version.jar
and add the dependency as you would normally do.
This approach has the least amount of code and work required, and if that library ever gets add into a maven repository you can always remove your in-project repository.

There is a much easier solution, which is set webResource in the plugin. By the solution, you can add any files of your local disk to the war! A sample is as below,
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<warName>api</warName>
<webResources>
<resource>
<directory>libs/</directory>
<targetPath>WEB-INF/lib</targetPath>
<includes>
<include>**/*.jar</include>
</includes>
</resource>
</webResources>
</configuration>
</plugin>

The best way to resolve this issue is to add these local jar files to WEB-INF/lib folder. You will find all these jars packaged in your final war file then.

I don't recommend this approach, but you could add some POM configuration to install the 3rd-party dependency in a separate profile:
<profiles>
<profile>
<id>install-dependencies</id>
<build>
<plugins>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<id>install-dropbox-sdk</id>
<phase>validate</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<groupId>com.dropbox</groupId>
<artifactId>dropbox-sdk</artifactId>
<version>1.3.1</version>
<file>src/main/lib/dropbox-java-sdk-1.3.1.jar</file>
<packaging>jar</packaging>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>build</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>com.dropbox</groupId>
<artifactId>dropbox-sdk</artifactId>
<version>1.3.1</version>
</dependency>
</dependencies>
</profile>
</profiles>
There are two profiles here: install-dependencies and build. The first installs the dropbox-sdk dependency into your Maven repository and needs to be run once on every machine as follows:
mvn -Pinstall-dependencies validate
The second is enabled by default, and adds the Dropbox SDK as a dependency.
To be honest though, this isn't much better than running
mvn install:install-file -Dfile=src/main/lib/dropbox-java-sdk-1.3.1.jar -DgroupId=com.dropbox -DartifactId=dropbox-sdk -Dversion=1.3.1 -Dpackaging=jar
on every machine.
The other downside of this approach is that you'll have to add all dependencies of the dropbox-sdk to your build as well- whereas if it is done properly by adding the JAR and a POM to a repository server, then Maven will calculate the transitive dependencies properly.

I recommend creating a "third party" repository in a Maven repository server such as Nexus or Artifactory, and uploading the jar to there. Even though that means putting the jar into Maven, at least with a repository server it is available to anyone who will be building your application.

change the lib path to :
src/main/webapp/WEB-INF/lib
in pom.xml:
<systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/xxxx.jar</systemPath>

The steps described in this site are pretty simple, and they work well enough:
https://mythinkpond.com/2010/10/02/adding-custom-jars-under-web-inflib-in-a-maven-project/
Create a “lib” folder under your project like this: “\src\main\webapp\WEB-INF\lib”
Copy needed “jars” etc that you want included inside your WAR bundle folder.
Invoke your maven build as you normally do. I use “mvn install”, which creates builds the war file.

I know I am really late but I was wondering on why you would not put in the jar in the local repo in the .m2 file and add a reference to the pom from there ?

Related

Unable to use class from Custom Spring boot library

Goal
I want to use a private repository as a library in other spring boot projects by hosting it as a GitHub package.
Library project
https://github.com/sagarnayak/privatecentralrepo
Client Project
https://github.com/sagarnayak/repoclientproject
Steps To Reproduce
the library project has a library001 module. this is what I want to use as a library for other projects.
In the library module pom file, I have added the repackage execution goal.
......
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
......
I want to use the module as a library and host it as a private GitHub package.
When I do the mvnw deploy in the library001 module this should create an exec jar and push to GitHub to use this library in other projects.
Github has this exec jar.
To use the jar in the client project I have added this as a dependency in the client project.
<dependency>
<groupId>com.sagar</groupId>
<artifactId>libraray001</artifactId>
<version>0.0.3-SNAPSHOT</version>
<classifier>exec</classifier>
</dependency>
This gets the project into the external libraries part of the client project. and this has the class that I want to use in the library (TestModel001).
But when I try to import this into any classes that I want to use it can not resolve the import.
How do I use the library project in this project?
I solved the issue with this -
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
The issue was with the pom file.
I was using the configurations for an older version.
The client project as visible at sagarnayak/repoclientproject is not configured to consume the artifacts from the private Maven repository hosted on GitHub as described in the Working with the Apache Maven registry.
Specifically, following settings are missing:
<repositories> configuration in pom.xml
<servers> configuration in local settings.xml
Add following elements to the pom.xml:
<repositories>
<repository>
<id>github</id>
<url>https://maven.pkg.github.com/sagarnayak/</url>
</repository>
</repositories>
Add following elements to the settings.xml
<servers>
<server>
<id>github</id>
<username>sagarnayak</username>
<password>YOUR_PERSONAL_ACCESS_TOKEN_HERE</password>
</server>
</servers>
Note: Keep settings.xml local to your machine - don't leak that Personal Access Token!
You are packaging the library via spring-boot-maven-plugin
It produces a JAR that has a self-running spring boot structure, and so you are unable to import it as a library correctly.
Try to remove spring-boot-maven-plugin from your libraray001 pom.xml, rebuild, republish and try to consume that artifact in your client project again, refreshing the dependencies and preferably bumping up the library version, to exclude caching possibility during the test.

Maven - How to extract a dependency inside another ZIP dependency?

I have a maven project.
Inside that project, I have a .zip dependency that carries a jar and I need to extract that jar out of the zip dependency and have maven use the jar as a dependency. I can currently download and unpack the zip but, cannot figure out a way to add the unpacked jar as a dependency for the project during the build process.
Here is what I'm currently doing for unpacking:
<dependency>
<groupId>com.bar</groupId>
<artifactId>foo</artifactId>
<version>${foo.version}</version>
<type>zip</type>
</dependency>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<phase>validate</phase>
<configuration>
<includeGroupIds>com.bar</includeGroupIds>
<includeArtifactIds>foo</includeArtifactIds>
<outputDirectory>${basedir}/target</outputDirectory>
<type>jar</type>
</configuration>
</execution>
</executions>
</plugin>
I read up on some other posts that you could try adding the jar to the class path using this.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<additionalClasspathElements>
<additionalClasspathElement>${basedir}/target</additionalClasspathElement>
</additionalClasspathElements>
</configuration>
</plugin>
Even doing so I was still unable to reference the packages in foo.jar in my project.
Can someone help me?
For maven to use it without subtly breaking stuff elsewhere, you must install the jar into your local repository.
I would suppose that a combination of unpacking the zip file in target/ and then invoking install:install-file on the resulting jar could do what you need. I asked some years back how to integrate that in a normal build - you might find the answer relevant. Multiple install:install-file in a single pom.xml
Let's assume that, after unpacking the zip, you have foo.jar in your module's target folder: ${project.build.directory}/foo.jar
Having this in place, you can then declare a System Dependency pointing to that jar, e.g.
<dependency>
<groupId>foo</groupId>
<artifactId>foo.jar</artifactId>
<systemPath>${project.build.directory}/foo.jar</systemPath>
</dependency>
Tip: if you dont want to delete/re-download the jar each time you do a clean (some IDE will complain the the jar is not always present) just download it once in the ${project.basedir}.
To download the jar once, you can put your "unpack" execution in a profile that gets activated only when the jar is missing.
<profiles>
<profile>
<activation>
<file>
<missing>${project.basedir}/foo.jar</missing>
</file>
</activation>
...
</profile>
</profiles>
Some time ago, I've faced the same problem. I had a zip file as my dependency, and during the build process I need to extract it and separate the content inside my generated package.
I don't know what are you using to deliver your project, but at that time I've used the maven-antrun-plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>2.6</version>
</plugin>
With this, I've used the tag unzip inside my target configuration. As you can see here or here. I just don't recommend you to use the task tag as they're using, you'd better prefer the target tag.
Hope it helps you.

Maven dependencies from parallel projects, not modules.

I have following maven projects (note : maven project, not maven modules). I know i will get questions, why not modules, but it has its own story, anyway.
myproj-common (JAR),
myproj-core (JAR),
myproj-product1-batch (EAR),
myproj-product2-batch (EAR)
myproj-core depends on myproj-common, and myproj-product1-batch depends on myproj-core.
If it is modules, i can simply create dependency. It if is standard archive, I can also create dependency and have JAR available in repository, if it is a library JAR, I can ...bla bla bla ...all standard dependency I can fix, I am not sure how to make a jar that is sitting somewhere on the disk, a dependency.
I am not able to get
C:\Documents and Settings\users\myproj-common\target\myproj-common-0.0.1-SNAPSHOT.jar
into following jar, as a dependency
C:\Documents and Settings\users\myproj-core\target\myproj-core-0.0.1-SNAPSHOT.jar
same problem for the JAR into EARs.
Any idea ? How ...hoping a small, quick and surprising fix, just not visible to me.
I don't see any reason why you shouldn't be able to use mvn install to install these jars and ears into your local repository. Then, you can just include them as dependencies anywhere you like.
I doubt that you'll be able to cleanly get maven to pull in a jar sitting anywhere on your filesystem other than your local repository.
To clarify, when you do mvn install it puts your JAR in the target folder, but it also puts it into your local repository (C:\Documents And Settings\.m2 by default in Windows). After that JAR is installed there, you can include that JAR in other projects as a maven dependency using a "dependencies" block in your pom like this:
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
The dependencies mechanism is explained in the Maven Docs.
In addition, you'll need to tell maven to actually package all dependencies in the JAR. You can do that by adding this to your POM. (Also check this question How can I create an executable JAR with dependencies using Maven? for the source of this code block).
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>

How to include resources from war to another maven project

I have a maven project , which needs to copy webapp/WEB-INF/ resources from another maven project which is packaged as a war .
How do I do it ?
PLease suggest
As Bittrance said, you should use the maven dependency plugin.
The better way is to create project that include all your shared resources, probably a type zip, which is build up with the assembly plugin. This is the good "maven way". It's a better solution than unpacking a war.
Then, refer it
<dependency>
<groupId>com.mygroup/groupId>
<artifactId>my-dependencies</artifactId>
<version>1.0.0</version>
<type>zip</type>
</dependency>
Next, you use the maven dependency plugin to unpack your resources, in the directory of your choice (probably WEB-INF/ ?)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-cfg-test-resources</id>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<phase>resources</phase>
<configuration>
<outputDirectory>${project.build.directory}/WEB-INF/</outputDirectory>
<includeArtifacIds>my-resources</includeArtifacIds>
<excludeTypes>pom</excludeTypes>
<excludeTransitive>true</excludeTransitive>
</configuration>
</execution>
</executions>
</plugin>
I'm not realy sure of this code snippet (written for another purpose), but this is an example.
For more information, please follow this link : http://maven.apache.org/plugins/maven-dependency-plugin/
If you can't shared a common-project including your files, you can unpack war including only ftl (or whatever you want), but it's not a realy clean solution ;)
There is a lot of posts that deal with this subject :
Unzip dependency in maven
...
Just try with the keywords maven-dependency-plugin, unpack :)
Hope that will help you.
I can see some alternatives:
Use external references in your version control system to point all repos to the same files.
The Maven Dependency module can copy and unpack project dependencies. From there, you can use the Maven Assembly plugin (or Ant targets) to include parts of that dependency in your own installation.
At least for the FTL files, perhaps you could package them in a separate Jar file and then load them as resources through the class loader.
If the resources are filtered, you may get into problem with solution 1 if you want the filtered version and 2, 3 if you want the source version.
Hope this helps.
(This assumes your dependent project is java (jar) and not another web app, if it is a webapp I think the solution is similar).
I suggest a (slightly) different approach:
Instead of reading resources from war, add this to your war pom, to generate a jar in the artifact as well as a war:
<!-- maven war plugin config -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<configuration>
...
<attachClasses>true</attachClasses>
<classesClassifier>some-string</classesClassifier>
</configuration>
<artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version>
</plugin>
...
<resources>
<!-- This is for inclusion in the jar, so dependent module can load it -->
<resource>
<targetPath>some-path</targetPath>
<directory>src/main/webapp/path...</directory>
<includes>
<include>your-resource</include>
</includes>
</resource>
</resources>
And this to your consuming pom, so the generated jar will be loaded:
<dependency>
<groupId>com.company</groupId>
<artifactId>...</artifactId>
<classifier>some-string</classifier>
</dependency>
Then you will be able to load the resources the usual way (getResourceAsStream("some-path/your-resource"))

Maven WAR dependency

I am writing a project for acceptance testing and for various reasons this is dependent on another project which is packaged as a WAR. I have managed to unpack the WAR using the maven-dependency-plugin, but I cannot get my project to include the unpacked WEB-INF/lib/*.jar and WEB-INF/classes/* to be included on the classpath so the build fails. Is there a way to include these files into the classpath, or is there a better way of depending on a WAR?
Many thanks.
There's another option since maven-war-plugin 2.1-alpha-2. In your WAR project:
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<attachClasses>true</attachClasses>
</configuration>
</plugin>
This creates a classes artifact which you can use in the acceptance tests project with:
<dependency>
<groupId>your-group-id</groupId>
<artifactId>your-artifact-id</artifactId>
<version>your-version</version>
<classifier>classes</classifier>
</dependency>
Indeed, by design, Maven doesn't resolve transitive dependencies of a war declared as dependency of a project. There is actually an issue about that, MNG-1991, but it won't be solved in Maven 2.x and I'm not sure that I don't know if overlays allow to workaround this issue. My understanding of the suggested solution is to duplicate the dependencies, for example in a project of type pom.
(EDIT: After some more digging, I found something interesting in this thread that I'm quoting below:
I have been helping out with the development of the AppFuse project over
the last month where we make heavy use of the war overlay feature in the
Maven war plugin. It is a really nifty feature!
To get max power with war overlays I have developed the Warpath plugin
that allows projects to use war artifacts as fully fledged dependencies.
In brief:
1) The contents of the /WEB-INF/classes directory in the war dependency
artifacts can be included in the project's classpath for normal compile,
etc tasks.
2) Transitive dependencies from the war dependency artifacts become
available for use by other plugins, e.g. compile and ear - so no more
having to include all the dependencies when creating skinny wars!
The plugin has now been actively used in the AppFuse project for the
last few months, and I feel it is at a point where it is both usable and
stable.
Would the war plugin team be interested in including the warpath
functionality inside the war plugin? It would seem to be the most
natural place to host it.
So, I don't have any experience with it, but the maven warpath plugin actually looks nice and simple and is available in the central repo. To use it,include the following plugin configuration element in your pom.xml file:
[...]
<build>
<plugins>
<plugin>
<groupId>org.appfuse</groupId>
<artifactId>maven-warpath-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>add-classes</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
[...]
And add the war dependencies you want included in the classpath as warpath type dependencies:
[...]
<dependencies>
<dependency>
<groupId>org.appfuse</groupId>
<artifactId>appfuse-web</artifactId>
<version>2.0</version>
<type>war</type>
</dependency>
<dependency>
<groupId>org.appfuse</groupId>
<artifactId>appfuse-web</artifactId>
<version>2.0</version>
<type>warpath</type>
</dependency>
</dependencies>
[...]
Both the war and warpath dependency types are needed: the war type is used by the Maven war plugin to do the war overlay, the warpath type is used by the Warpath plugin to determine the correct list of artifacts for inclusion in the project classpath.
I'd give it a try.)
Use overlays. First, your test project need to have also packaging war.
Declare dependency of war project you want to test:
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>your-project-arftifactId</artifactId>
<version>${project.version}</version>
<type>war</type>
<scope>test</scope>
</dependency>
then configure maven-war-plugin overlay:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webResources>
<resource>
<directory>${basedir}/src/main/webresources</directory>
<filtering>true</filtering>
</resource>
</webResources>
<overlays>
<overlay/>
<overlay>
<groupId>your.group</groupId>
<artifactId>your-project-artifactId</artifactId>
</overlay>
</overlays>
</configuration>
</plugin>
In the above example in test project I overwrite webresources configuration files (like conxtext etc.).
EDIT: This solution wasn't tested with Maven 3.
Good point, Justin. That got me actually solving my problem, namely: including a war into an assembly AND including all its transitive dependencies.
I could not duplicate the war-dependency as 'jar' as you suggested since the assembly plugin would not find a jar referenced by that groupId/artefactId, but
duplicating the war-dependency as type pom
works!
The war and its transitive dependencies are not included in the assembly.
To exclude the (now also appearing) pom file I had to add an exclude element like this:
<excludes>
<exclude>*:pom</exclude>
</excludes>
into my assembly.xml file.
I think this could also be a workaround for the original question of this thread.
If you list the dependency on the war project as a jar dependency it seems to pickup the required jars/resources. I'm using Maven 2.2 + m2eclipse.

Resources