My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
ThrowingProviders  
throwing providers extension tutorial
Updated Oct 16, 2011 by sberlin

Throwing Providers

Guice isn't very good at handling exceptions that occur during provision.

  • Implementers of Provider can only throw RuntimeExceptions.
  • Callers of Provider can't catch the exception they threw, because it may be wrapped in a ProvisionException.
  • Injecting an instance directly rather than a Provider can cause creation of the injected object to fail.
  • Exceptions cannot be advertised in the API.

The ThrowingProviders extension offers an alternative to Providers that allow a checked exception to be thrown.

  • API consistent with Provider.
  • Scopable
  • Standard binding DSL

ThrowingProvider (new in Guice 2.0)

Guice 2.0 offers the ThrowingProvider interface. It is similar to Provider, but with a generic Exception type:

public interface ThrowingProvider<T,E extends Exception> {
  T get() throws E;
}

For each application exception, create an interface that extends the ThrowingProvider. For our news widget application, we created the FeedProvider interface that throws a FeedUnavailableException:

public interface FeedProvider<T> extends ThrowingProvider<T, FeedUnavailableException> { }

CheckedProvider (new in Guice 3.0)

Guice 3.0 offers the CheckedProvider interface. It improves upon ThrowingProvider by allowing more than one exception type to be thrown:

public interface CheckedProvider<T> {
  T get() throws Exception;
}

For each object where providing may throw an exception, create an interface that extends the CheckedProvider. For our news widget application, we created the FeedProvider interface that throws a FeedUnavailableException and SecurityException:

public interface FeedProvider<T> extends CheckedProvider<T> {
  T get() throws FeedUnavailableException, SecurityException;
}

Binding the provider

After implementing our WorldNewsFeedProvider and SportsFeedProvider, we bind them in our module using ThrowingProviderBinder:

public static class FeedModule extends AbstractModule {
  protected void configure() {
    ThrowingProviderBinder.create(binder())
        .bind(FeedProvider.class, BbcFeed.class)
        .annotatedWith(WorldNews.class)
        .to(WorldNewsFeedProvider.class)
        .in(HourlyScoped.class);

    ThrowingProviderBinder.create(binder())
        .bind(FeedProvider.class, BbcFeed.class)
        .annotatedWith(Sports.class)
        .to(SportsFeedProvider.class)
        .in(QuarterHourlyScoped.class);
  }
}

Using @CheckedProvides (new in Guice 3.0)

You can also bind checked providers use an @Provides-like syntax: @CheckedProvides. This has all the benefits of @Provides methods, and also allows you to specify exceptions.

public static class FeedModule extends AbstractModule {
  protected void configure() {
    // create & install a module that uses the @CheckedProvides methods
    install(ThrowingProviderBinder.forModule(this)); 
  }

  @CheckedProvides(FeedProvider.class) // define what interface will provide it
  @HourlyScoped // scoping annotation
  @WorldNews // binding annotation
  BbcFeed provideWorld(FeedFactory factory)
      throws FeedUnavailableException, SecurityException {
    return factory.tryToFeed("bbc"); // may throw an exception
  }

  @CheckedProvides(FeedProvider.class) // define what interface will provide it
  @QuarterlyHourlyScoped // scoping annotation
  @Sports // binding annotation
  BbcFeed provideSports(FeedFactory factory)
      throws FeedUnavailableException, SecurityException {
    return factory.tryToFeed("bbc"); // may throw an exception
  }

Injecting the provider

Finally, we can inject the FeedProviders throughout our application code. Whenever we call get(), the compiler reminds us to handle the FeedUnavailableException and any other exceptions declared in the interface:

public class BbcNewsWidget {
  private final FeedProvider<BbcFeed> worldNewsFeedProvider;
  private final FeedProvider<BbcFeed> sportsFeedProvider;

  @Inject
  public BbcNewsWidget(
      @WorldNews FeedProvider<BbcFeed> worldNewsFeedProvider,
      @Sports FeedProvider<BbcFeed> sportsFeedProvider) {
    this.worldNewsFeedProvider = worldNewsFeedProvider;
    this.sportsFeedProvider = sportsFeedProvider;
  }

  public GxpClosure render() {
    try {
      BbcFeed bbcWorldNews = worldNewsFeedProvider.get();
      BbcFeed bbcSports = sportsFeedProvider.get();
      return NewsWidgetBody.getGxpClosure(bbcWorldNews, bbcSports);
    } catch (FeedUnavailableException e) {
      return UnavailableWidgetBody.getGxpClosure();
    }
  }
}

Notes on Scoping

Scopes work the same way they do with Providers. Each time get() is called, the returned object will be scoped appropriately. Exceptions are also scoped. For example, when worldNewsFeedProvider.get() throws an exception, the same exception instance will be thrown for all callers within the scope.

Comment by kashie...@gmail.com, Jan 24, 2010

Hi, "After implementing our WordlNewsFeedProvider? and SportsFeedProvider?". It is not clear how to implement "WordlNewsFeedProvider?" and "SportsFeedProvider?". Should they implement "Provider" interface or "FeedProvider?", and what is "BbcFeed?.class"? can you please attach the complete example code? Thanks, Erez

Comment by miroslav...@gmail.com, Mar 28, 2011

@kashie, there is no source, they are made up examples.

Comment by grave.co...@gmail.com, Apr 20, 2011

Hi, Is provider inject the only way to use throwing exception extension? is there any way likes toProvider()?

Comment by laola...@gmail.com, Jul 29, 2011

Hi,

I am trying to use the CheckedProvider? with the instructions in this page. I think what is missing in the page is how the WorldNewsFeedProvider? and SportsFeedProvider? are implemented? (As mentioned by kashie above.) Really appreciate if the missing part can be filled in, which can be a great help for any new comers.

Thanks

Comment by jonasloe...@gmail.com, Aug 30, 2011

Hi, right now it's not clear how a Throwing Provider works. I'm also missing a complete example. Especially because there is no JavaDoc?-comment for the methode bind()(http://google-guice.googlecode.com/svn/tags/3.0/javadoc/com/google/inject/throwingproviders/ThrowingProviderBinder.html#bind(java.lang.Class<P>, java.lang.reflect.Type)). Having a meaningful JavaDoc? in the near future would be great!

Thanks

Comment by marcin.l...@gmail.com, Nov 15, 2011

Could somebody provide a FULL working source for CheckedProviders?, because I can't make it work with those examples unfortunately... I'm not sure it's a bug or if I'm doing something wrong. Thanks.


Sign in to add a comment
Powered by Google Project Hosting