[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openjdk-jigsaw-dev
Subject:    Modular services with OpenJDK Jigsaw and Guice
From:       paul.sandoz () oracle ! com (Paul Sandoz)
Date:       2012-07-11 8:49:09
Message-ID: 46556F11-344E-4712-A111-2875E77070D7 () oracle ! com
[Download RAW message or body]

Hi Tim,

Just to be clear on the approach i was experimenting with.

I was not trying to shoe horn service discovery into Guice. 

Rather i was using Guice for explicit binding of service interfaces and using the \
ServiceLoader mechanism to bootstrap access to Injector instances provided by \
modules. 

The bindings of the Injector instances are introspected to find all keys for the type \
literal that is the service interface. From those keys service instances are obtained \
from the corresponding Injector.

Using Guice this way provides a richer way to bind and scope service interfaces than \
is capable with ServiceLoader (in classpath or module mode) at the expense of having \
to explicitly declare the binding (which is currently also required in module mode \
for services), and the resolver is blind to what service interfaces are bound.

I anticipated there would be one Guice Module/Injector per Java module for such \
Guice-based service lookup.

I am sure it is possible to improve on this with tighter integration with the module \
system, especially the resolver if there were richer ways to signal the binding of \
service interfaces.

Paul.

On Jul 10, 2012, at 7:54 PM, Tim Boudreau wrote:

> 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
> 


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic