Maven 2 & 3

deprecate system scope, analyse other use cases

Details

  • Complexity:
    Intermediate
  • Number of attachments :
    1

Description

possibly can avoid all use cases for system scope through proper use of alternate resolvers. Gather use cases (see MNG-1471) to ensure.

Issue Links

Activity

Hide
Mike Whittemore added a comment -

I would like to be able to specify a system path for any dependency regardless of the scope. For example, I would like to mark junit-3.8.1 as being in the "test" scope, yet point at a jar that is not in the repository. Something like this:

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
<path>${cots.top}/junit/junit.jar</path>
</dependency>

I don't want to mark it as "system" scope, simply to say it is not in the repository because that would lose the fact that it is really something scoped for the unit test phase.

I understand the preferred way to use maven is to install 3rd-party artifacts in the repository (and the public ibiblio repository if possible), but the security culture in my company will not allow it (there is a rigid procedure for how 3rd-party jars and tools get downloaded, installed, and used - not uncommon in our particular industry). Without this feature I will be forced to mark all 3rd-party jars as "system" scoped, which I want to avoid. Regardless of my special circumstances, this feature would add a little more flexibility to maven for handling special cases.

So to summarize, I would like to be able to tag certain dependencies with a system path, but still tag them with an appropriate build scope such as"runtime", "test" or "provided". If tagged with a path, the dependency would not go to the repository to resolve the jar, but instead would follow the system path. Additionally, the path should be allowed to contain variables so I can make the build portable across operating systems (for example, by using a varaible to indicate the root directory of COTS software installations).

I would be happy to help out with the implementation, though I would need a few pointers of where to focus my attention.

Show
Mike Whittemore added a comment - I would like to be able to specify a system path for any dependency regardless of the scope. For example, I would like to mark junit-3.8.1 as being in the "test" scope, yet point at a jar that is not in the repository. Something like this: <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> <path>${cots.top}/junit/junit.jar</path> </dependency> I don't want to mark it as "system" scope, simply to say it is not in the repository because that would lose the fact that it is really something scoped for the unit test phase. I understand the preferred way to use maven is to install 3rd-party artifacts in the repository (and the public ibiblio repository if possible), but the security culture in my company will not allow it (there is a rigid procedure for how 3rd-party jars and tools get downloaded, installed, and used - not uncommon in our particular industry). Without this feature I will be forced to mark all 3rd-party jars as "system" scoped, which I want to avoid. Regardless of my special circumstances, this feature would add a little more flexibility to maven for handling special cases. So to summarize, I would like to be able to tag certain dependencies with a system path, but still tag them with an appropriate build scope such as"runtime", "test" or "provided". If tagged with a path, the dependency would not go to the repository to resolve the jar, but instead would follow the system path. Additionally, the path should be allowed to contain variables so I can make the build portable across operating systems (for example, by using a varaible to indicate the root directory of COTS software installations). I would be happy to help out with the implementation, though I would need a few pointers of where to focus my attention.
Hide
Brett Porter added a comment -

Mike - we are currently resorting to custom resolvers for such cases. You basically use the repository, or you don't - it can't be mixed and matched. Is this acceptable if it is documented?

Show
Brett Porter added a comment - Mike - we are currently resorting to custom resolvers for such cases. You basically use the repository, or you don't - it can't be mixed and matched. Is this acceptable if it is documented?
Hide
Mike Whittemore added a comment -

Sorry, I'm not sure what you mean by custom resolver. I browsed the subversion files a bit and nothing really jumped out at me. Are you saying there is something called a "custom resolver" that I can configure such that Maven will resolve dependecies found outside the repository, and that if I use this mechanism I cannot use the repository at all? If so, where do build artifacts go when I run Maven install?

If you are saying there is essentially a way to do what I need but it requires giving up use of the repository completely, then documenting that would likely solve my dilemma. Thanks.

Show
Mike Whittemore added a comment - Sorry, I'm not sure what you mean by custom resolver. I browsed the subversion files a bit and nothing really jumped out at me. Are you saying there is something called a "custom resolver" that I can configure such that Maven will resolve dependecies found outside the repository, and that if I use this mechanism I cannot use the repository at all? If so, where do build artifacts go when I run Maven install? If you are saying there is essentially a way to do what I need but it requires giving up use of the repository completely, then documenting that would likely solve my dilemma. Thanks.
Hide
Mike Whittemore added a comment -

