Yup, for our internals we actually have a two-pronged approach where we try to eagerly validate whatever we can (using getAllBindings) at startup, and then continue to monitor for any stragglers using a ProvisionListener.
sam On Wed, Nov 25, 2015, 8:38 PM Tavian Barnes <[email protected]> wrote: > Ah, that's another approach to http://stackoverflow.com/q/18474368/502399 > :) > > On Wednesday, 25 November 2015 17:54:13 UTC-5, Sam Berlin wrote: > >> You can write your own analysis using the SPI and fail eagerly. This >> will work only if users don't inject the Injector. We do this internally >> for singletons to ensure that only other singletons or unscoped things (or >> Providers) are injected into singletons. The APIs involved would be >> Binding.acceptTargetVisitor(BindingTargetVisitor), checking dependencies >> (often by casting to HasDependencies, for linked bindings getting the link, >> potentially implementing extension-specific BindingTargetVisitor >> subinterfaces), and keeping track of the path as you're recursing through >> dependencies. The starting point for visiting would be each binding in >> injector.getAllBindings().values(). (And you could keep track of what >> you've visited to short-circuit on later visits, to avoid redoing the same >> work.) >> >> sam >> >> >> >> On Wed, Nov 25, 2015 at 5:42 PM Tavian Barnes <[email protected]> wrote: >> > All the semantic information you want is thrown away very early by Guice, >>> so there's probably not a way to get the kind of details that you want. >>> The internal implementation >>> <https://github.com/google/guice/blob/master/core/src/com/google/inject/internal/Errors.java> >>> uses >>> the same Message class that you see in the ProvisionException. >>> >>> >>> On Wednesday, 25 November 2015 03:46:36 UTC-5, jwa wrote: >>>> >>>> I would like to intercept some of the exceptions being thrown by Guice, >>>> with access to the full context of the underlying error, and use >>>> domain-specific details to come up with meaningful error messages. >>>> >>>> To illustrate this problem I am using a vastly simplified domain, this >>>> may be a bit tenuous, bear with me. >>>> >>>> I provide my clients with a simplified API which allows them to >>>> build-up the event without exposing them to the fact that Guice will be >>>> used to wire everything together: >>>> >>>> AthelticsBuilder builder = new AthelticsBuilder() >>>> .withTicketIssuer(ResultRecorded.class) // <-- This is a singleton, >>>> one ticket issuer per event >>>> .withObserver(ResultRecorded.class) // <--- This is >>>> race-scoped, one created per race >>>> .addRace("100 meter sprint") >>>> .build(); >>>> >>>> Behind the scenes the AthleticsBuilder will use Guice to obtain >>>> instances of each of the classes described above. Framework-related >>>> dependencies may be injected into these classes, for example RaceObservers >>>> might want to gain access to the StopWatch that is timing the event they >>>> are responsible for observing: >>>> >>>> public class ResultRecorder implements RaceObserver { >>>> @Inject >>>> public ResultRecorder(Race race, StopWatch watch) { /* ... */ } >>>> } >>>> >>>> The injection of these race-specific dependencies is facilitated by a >>>> custom "RaceScope" which is entered/exited as the AthelticsBuilder creates >>>> each race added to the builder. >>>> >>>> It is possible for my API clients to make rather silly mistakes. For >>>> example, they might ask for a StopWatch to be injected into their >>>> TicketIssuer. This is not legal, as the TicketIssuer is a singleton, and >>>> has no access to members injected by the RaceScope. For eaxmple, if the >>>> following constructor is used: >>>> >>>> public class TicketMachine implements TicketIssuer { >>>> >>>> @Inject >>>> public TicketMachine(StopWatch watch) { /* ... */ } >>>> } >>>> >>>> Guice will throw a ProvisionException when attempting to instantiate >>>> the TicketMachine. This will have the following error: >>>> >>>> Caused by: com.google.inject.ProvisionException: Unable to provision, >>>> see the following errors: >>>> >>>> 1) Error in custom provider, com.google.inject.OutOfScopeException: >>>> Cannot access Key[type=com.acme.StopWatch, annotation=[none]] outside of a >>>> scoping block >>>> at com.acme.RaceScopeModule.configure(RaceScopeModule.java:25) >>>> while locating com.acme.StopWatch >>>> for parameter 0 at >>>> com.acme.TicketMachine.<init>(TicketMachine.java:85) >>>> while locating com.acme.TicketMachine >>>> >>>> This is rather unfortunate for two reasons: >>>> >>>> - It exposes my API clients to the fact I'm using Guice. My API >>>> completely insulates them from this, which is nice. It's only when >>>> errors >>>> are encountered that they suddenly become aware what's happening >>>> under-the-covers >>>> - The API consumer isn't likely to be able to decipher this error, >>>> and identifying the underlying issue >>>> >>>> It would be much nicer if I could intercept this exception (more likely >>>> the underlying exception) and provide something far more meaningful: >>>> "*TicketMachine >>>> cannot access com.acme.StopWatch as it does not have reference to a race* >>>> ". >>>> >>>> To be able to achieve this, I'd need to be able to intercept the exact >>>> details of the binding error. Simply catching ProvisionException is of >>>> little use to me; it just contains "Messages", which don't have any of the >>>> rich context-specific information I need to produce more meaningful errors. >>>> >>>> Is there some mechanism for handling / intercepting this errors, in >>>> order to produce more meaningful exceptions? >>>> >>>> Any pointers would be greatly appreciated. >>>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "google-guice" group. >>> >> To unsubscribe from this group and stop receiving emails from it, send an >>> email to [email protected]. >>> To post to this group, send email to [email protected]. >> >> >>> Visit this group at http://groups.google.com/group/google-guice. >>> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/google-guice/9a4d8bd2-114c-4795-b8ca-90902ab9b984%40googlegroups.com >>> <https://groups.google.com/d/msgid/google-guice/9a4d8bd2-114c-4795-b8ca-90902ab9b984%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> For more options, visit https://groups.google.com/d/optout. >>> >> -- > You received this message because you are subscribed to the Google Groups > "google-guice" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To post to this group, send email to [email protected]. > Visit this group at http://groups.google.com/group/google-guice. > To view this discussion on the web visit > https://groups.google.com/d/msgid/google-guice/d748c616-0001-4201-a170-a914b6f3bdab%40googlegroups.com > <https://groups.google.com/d/msgid/google-guice/d748c616-0001-4201-a170-a914b6f3bdab%40googlegroups.com?utm_medium=email&utm_source=footer> > . > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "google-guice" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/google-guice. To view this discussion on the web visit https://groups.google.com/d/msgid/google-guice/CAJEBNUe1c2U8Ebc133wTf0TMPjBcNPKhi8RX7La1-GVbCybxog%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.
