Include a Maven dependency only if it exists - java

I have a problem, I have a project which is based in a system that includes modules. This modules are other maven projects and are referenced from system POM. My problem is I'm sharing the system project with a workmate and we've got different modules.
So, is there a way to tell Maven that I want to include a module referenced in my POM only if this module exists? I mean, without compilation failure.
Thanks!

I would suggest to use profiles and activate them on file/exists option.

Use dependencyManagementis to pull all the dependency information into a common POM file, simplifying the references in the child POM file.

There are several solutions, depending on what you can do/want to achieve.
One approach is to install a Maven repository server at your company (in your local LAN or in a LAN that you and your colleague share). Build the system and then deploy the modules to the server.
In your build, you can add this new server like this (documentation):
<project>
...
<repositories>
<repository>
<id>my-internal-site</id>
<url>http://myserver/repo</url>
</repository>
</repositories>
...
</project>
Or you can both copy the base system and build it locally with mvn install. That will copy all artifacts into your local cache.
From there, you can reference them as usual. You don't need to include all the modules; just the ones you really need. That way, you and your friend don't have to use the same dependencies.

Related

Replace maven library with local one

I have a dependency in pom on some library.
I want to make some changes in it, test it locally and if it will work fine - deploy it to remote repo.
So I have locally made some changes in this library, installed it as a jar, and want to replace in my main project remote library with the local one.
What is proper way to do it?
You can override default maven repository in project's pom:
<repositories>
<repository>
<id>central</id>
<url>file://d:/repo</url>
</repository>
</repositories>
When resolving dependencies, Maven looks in your local repository ($HOME/.m2/repository). So if you have installed your modified dependency into your local repository (e.g. through mvn install) then when you build your main project, it will be used.
To make this more obvious, you may want to change the versions being used in both the library and your main project POM, so that you can be sure your version is being used for testing.
You may also find this question/answer useful: How do I force Maven to use my local repository rather than going out to remote repos to retrieve artifacts?
Maven first looks in your local repository in
C:\Users\User\.m2\repository
and if it can't find the library, then it looks in remote repos. If I understand your question correctly, this should be happening automatically as long as you point the correct version in the POM.

Set the maven local repository location in a pom.xml file?

It's possible to set the maven local repository in settings.xml:
<localRepository>${user.home}/.m2/repository</localRepository>
And it's possible to set the maven local repository on the command line:
mvn clean install -Dmaven.repo.local=repository
Is it possible to specify within the pom.xml itself?
Note: I'd like a way to specify, in the pom.xml, where maven initially searches for artifacts (by default, ~/.m2/repository) and where maven installs artifacts via mvn install (by default, ~/.m2/repository).
According to the Maven POM Reference and the Guide to using multiple repositories, you can specify repositories in pom.xml too.
There are two different ways that you can specify the use of multiple repositories. The first way is to specify in a POM which repositories you want to use
And according to Introduction to repositories, you can use the file:// protocol in <url>.
Remote repositories refer to any other type of repository, accessed by a variety of protocols such as file:// and http://.
So the following works:
<project>
...
<repositories>
<repository>
<id>example-repo</id>
<name>Example Repository</name>
<url>file://path/to/your/local/repository</url>
</repository>
</repositories>
</project>
Edit:
Based on your comment and edit, you need to override the default repository and Maven home directory in pom.xml.
I've found a topic about disabling central repository, and tried out the answers, but Maven still uses the values from settings.xml. This answer in another thread explains why:
settings.xml allows you to override definitions in pom.xml, not the other way round.
So it's seems it is not possible to override the default mechanism from pom.xml, Maven will search for dependencies in repositories configured in settings.xml and will install to Maven home specified in that file.
If the problem is having to write the options every time when running maven, you can use a feature available since version 3.3.1 that allows you to set command line options in your project (or parent project of your module). Read #Brice's answer: https://stackoverflow.com/a/48583079
So with this feature in mind, you can achieve a similar result by setting up a new settings.xml with the <localRepository> pointing to the location you desire and use maven.config in your project to make maven use the new settings.xml, which by the way can be anywhere you want.

Maven: Using a project folder as a repository for lib

I have a project with the following layout:
My goal was to have mvn looking in the project lib dir as an additional location for potential libs that would not be found in maven repository like j-text-utils.jar for example. So I added this in the pom.xml
<repositories>
<repository>
<id>lib</id>
<url>file://${project.basedir}/lib</url>
</repository>
</repositories>
I took the idea from here: http://randomizedsort.blogspot.co.il/2011/10/configuring-maven-to-use-local-library.html
When running mvn compile, it fails to find the relevant libs in the project folder.
Is there anything wrong with the above?
Thx
There is nothing wrong to setup a file based repository. But first and foremost, your directory structure needs to conform to the groupid/artifactid. You should use
set localrepopath=C:\path_to_repo_rootdir
call mvn install:install-file -Dfile=xyz-1.2.jar -DgroupId=com.foo -DartifactId=xyz -Dversion=1.2 -Dpackaging=jar -DlocalRepositoryPath=%localrepopath% -DcreateChecksum=true
It will create directory com\foo\1.2 with all the pom.xml, jar files, checksum files under it.
Then you need to define the dependency for these newly installed artifacts in your own project pom.xml.
If you do not want to setup local repository and only want to add them to the compile classpath, you can consider using "system" scope dependency, but it will make your build not portable and is discouraged in general.
You can do that (just configure the maven-dependency-plugin properly), but I wouldn't suggest that.
There might be a few drawbacks with that direction (e.g., having the Jars there could get into the repository you're using, for many projects it's better to have only one Jar in a dedicated place of your HDD rather than having one of them in each and every project, etc.).

