Atom Feed SITE FEED   ADD TO GOOGLE READER

Future Guice: Providers that throw unchecked exceptions

As previously mentioned, I'm cataloging Guice's changes since 1.0.

Suppose you have a provider that throws an unchecked exception:
class PhaseOfTheMoonProvider implements Provider<PhaseOfTheMoon> {
@Inject Observatory observatory;

public PhaseOfTheMoon get() {
if (observatory.isNighttime()) {
return observatory.getCurrentPhase();
}

throw new IllegalStateException("Can't see the moon unless it's nighttime.");
}
}

For the most part, unchecked exceptions are useful for validating pre- and postconditions. But a problem arises when code attempts to catch the specific exception thrown by a provider. Suppose this is our calling code:
  @Inject Provider<PhaseOfTheMoon> phaseOfTheMoonProvider;

public boolean isFullMoon() {
try {
PhaseOfTheMoon phaseOfTheMoon = phaseOfTheMoonProvider.get();
return phaseOfTheMoon == PhaseOfTheMoon.FULL;
} catch (IllegalStateException e) {
return false;
}
}

This code works, but it's prone to regress as the provider code is maintained. For example, if the provider code is changed to throw NoMoonlightException, our application breaks without any notice from the compiler. And should other unchecked exceptions be thrown, the only way to reliably handle them is to suffix all provider access with an ugly catch (RuntimeException e) block.

Enter ProvisionException


To simplify this situation, recent snapshots of Guice make ProvisionException public, and guarantee that that will be the only exception type thrown by injected providers. Client code only needs to catch ProvisionException in order to recover from a failed provider.

To implement this, Guice wraps user-supplied providers and performs exception-chaining to rethrow arbitrary exceptions as ProvisionException. It embeds contextual information in the provision exception, which simplifies diagnosing problems with indirectly-injected values.

The new client code can catch ProvisionException instead. This code will continue to work, even if the Provider<PhaseOfTheMoonProvider> changes its thrown types:
  public boolean isFullMoon() {
try {
PhaseOfTheMoon phaseOfTheMoon = phaseOfTheMoonProvider.get();
return phaseOfTheMoon == PhaseOfTheMoon.FULL;
} catch (ProvisionException e) {
return false;
}
}

This is the Guice change that I'm most anxious about. It's makes a nontrivial change in Guice's behaviour in an area that is least likely to have test coverage - the exceptional case. How good are your unit tests?

PS - for checked exceptions, look at the throwing providers extension.

Glazed Lists talk at JavaOne: Friday at 2:50pm

Details on this year's Glazed Lists tech session:
Simply Sweet Applications with Glazed Lists
Ken Orr, The MathWorks
Session TS-6047
Friday May 9 at 14:50, Hall E 135


From Ken's Abstract,
Glazed Lists fosters data-centric design, which promotes decoupling of components and increases the testability of your code. This lets developers envision their data infrastructure as a data fabric, which is a fantastic abstraction. List pipelining is where the real power of Glazed Lists shines.


I've committed to hang around Google's booth on Tuesday. I'll be there from 11:30 to 12:30, plus 1:30 to 2:30 if you'd like to drop by and say hi.

Guice Multibinder API proposal

Multibindings is an idea to allow multiple independent modules to contribute elements to a collection. There's lots of proposed APIs to add multibindings to Guice.

Unlike almost all of the existing proposals, this strategy can be used to add multibindings as an extension to Guice. Therefore we don't increase the complexity of the existing Binder API in the much more common non-multibinding case. The API:
public class Multibinder<T> {

/**
* Returns a new multibinder that collects instances of {@code type} in a list.
*/
static <T> Multibinder<T> newListBinder(Binder binder, Class<T> type);

/**
* Returns a new multibinder that collects instances of {@code type} in a set.
*/
static <T> Multibinder<T> newSetBinder(Binder binder, Class<T> type);

/**
* Build a new element in the bound collection.
*/
AnnotatedBindingBuilder<T> addBinding();
}

... and here's what the client code would look like:
  public static void testMultibinder() {
AbstractModule stanCartmanKennyModule = new AbstractModule() {
protected void configure() {
Multibinder<String> stringBinder
= Multibinder.newSetBinder(binder(), String.class);

stringBinder.addBinding().toInstance("Stan");
stringBinder.addBinding().annotatedWith(Names.named("Fatass")).toInstance("Cartman");
stringBinder.addBinding().toProvider(new Provider<String>() {
public String get() {
return "Kenny";
}
});
}
};

AbstractModule kyleModule = new AbstractModule() {
protected void configure() {
Multibinder.newSetBinder(binder(), String.class)
.addBinding().toInstance("Kyle");
}
};

Injector injector = Guice.createInjector(stanCartmanKennyModule, kyleModule);

Set<String> boys = injector.getInstance(Key.get(new TypeLiteral<Set<String>>() {}));
assertEquals(Sets.newHashSet("Stan", "Cartman", "Kenny", "Kyle"), boys);
assertEquals("Cartman", Key.get(String.class, Names.named("Fatass"));
}

Note that I've simplified the code above by omitting some details (annotating the collections, binding collections of parameterized types).

I think this API is both compact and convenient. What's your favourite multibinding API?

Future Guice: injecting inner classes

As previously mentioned, I'm cataloging the differences in Guice since 1.0.

This test passes in Guice 1.0, but how it does so is surprising:
public class InjectTest extends TestCase {
public void testFoo() {
Foo foo = Guice.createInjector().getInstance(InnerFoo.class)
}

class InnerFoo implements Foo {
@Inject InnerFoo() {}
}
}

The problem is that the InnerFoo inner class is not marked static. Therefore each instance of InnerFoo has an implicit, invisible reference to its containing class, InjectTest. When it creates an instance of InnerFoo, Guice 1.0 will also build a new InjectTest, using its default constructor. This is weird! The outer-class instance is only reachable via the implicit reference, which is awkward and unexpected.

The latest snapshots of Guice refuse to construct non-static inner classes. This will help to find bugs! And for the rare situation where non-static is desired, Providers can be used. Plus they make the choice of containing instance explicit.

Future Guice: More aggressive error detection

For the past month, I've been cataloging the various changes since Bob & Kevin released version 1.0 back in March 2007. For a 1.0, it's held up remarkably well. We've been using it on my team without many problems and we've quite enjoyed it.

Good News!


Guice has improved since 1.0. There's new features, bugfixes, performance improvements and tools for Guice users to enjoy.

Bad News


The latest snapshosts of Guice are not 100% backwards-compatible with version 1.0. For example, Guice had a bug where it quietly ignored some bindings that it couldn't fulfill. This test case gives a false-positive result: it succeeds even though there's no binding for interface A:
  public void testBindProvidersOrder() {
Injector injector = Guice.createInjector(new AbstractModule() {
protected void configure() {
bind(String.class).toProvider(new Provider<String>() {
@Inject A a;

public String get() {
return "hello world";
}
});
}
});

assertEquals("hello world", injector.getInstance(String.class));
}

Today's Guice is better - when this test runs it prints an error at Injector-creation time:
com.google.inject.CreationException: Guice configuration errors:

1) Error at com.google.inject.BinderOrderTest$1$1.a(BinderOrderTest.java:31):
Binding to com.google.inject.BinderOrderTest$A not found. No bindings to that type were found.

1 error[s]
at com.google.inject.InjectorBuilder$ConfigurationErrorHandler.blowUpIfErrorsExist(InjectorBuilder.java:281)
at com.google.inject.InjectorBuilder.validate(InjectorBuilder.java:181)
at com.google.inject.Guice.createInjector(Guice.java:59)
at com.google.inject.BinderOrderTest.testBindProvidersOrder(BinderOrderTest.java:26)

This particular problem is easy to recognize and fix. It's a net win, even though it breaks backwards-compatibility. There's more similar changes, and I intend to post about them in the coming weeks...

Quine Programs in Java

Michael Kölling blogged about Quines - programs that print themselves. Here's my best effort in Java (prettyprinted for readability):
class A {
static {
String a="class A{static{String a=%s%s%1$s;System.out.printf(a,'%1$s',a);}}";
System.out.printf(a,'"',a);
}
}

Can you beat 122 characters?

Amazon MP3 works good

I just bought the new Panic At The Disco album on Amazon MP3. It was easy! And I don't have the DRM-guilt that I usually get whenever I buy stuff from iTunes. The price is right, the quality is high, and I don't have to do the Deregister Computer bullshit if I change my laptop. Hooray!

I don't think I'll be going back to the iTunes store for music.

Don't do this: Share names

The following program is valid Java, even though the Runnable on line 1 is a completely different symbol than Runnable on line 3:
public class Refrigerator implements Runnable {
public void run() {
new Runnable().freeze();
}

public class Runnable {
void freeze() {
System.out.println("cold and refreshing");
}
}

public static void main(String[] args) {
new Thread(new Refrigerator()).start();
}
}
I'm not quite sure if this is shadowing, obscuring or hiding, but it's certainly not good. Writing a compiler must be pretty difficult!