Version 99 Does Not Exist emulates a Maven 2 repository and serves empty jars for any valid package that has version number 99.0-does-not-exist. It also generates poms, metadata files and of course the appropriate hashes. For example the following links will give an empty jar, its pom and the maven metadata for commons-logging. Why?
To get rid of dependencies that maven 2 insists on including on your classpath (like commons-logging while you want to use jcl-over-slf4j). How do you use it?
First of all: if you were using no-commons-logging before, you do not need to change anything! Version 99 Does Not Exist is fully backward compatible with no-commons-logging. Otherwise, read on. In your pom.xml declare the following 2 things: 1) the Version 99 Does Not Exist repository, and 2) for each jar that you get but do not want, declare a dependency with version 99.0-does-not-exist. So, for example, if you do not want to be bothered with commons-logging, include the following in your pom.xml:
<repositories> <repository> <id>Version99</id> <name>Version 99 Does Not Exist Maven repository</name> <layout>default</layout> <url>http://no-commons-logging.zapto.org/mvn2</url> </repository> </repositories> <dependencies> <!-- get empty jar instead of commons-logging --> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>99.0-does-not-exist</version> </dependency> </dependencies>
Version 99 Does Not Exist is implemented in a single file as a Camping application. Where is the code?
If you want to run it yourself you'll need the following: Version 99 Does Not Exist download (rb file, 4Kb, MIT license), Ruby, Ruby Gems and Camping. Version 99 Does Not Exist is started with a simple camping version99.rb. Good camping! Update 2007-11-06: The empty jar is no longer completely empty as 'mvn site' fails on it. Thanks to Stefan Fußenegger for the report. Update 2007-12-14: The repository was off line for a day or so because I goofed while switching internet provider. Now, it is not only working again, but reachability is better then ever: 10 Mbit/s up and down! Update 2008-02-09: Version 1.2: another update to the empty jar. Sasha Ovsankin reported that the compiler could not open it. The jar now contains a valid manifest. Thanks Sacha! Update 2009-05-01: During my move from Amsterdam to Haarlem the server has been off line for a day or so. I am now on ADSL so my internet connection is a lot slower. If anyone want to run a mirror, I am happy to set up a rotating DNS. Update 2009-07-24: Version 1.3: artifacts with a groupid that contain a dot are now supported. Éric Vigeant, thanks for the bug report! Update 2009-10-17: Version 2.0: Éric Vigeant's problems were still not over. Now removed metadata support, this will hopefully make some proxies behave better. Update 2011-08-15: DNS for Version 99 is offline. Update 2011-12-19: I just found an alternative with almost the same name: version99.qos.ch. It is a static maven repository with a limited number of version 99 jars. Update 2019-11-15: Fixed link to original Camping appliction. The Camping links now point to wikipedia.
Wow, cool! For something like this camping seems to be really useful. Seems like te right tool for the right job!
ReplyDeleteI probably miss something but isn't
ReplyDelete<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl104-over-slf4j</artifactId>
<scope>runtime</scope>
</dependency>
exactly what you want?
@joern: Thanks Joern. After many days of plain misunderstanding and struggling with maven bugs(?) I gave up and wrote this workaround.
ReplyDeleteBut I'll try your suggestion next week.
@joern: Actually your solution is different!
ReplyDeleteThe "provided" scope makes sure commons-logging is not put in the distribution; but commons-logging classes will still be on the classpath at compiletime or when running tests which might not be what you want!
Ah! Thanks Peter. Indeed you are right. I had forgotten already. That probably illustrates that Maven is a tad too difficult, or put otherwise: Maven is only suitable for people with very large brains, or yet another way: its for people that do not have much else to do :)
ReplyDeleteHey thanks for your effort here! I just your little repository and figured one thing out: if you are working with ranges like
ReplyDelete<dependency>
<groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId>
<version>[5.0,)</version>
</dependency>
you are screwed, as maven will add mysql-connector-java-99.0-does-not-exist to the classpath. everybody using your hack should consider this!
Another thing: I also get this when running `mvn site`:
error: error reading repo\commons-logging\commons-logging\99.0-does-not-exis
t\commons-logging-99.0-does-not-exist.jar; error in opening zip file
I don't know which task fails and I don't have to much time for fiddling around with maven right now, but I guess it is expecting some files in the jar files and throws an exception as the jar/zip is empty. Probably adding a simple README to the file would make this plugin (and maybe others) happy.
Regards, Stefan
the task that fails with commons-logging-99.0-does-not-exist is compiler:testCompile. I added a README to the jar file and everything works fine again ... so I guess I have too much time ;)
ReplyDeleteThanks Stefan! I'll add a readme to the jar as soon as possible.
ReplyDeleteAbout the open ended versions: I would never like to work that way, far to risky! But in a way, all software will eventually be obsolete, so it makes sense ;)
hi erik,
ReplyDeleteisn't it kind of frustrating to think that all software that you write will be obsolete in the end ;)
I like working with open ranges in a very early development/prototype stage ... and I just like to live on the edge ;)
In deed, I agree that using open ranges is too dangerous. Tough I'd use versions like [1.2.3,1.3) or [1.2.3,2.0) in order to get the latest bugfixes etc.
I just forgot to close one of those ranges and ended up with a useless mysql connector. Therefore I wanted to drop a (short?) note for everybody.
Ha! It is no less frustrating then the end of life itself! ;)
ReplyDeleteThanks for the note though.
hi erik,
ReplyDeletei just came back to see if you patched the file and i've seen that you did today ... thanks a lot!
regards, stefan
Hi Erik,
ReplyDeleteThanks for the great hack. For some reason, it didn't work in my build because the compiler would reject the JAR file. Here is the link to a file that works for me:
http://www.codebistro.com/commons-logging-99.0-does-not-exist.jar
Thanks,
-- Sasha
Hi, could you please do the same for commons-logging-api module? Thanks.
ReplyDeleteBigs ups man. You a medal.
ReplyDeleteVery useful!
ReplyDeleteI've hit on another use case that the repository does not cover yet. If the group id has more than one folder, this repository does not work.
I need:
org.apache.commons:
com.springsource.org.apache.commons.logging:
99.0-does-not-exist
Thanks again for facilitating SLF4J.
Thanks Éric! Fixed in version 1.3.
ReplyDeleteWOW, very fast turnaround!
ReplyDeleteThanks, this solved my original problem.
However (maybe due to the fix I asked), I now run into another problem with maven plugins.
I'm using Nexus as a mirror for everything including pluginRepository. However, I cannot add the 99-does-not-exist repository in that list because all plugins stop working.
This is due to the maven-metadata.xml files which list version 99-does-not-exist. Are those absolutely necessary with maven2?
I'm assuming somebody needed them, since you are generating them.
I was wondering if it was possible to have a version of the repository without the metadata files (EX: http://no-commons-logging.zapto.org/mvn2-no-metadata/...)
Thanks for the great (and quick) work!
Hi Erik, thanks a lot. But today -after some time out on development- I can no longer use mvn site:site if your repo is in my pom.xml. I got the following error by maven: "[INFO] The skin does not exist: Unable to determine the release version
ReplyDeleteTry downloading the file manually from the project website.
Then, install it using the command:
mvn install:install-file -DgroupId=org.apache.maven.skins -DartifactId=maven-default-skin -Dversion=RELEASE -Dpackaging=jar -Dfile=/path/to/file
Alternatively, if you host your own repository you can deploy the file there:
mvn deploy:deploy-file -DgroupId=org.apache.maven.skins -DartifactId=maven-default-skin -Dversion=RELEASE -Dpackaging=jar -Dfile=/path/to/file -Durl=[url] -DrepositoryId=[id]
org.apache.maven.skins:maven-default-skin:jar:RELEASE"
Hey! I selected Name/URL - not Anonymous! Anyway... Now with Google Account...
ReplyDeleteStefan
Been using this method successfully for a while, but started getting the following today:
ReplyDeleteCouldn't find a version in [99.0-does-not-exist] to match range [1.5.0,2)
org.slf4j:log4j-over-slf4j:jar:null
Anyone else having this problem?
Hey Erik, any comments on the two errors form me an Thom?
ReplyDeleteStefan, I have no idea what that means.
ReplyDeleteThom, you should also include some other 'real' repositories i your repository list.
Hi Erik, I think the problem mentioned all come from what I described in my earlier comment.
ReplyDeleteWhen Maven checks for newer versions of plugin (or for dependencies with open-ended version intervals) it asks the repositories the version numbers.
Since your repository always returns that there is a version 99, it is always the one selected, but then the jar is empty...
This problem probably occurs since the fix you made to accomodate jars with dots in the groupID. (Sorry I was the one who requested this fix...)
Is there a way to return that your repository contains a version 99 only when it is requested explicitely... (I don't know the maven protocol...)
Released 2.0 with removed support for metadata. Please let me know if it works.
ReplyDeleteI may be missing something, but isn't it much easier to simply exclude the nested dependency, as in:
ReplyDeleteorg.hibernate
hibernate
3.2.6.ga
commons-logging
commons-logging
This even works with dependencyManagement!
Regards
Walter
sorry... have to escape the > and < ;/
ReplyDelete<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.2.6.ga</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
Walter, when you declare an exclusion like that, you exclude commons-logging only for hibernate. So to get this right, you must follow all your dependencies, and all their dependencies, and their dependencies, etc. Each dependency that declares commons-logging must then be listed in your pom.
ReplyDeleteIf you have ever tried this (I have) you get tired very quickly. Your poms become very large and fragile.
Erik, you are right... it may get tedious. But it has the advantage that there is less black magic involved. You can see which packages still contain that cruft... and they're getting less and less ;)
ReplyDeleteWe actually switched in a large project from 99 to exclusions.
Walter, good for you! I'll celebrate the day that version 99 is no longer needed! You're already there apparently :)
ReplyDeletehi there,
ReplyDeletestumbled opon the same troubles... however, I realized that if you declare the logback/slf4j bridge dependencies before your other dependencies in the pom.xml they will be handled first!
no need for a hack ;-)
e.g.
ch.qos.logback
logback-core
0.9.18
ch.qos.logback
logback-classic
0.9.18
org.slf4j
slf4j-api
1.5.10
org.slf4j
jcl-over-slf4j
1.5.10
org.slf4j
log4j-over-slf4j
1.5.10
some.evil.lib
using-commons-logging
...
Cheers
Hi Erik,
ReplyDeletejust wanted to tell you that everything is working great! I added back your repository in my nexus instance after you made the fix (v2.0) and I didn't have any of the plugin problems I had before.
So thank you once again for the quick fix and solution to commons-logging problem. Sorry for taking so long to give you feedback, I guess when no one complains, you can assume everything is working fine!
I am having some curious problems.
ReplyDeletehttp://stackoverflow.com/questions/5396384/dependency-mechanism-overriding-transitive-version
Gradle does this pretty nicely these days: (killer feature :) )
ReplyDeleteconfigurations {
all*.exclude group: "commons-logging"
}
And be done with it :)