PUBLIC OBJECT

Always use jarjar to package implementation dependencies

jarjar is a sweet Java packaging tool that allows you to embed one .jar file in another. But rather than just smashing the jars together in one big archive, jarjar renames the embedded .jar's classes so that they live in the main jar's namespace. For example, Guice's ProxyFactory.java file has an impressive collection of imports:

package com.google.inject;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.inject.internal.*;
import java.lang.reflect.*;
import java.util.*;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.CallbackFilter;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodProxy;
import net.sf.cglib.reflect.FastClass;
import net.sf.cglib.reflect.FastConstructor;

class ProxyFactory implements ConstructionProxyFactory {
  ...
}`</pre>
These imports include classes from [net.sf.cglib](http://cglib.sourceforge.net/) and [com.googe.common.collect](http://code.google.com/p/google-collections/). But when we package it up with jarjar, everything gets prefixed with the Guice package name: **com/google/inject**:
<pre>`     0 Thu Jan 01 22:13:36 PST 2009 META-INF/
  1726 Thu Jan 01 22:13:34 PST 2009 META-INF/MANIFEST.MF
 11357 Sun May 25 20:34:04 PDT 2008 LICENSE
   101 Sun May 25 20:34:04 PDT 2008 NOTICE
  5975 Thu Jan 01 22:13:20 PST 2009 com/google/inject/AbstractModule.class
  2466 Thu Jan 01 22:13:20 PST 2009 com/google/inject/Binder.class
   806 Thu Jan 01 22:13:20 PST 2009 com/google/inject/Binding.class
   414 Thu Jan 01 22:13:22 PST 2009 com/google/inject/BindingAnnotation.class
   ...
   136 Sun May 25 20:34:04 PDT 2008 com/google/inject/internal/cglib/proxy/Callback.class
   238 Sun May 25 20:34:04 PDT 2008 com/google/inject/internal/cglib/proxy/CallbackFilter.class
 28315 Sun May 25 20:34:04 PDT 2008 com/google/inject/internal/cglib/proxy/Enhancer.class
  5712 Sun May 25 20:34:04 PDT 2008 com/google/inject/internal/cglib/proxy/MethodProxy.class
  5535 Sun May 25 20:34:04 PDT 2008 com/google/inject/internal/cglib/reflect/FastClass.class
  1642 Sun May 25 20:34:04 PDT 2008 com/google/inject/internal/cglib/reflect/FastConstructor.class
  ...
  8144 Sat Nov 29 14:11:22 PST 2008 com/google/inject/internal/collect/ImmutableList.class
  9826 Sat Nov 29 14:11:26 PST 2008 com/google/inject/internal/collect/ImmutableMap.class
  6026 Sat Nov 29 14:11:24 PST 2008 com/google/inject/internal/collect/Lists.class
 12551 Sat Nov 29 14:11:26 PST 2008 com/google/inject/internal/collect/Maps.class

By using jarjar, Guice encapsulates these library dependencies. This is fantastic! Many problems are avoided by encapsulating the library dependency:

  • Guice users don't need to tell their classpath, IDE or build.xml files about cglib or Google Collections.
  • Other versions of the libraries won't conflict with the Guice version. We can ship one binary and support users of either extremely old or extremely new versions of cglib. Even if cglib broke compatibility every release (it doesn't), we aren't impacted.
  • We can freely change our own libraries. Should we add a dependency on paranamer in a future release, our users don't need to reconfigure their build scripts.
  • Most importantly, we can patch the libraries to fit our needs. If we want a special build of google-collections that includes our own hacks and tweaks, that's just fine. Our build doesn't even need to be compatible with the public version.

Standard jars for API dependencies

Guice's dependency on aopalliance doesn't use jarjar. Guice users implement the aopalliance interfaces, so the version independence and encapsulation offered by jarjar doesn't make much sense.