If library versioning in Python is bad, how would a JVM language be better? In my experience, there is no widely-used post-build-time system for declaring or checking dependencies except for OSGi, which is not spreading like wildfire as I expected it to. The Java model seems to be to bundle all your dependencies into a single deployable app, performing all dependency checking at build time and carefully isolating your app from other apps in an application container. I.e., don't even try to solve the problem of sharing libraries between applications.
Oddly enough, C has superior runtime checks (dynamic library loading using major version numbers) and install-time checks (*nix package dependencies) compared to dynamic languages. It is very, very strange to me that other language communities have neither embraced alternatives such as OSGi nor worked to transfer responsibility to native package managers such as dpkg or RPM. C et al. under Linux have set a standard that other language communities don't seem interested in matching, much less exceeding. As far as I know, the standard answer for deploying a security update to a Java library is to rebuild and redeploy the entire application that depends on it.
>> carefully isolating your app from other apps in an application container. I.e., don't even try to solve the problem of sharing libraries between applications.
I would argue that this is the most reliable solution, if you can do it.
It isn't necessarily a bad thing -- it's basically static linking -- but the way it's done, it makes administration and troubleshooting a nightmare. As a platform, Java lacks the tools that a Unix sysadmin takes for granted. For example, with Debian or Ubuntu:
What version of a library is installed, if any: dpkg -l
What's the latest version available to be installed: apt-get update, apt-cache search
Update the library for all applications that link it: apt-get upgrade
These tools are important for administration, security, and troubleshooting. It mystifies me that Java developers and sysadmins managing Java servers don't demand them. Instead, they're willing to muck around in a web interface, go back to their dev box to look at Maven scripts, or go searching through the filesystem just to see what software is installed and running. Even if you're not averse to doing that by hand, how scriptable is it?
If you have a large Java environment with many different services running on dozens or hundreds of boxes, how do you get a report of which boxes have a particular version of a library installed? I know our sysadmins don't know how, and I know our Java developers don't care. They could develop the tools themselves, but they have no interest. The sysadmins do not do web pages; they are not going to spend all day going click-click-click to update a few dozen servers. They have told the Java developers not to expect the same level of support for their applications as our C++ programmers get because Java is an unmanageable platform, and the developers don't care. I really, really do not understand why our Java programmers are not writing scripts to automate any of these basic tasks.
It seems to be a compile time only tool. Does it let you safely deploy application code separately from its dependencies? Does it let different applications share libraries when possible? Does it come with tools that let you query the version and dependencies of a deployed library and see how those dependencies are satisfied? Can you push a security fix for a library to servers in the field without completely rebuilding and redeploying every application that uses the library (if you can figure out which ones they are?)
You can create tar/jar/war files, deploy artifacts to remote mvn repositories, push to the Google App Engine or Elastic Beanstalk, etc. Deployment to generic unix servers is handled by Pallet, which integrates well with Leiningen: https://github.com/pallet/pallet-lein
> Does it let different applications share libraries when possible?
This goes strongly against the culture of the JVM for various reasons that are outside the scope of Clojure itself.
> Can you push a security fix for a library to servers in the field without completely rebuilding and redeploying every application that uses the library.
Sure, this is pretty easy to do with Swank, but the specifics are going to vary widely based on the type of deployment.
Oddly enough, C has superior runtime checks (dynamic library loading using major version numbers) and install-time checks (*nix package dependencies) compared to dynamic languages. It is very, very strange to me that other language communities have neither embraced alternatives such as OSGi nor worked to transfer responsibility to native package managers such as dpkg or RPM. C et al. under Linux have set a standard that other language communities don't seem interested in matching, much less exceeding. As far as I know, the standard answer for deploying a security update to a Java library is to rebuild and redeploy the entire application that depends on it.