Just to be clear on one of my questions above, I meant: where do my build artifacts go when I run "mvn install" if I am not using a repository. Thanks.

Show
Mike Whittemore added a comment - Just to be clear on one of my questions above, I meant: where do my build artifacts go when I run "mvn install" if I am not using a repository. Thanks.
Hide
Brett Porter added a comment -

ok, will work on that.

The custom resolver would be paired by an installer that would install the artifacts into the same locations you refer to above, I assume. However, its completely up to you.

Show
Brett Porter added a comment - ok, will work on that. The custom resolver would be paired by an installer that would install the artifacts into the same locations you refer to above, I assume. However, its completely up to you.
Hide
Jason van Zyl added a comment -

Deprecate during 3.0, remove in 3.1. System scope and picking artifacts up off the local file system is bad.

Show
Jason van Zyl added a comment - Deprecate during 3.0, remove in 3.1. System scope and picking artifacts up off the local file system is bad.
Hide
Arnaud Heritier added a comment -

NOOOO. I'm not against deprecating/removing it, but we cannot remove things in a 3.1 version
Our users won't understand how we can provide a 3.0 100% backward compatible and a 3.1 which is not.

Show
Arnaud Heritier added a comment - NOOOO. I'm not against deprecating/removing it, but we cannot remove things in a 3.1 version Our users won't understand how we can provide a 3.0 100% backward compatible and a 3.1 which is not.
Hide
Jason van Zyl added a comment -

It's all about setting expectations, documenting the changes and providing alternatives like easier ways to get everything into the local repository.

Show
Jason van Zyl added a comment - It's all about setting expectations, documenting the changes and providing alternatives like easier ways to get everything into the local repository.
Hide
Jesse Glick added a comment -

System scope is the only known way to do certain tasks. Most notably:

http://maven.apache.org/general.html#tools-jar-dependency

This case could be solved "properly" only if everyone agreed that the (Open)JDK 6 or 7 version of tools.jar sufficed, and could be legally published to a well-known repository. There may be other rarer cases with dt.jar etc.

Show
Jesse Glick added a comment - System scope is the only known way to do certain tasks. Most notably: http://maven.apache.org/general.html#tools-jar-dependency This case could be solved "properly" only if everyone agreed that the (Open)JDK 6 or 7 version of tools.jar sufficed, and could be legally published to a well-known repository. There may be other rarer cases with dt.jar etc.
Hide
Jason van Zyl added a comment -

It's not the only way. What we do in the compiler plugin is discovery the location and load it appropriately. One small library to deal with the locations that JDK provides on various platforms. We're not putting a JVM specific tools.jar in Maven Central. This doesn't work for people who use the IBM JDK, or deal with cases where platforms have custom JVMs like the Blackberry. The strategy employed in the compiler plugin will be expanded. A little more work, but the right thing to do.

Show
Jason van Zyl added a comment - It's not the only way. What we do in the compiler plugin is discovery the location and load it appropriately. One small library to deal with the locations that JDK provides on various platforms. We're not putting a JVM specific tools.jar in Maven Central. This doesn't work for people who use the IBM JDK, or deal with cases where platforms have custom JVMs like the Blackberry. The strategy employed in the compiler plugin will be expanded. A little more work, but the right thing to do.
Hide
Jesse Glick added a comment -

Most of tools.jar - the part created by the OpenJDK langtools project - is not JVM-specific and can be used as a plain old Java library with any JRE (1.5 or later). For example, if you want an implementation of javax.tools.JavaCompiler to be present with test scope (because your unit tests generate and compile source code on the fly), this would be the obvious choice. Besides clarity, using regular artifacts provides better reproducibility of builds since the version of the tool is encoded directly in the POM in the normal way rather than being at the mercy of the environment, and you could switch to a particular version of ECJ if that were faster or did not have a crucial bug.

There are some less frequently used pieces like the com.sun.tools.attach and com.sun.jdi APIs which should probably be packaged as separate artifacts with the understanding that they are applicable to JREs derived from the Sun codebase. You ought to be able to compile modules using these APIs without requiring Maven to be run with a Sun JDK.

