Modular services with OpenJDK Jigsaw and Guice

Tim Boudreau niftiness at gmail.com
Tue Jul 10 10:54:13 PDT 2012


On Tue, Jul 10, 2012 at 4:38 AM, Paul Sandoz <paul.sandoz at oracle.com> wrote:

> Sisu provides extensions to Guice to avoid the need to explicitly bind:
>
>   http://www.eclipse.org/sisu/
>
> but i dunno if that can do what you want.
>
> FWIW i have a preference for explicit bindings, it seems to fit well with
> the idea of a module declaration expressing it's interface to consumers.
>

Yeah, I've done the classpath scanning thing too.  It's a bit brute-force
and ugly, though.  It does give you an additional sanity check on startup -
if a class couldn't actually resolve its dependencies or threw an exception
in a static initializer, you find that out immediately on startup.  When I
did this, I would just, say, look up all non-abstract subtypes of some
interface which did not have my @Invisible annotation.

But I don't think it's worth it - I'd rather use a mechanism like Lookup,
or if I need more metadata, write an annotation processor that writes a
file into the classpath, and then provide a module that finds and reads all
such files, loads classes and binds them.  Forcing loading every class the
VM can see is overkill - and it should be a clear indication to anybody
doing it that they're trying to fit a square peg in a round hole.

The thing we're really touching on here is that Service Discovery !=
Dependency Injection, and sometimes you need both.  Trying to shoehorn
generic service discovery into Guice doesn't seem like a fabulous idea -
it's simply not for that.  If you've gotta, gotta, gotta do that, an
annotation processor and some mechanism like META-INF/services files will
work (ideally with richer metainfo than just a class name).

But Guice injection is entirely based around Key[1] - which really just
wraps up a type, generic RTTI and optional annotations;  when it tries to
inject a constructor parameter, it is constructing a Key for that parameter
and then comparing it with the keys that the injector knows about.  So
injection is not polymorphic unless you tell Guice it is - I can call
Lookup.lookup(Object.class) and I'll get something or other;  if I @Inject
Object, it's an error unless something told Guice to bind Object somehow -
it will not guess for me (I had to learn this the hard way a few years ago,
since I was used to Lookup [2]).

One of my favorite things about Guice (as opposed to, say, Spring) is that
it is tightly focused on exactly one very specific problem it's there to
solve.  It isn't a service discovery library, it's a
separate-your-configuration-from-your-business-logic library.  Probably
things that try to abuse Guice to be a service-discovery/auto-wiring
platform should not be encouraged, and some simple, clean mechanism like
Lookup should be fulfilling that role - with an easy way to wrap a Guice
Provider around that mechanism *for specific types*.

Auto-wiring is useful and good (but commonly you need a way to override or
turn pieces of it off in a test environment, and that aspect is usually
implemented as an afterthought or hack when somebody tries to write a test
and something explodes  - Jarda, how many subclasses are there of
Repository in older unit tests for NetBeans that don't directly use
FileSystem?).  It's good to have the mechanism be configurable and
optionally able to be initialized by running code on startup (to solve the
test environment problem).  But it's really a different problem than Guice
solves - it's just that the shape of the solution is deceptively similar.

Orthagonal to all of this is the desire not to load classes on startup.
 That's an optimization.  One that's critical for desktop applications, and
uninteresting or even harmful for server-side applications (if the process
is going to run for months, I care much more about it failing quickly if
it's broken than I do about startup time).  So probably any service
discovery mechanism should be *able* to be completely declarative, but that
should not be the only way to initialize things.

-Tim

[1]
http://google-guice.googlecode.com/git/javadoc/com/google/inject/Key.html
[2]
https://groups.google.com/forum/?fromgroups#!topic/google-guice/wyA1ZijITZU



More information about the jigsaw-dev mailing list