ThrowingProvider
Guiceは(プロバイダによる)インスタンス生成中の例外をうまくハンドリングできない。
プロバイダ実装はRuntimeExceptionのみを投げることが可能である(訳注:チェック例外は利用できない)。
プロバイダの呼び出し側は、それが投げる例外をキャッチすることができない。なぜなら、それらはProvisionExceptionによってラップされているからである。
- プロバイダを利用せず、インスタンスに直接注入しようとすると、そのインスタンスの生成に失敗する可能性がある。
- Exceptions cannot be advertised in the API.
ThrowingProvidersはプロバイダの代替であり、チェック例外を投げることができる。
- API consistent with Provider.
- Scopable
- Standard binding DSL
ThrowingProviderインターフェースはProviderと同様であるが、一般例外タイプを持つ。
public interface ThrowingProvider<T,E extends Exception> { T get() throws E; }
それぞれのアプリケーション例外について、ThrowingProviderを拡張するインターフェースを作成するとよい。 我々のニュースウィジェットアプリケーションではFeedUnavailableExceptionを投げるFeedProviderを作成した。
public interface FeedProvider<T> extends ThrowingProvider<T, FeedUnavailableException> { }
WordlNewsFeedProviderとSportsFeedProviderの実装を作成し、それらをモジュール内にて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); } }
最後にFeedProviderをアプリケーション全体に渡って注入する。 そのget()呼び出しではいつでもFeedUnavailableExceptionをハンドリングすべきことをコンパイラが教えてくれる。
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(); } } }
スコーピングに関するノート
スコープもプロバイダに関して同じように動作する。 get()が呼び出されるときには、返されたオブジェクトは適切にスコープされる。 例外も同じくスコープされる。 例えば、worldNewsFeedProvider.get()が例外を投げると、その同じ例外がスコープ内のすべての呼び出し側に返される。