Configure Maven To Create An Archive File With All Dependencies Defined in POM XML

I am working in a private network which doesn't have internet proxy.
I can not create a local repository as well which involves the bureaucracy, management won't allow it. I may be a long term fix but not the solution for the question I asked.
I can not keep maven as a build tool as it requires the direct or indirect internet connection.
I HAVE to use ANT for building the project hence using maven in offline mode also not an option for me.
But I still want to use the maven dependency management for collecting all the jars in a one archive smartly.
My plan is to generate a ZIP file containing dependencies resolved using maven. And then we will share this ZIP file to all developers working inside a private network which doesn't have internet connection.
To do so I will get a temporary access to a computer which is having internet connection and from there I will define a dummy POM with all the dependencies required.
Now the question is how do I generate a ZIP file ( not a single jar ) using maven which contains all the dependencies defined in POM.
while what youre suggesting is technically possible, it is (in my opinion) not the best solution to your problem.
your statement that
it requires the direct or indirect internet connection
is not accurate. what maven requires is a maven repository (or a set of them) to fetch stuff from. the best solution to your problem would be to install a local maven repository inside your organization's network. the 2 most popular choices for a loaclly-run maven repository seem to be nexus and artifactory - both offer free open source versions and paid supported pro versions.
once you set up a maven repository inside your organization's network and populate it with the artifacts you require you can simply configure all of your project's pom files to go to those repositories. for example, to configure maven to use your repo instead of maven central, you can do this:
<repositories>
<!-- override central -->
<repository>
<id>central</id>
<url>http://your.repo.location</url>
</repository>
</repositories>
you will need to map a plugin repository in a similar fashion.
its also possible to achieve this by configuring the maven settings.xml file in each user's home directory if you dont want this in the pom files but from my experience its less error-prone this way
use following command to build Maven project offline.
mvn -o package
Refer this and this for more information.
I ended up with a smart hack which lets me do dependency resolution and archiving!
I am creating a dummy maven web project with all the dependencies defined in pom xml.
Now the war packaging mode is used by default for web applications.
I simply install the maven project from internet facing machine.
I get all the dependencies and transitive dependencies in war file's "lib" directory with dependency naming version remaining unchanged !!!!
Copying and adding those files into an ANT project is a trivial task then..!

Maven: Add local dependencies to jar

I have a dependency
<dependency>
<groupId>de.matthiasmann</groupId>
<artifactId>twl</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/TWL.jar</systemPath>
</dependency>
Then I execute mvn assembly:assembly. All natives files and remote maven libs are added, but there is no this jar.
UPDATE
When I am trying to run app by java -jar myjar.jar. It returns an error that there is no class from the above dependency (NoClassDefFoundError : de.matthiasmann.twl.ForExample).
I want to add classes from this jar to myjar.jar (the same what maven does with remote dependencies). How I can configure maven to do that?
See Maven 2 assembly with dependencies: jar under scope "system" not included for why system dependencies are not included and how you can work around it, specifically the mvn install:install-file code is what you want.
You cannot use systemPath, unless your Java EE server/container has that jar configured.
Remember that maven is development and compile time only. Once the war file is built, maven has no effect except for having placed all the desired jars into the WEB-INF/lib folder.
When you specify system scope, it means that it is your responsibility to ensure that the jar is present when the war is deployed. You already have a framework to do that and you do not wish to encumber your build dependency with that jar, but you have to make it available thro Maven only during development.
The other similar scope is "provided". e.g., JBoss or your corporate common deployment Tomcat framework already provides many of the jars like Spring and Hibernate that are loaded by the server startup and common to all apps in the server. Therefore, you would not want maven build to include those into the war file.
The right way, Maven gurus would tell you. is to have your own maven server and build whatever artefacts you need into that server. However, occasionally that is not possible.
Therefore, on such occasions, I create project level repository that is distributed with the project and checked into version control. I run the command mvn install to create a project level directory called, say, "project-repo".
http://maven.apache.org/plugins/maven-install-plugin/examples/specific-local-repo.html (Due to familiarity, most of the time, I build the repo by hand rather than run mvn install).
Then in the POM, I specify file://${project.basedir}/project-repo as one of the repositories. The caveat with this is that in Windows, the slashes other than the pair after "file://" has to be back-slashes when referring to Windows file system paths.
<repositories>
<repository>
<id>my-repo1</id>
<name>my custom repo</name>
<url>http://ho.ho.ho</url>
</repository>
<repository>
<id>project-repo</id>
<name>my project repo</name>
<url>file://${project.basedir}\project-repo</url>
</repository>
</repositories>
YOu can implement this in many ways refer the blog below
http://blog.valdaris.com/post/custom-jar/
If you have such an dependency the best solution is first to use a repository manager and simply put that dependency into the repository manager and afterwards use it as simple dependency.

Categories