Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Local jars are not included in class path (`<scope>system</scope>`)

Tags:

java

maven-2

I am trying to build my application using maven and eclipse. I have dependencies on 3rd party jars which are on my local machine. here is my pom.xml

<dependency>
    <groupId>sourceforge.net</groupId>
   <artifactId>zipdiff</artifactId>
   <version>0.4</version>
   <scope>system</scope>
   <systemPath>C:/gelcap/lib/zipdiff-0.4.jar</systemPath>
</dependency>

<dependency>
    <groupId>log4j</groupId>
   <artifactId>log4j</artifactId>
   <version>1.2.11</version>
</dependency>

when i run mvn : install it creates war file for my project. But problem is it does not include zipdiff.jar file to the web-inf/lib folder it only includes the files which are downloaded. I need to include copy the files from my local system also but maven ignores them. I have not got any thought why it is happening why maven is not including files with system scope to my war file. Please give me any idea how this problem can be resolved. Thanks in advance

like image 395
viren Avatar asked Jul 19 '10 12:07

viren


2 Answers

With "system" scope, the container is expected to provide the artefact. From the maven docs:

provided

This is much like compile, but indicates you expect the JDK or a container to provide the dependency at runtime. For example, when building a web application for the Java Enterprise Edition, you would set the dependency on the Servlet API and related Java EE APIs to scope provided because the web container provides those classes. This scope is only available on the compilation and test classpath, and is not transitive.

[...]

system

This scope is similar to provided except that you have to provide the JAR which contains it explicitly. The artifact is always available and is not looked up in a repository.

By using a system scope, you are indicating to the war plugin that the container will provide this dependency. Since this is not what you are intending to do, the simplest solution is to put the artefact in a repository, either your local maven repository, or your own maven repo on your intranet, if you have one.

The install:install-file goal can be used to install a single file (without POM) to your local repository. After doing this, change the dependency type to "compile" and remove the "systemPath" element.

In my day job, we use Nexus to manage a company-wide repository on our intranet. You can have separate repositories for your own artefacts, vs third party artefacts. Nexus also acts as a proxy, caching artefacts from external repositories, speeding up the build quite a bit. This means that only the developer that uses a new dependency that is not available in the other repos has to upload - after that, all the other devs can use it - they can checkout from SCM and build without worrying about where the dependencies are located.

like image 179
mdma Avatar answered Oct 19 '22 23:10

mdma


I have not got any thought why it is happening why maven is not including files with system scope to my war file. Please give me any idea how this problem can be resolved.

This is by design, system scoped dependencies are supposed to be provided as documented.

Actually, I've written numerous times (here, here, here and here) that system scoped dependencies should be avoided. They are most of time a bad practice, people are abusing them, and they generate almost always more troubles than benefits.

Let me quote the Dependency Scopes mini guide if you want an "official" point of view:

  • system: This dependency is required in some phase of your project's lifecycle, but is system-specific. Use of this scope is discouraged: This is considered an "advanced" kind of feature and should only be used when you truly understand all the ramifications of its use, which can be extremely hard if not actually impossible to quantify. This scope by definition renders your build non-portable. It may be necessary in certain edge cases. The system scope includes the <systemPath> element which points to the physical location of this dependency on the local machine. It is thus used to refer to some artifact expected to be present on the given local machine an not in a repository; and whose path may vary machine-to-machine. The systemPath element can refer to environment variables in its path: ${JAVA_HOME} for instance.

So, instead of using the system scope, either:

  • Add your libraries to your local repository via install:install-file. This is a quick and dirty way to get things working, it might be an option if you're alone but it makes your build non portable.
  • Install and run an "enterprise repository" like Nexus, Archiva, or Artifactory and add your libraries via deploy:deploy-file. This is the ideal scenario.
  • Setup a file based repository as described in this previous answer and put your libraries in there. This is the best compromise if you don't have a corporate repository but need to work as a team and don't want to sacrifice portability.

Please, stop using the system scope.

like image 33
Pascal Thivent Avatar answered Oct 19 '22 23:10

Pascal Thivent