Special embedded JVMs generally need their own tools. For example, for Android development the plugin handles the special build, packaging, and verification steps needed by that platform. This would not be done with system-scope JARs to begin with, and the JVM running Maven is almost certainly different from the target JVM.

Show
Jesse Glick added a comment - Most of tools.jar - the part created by the OpenJDK langtools project - is not JVM-specific and can be used as a plain old Java library with any JRE (1.5 or later). For example, if you want an implementation of javax.tools.JavaCompiler to be present with test scope (because your unit tests generate and compile source code on the fly), this would be the obvious choice. Besides clarity, using regular artifacts provides better reproducibility of builds since the version of the tool is encoded directly in the POM in the normal way rather than being at the mercy of the environment, and you could switch to a particular version of ECJ if that were faster or did not have a crucial bug. There are some less frequently used pieces like the com.sun.tools.attach and com.sun.jdi APIs which should probably be packaged as separate artifacts with the understanding that they are applicable to JREs derived from the Sun codebase. You ought to be able to compile modules using these APIs without requiring Maven to be run with a Sun JDK. Special embedded JVMs generally need their own tools. For example, for Android development the plugin handles the special build, packaging, and verification steps needed by that platform. This would not be done with system-scope JARs to begin with, and the JVM running Maven is almost certainly different from the target JVM.
Hide
Paul Benedict added a comment -

When it comes to system scope, the idea of hard-coding a file path into your POM seems really counter-intuitive to the flexible nature of Maven. In my opinion, such information is actually a user setting. Why not move that kind of basic resolution into settings.xml? For example:

<system-dependencies>
  <groupId/>
  <artifactId/>
  <version/>
  <systemPath/>
</system-dependencies>
Show
Paul Benedict added a comment - When it comes to system scope, the idea of hard-coding a file path into your POM seems really counter-intuitive to the flexible nature of Maven. In my opinion, such information is actually a user setting. Why not move that kind of basic resolution into settings.xml? For example:
<system-dependencies>
  <groupId/>
  <artifactId/>
  <version/>
  <systemPath/>
</system-dependencies>
Hide
Karl Heinz Marbaise added a comment -

Currently i have the following example of using the system scope:

<dependency>
  <groupId>org.apache.hadoop</groupId>
  <artifactId>hadoop-common</artifactId>
  <version>${hadoop.version}</version>
  <scope>system</scope>
  <systemPath>${basedir}/hadoop-${hadoop.version}/hadoop-common-${hadoop.version}.jar</systemPath>
</dependency>
...

This makes it possible to handle the situation where artifacts are not availabe as Maven artifacts (central..). I would suggest to make at least a scope available to have dependencies which are located within the current project.

<dependency>
  <...>
  <scope>project</scope>
  <systemPath>../...jar</systemPath>
</dependency>

Furthermore the usage of things like tools.jar of the JDK would be usefull as well as mentioned earlier.

Show
Karl Heinz Marbaise added a comment - Currently i have the following example of using the system scope:
<dependency>
  <groupId>org.apache.hadoop</groupId>
  <artifactId>hadoop-common</artifactId>
  <version>${hadoop.version}</version>
  <scope>system</scope>
  <systemPath>${basedir}/hadoop-${hadoop.version}/hadoop-common-${hadoop.version}.jar</systemPath>
</dependency>
...
This makes it possible to handle the situation where artifacts are not availabe as Maven artifacts (central..). I would suggest to make at least a scope available to have dependencies which are located within the current project.
<dependency>
  <...>
  <scope>project</scope>
  <systemPath>../...jar</systemPath>
</dependency>
Furthermore the usage of things like tools.jar of the JDK would be usefull as well as mentioned earlier.
Hide
Jesse Glick added a comment -

To Karl's example: using install:install-file you can accomplish this without <scope>system</scope>, and arguably in a better way because it is straightforward to use the library from multiple modules, and to associate sources and Javadoc too. Look at the attached demo.

Show
Jesse Glick added a comment - To Karl's example: using install:install-file you can accomplish this without <scope>system</scope>, and arguably in a better way because it is straightforward to use the library from multiple modules, and to associate sources and Javadoc too. Look at the attached demo.

People

Vote (2)
Watch (7)

Dates

  • Created:
    Updated: