-
Notifications
You must be signed in to change notification settings - Fork 1.7k
ERROR_IN_CUSTOM_PROVIDER
Guice will throw a ProvisionException
with an ERROR_IN_CUSTOM_PROVIDER
error
code when a
provider in
Guice throws a runtime exception.
Example:
final class FooModule extends AbstractModule {
@Override
protected void configure() {
bind(Bar.class).toProvider(BarProvider.class);
}
@Provides
Foo provideFoo(Bar bar) {
// An ERROR_IN_CUSTOM_PROVIDER error will be reported if this precondition
// check fails.
Preconditions.checkState(bar.hasFoo());
return bar.getFoo();
}
}
final class BarProvider implements Provider<Bar> {
@Override
public Bar get() {
// An ERROR_IN_CUSTOM_PROVIDER error will be reported if this method
// throws an exception
...
}
}
ERROR_IN_CUSTOM_PROVIDER
error occurs when Guice calls application code (e.g a
@Provides
method) to create an object and that code throws an exception. To
fix the error, examine and address the associated underlying cause of the error
(the cause of the ProvisionException
) so that Guice can successfully create
the required objects. For example, you can handle the exception by catching it
and return a fallback object instead of letting Guice handle the exception.
Sometimes it is reasonable to have some ERROR_IN_CUSTOM_PROVIDER
errors if
those errors are caused by exceptions that are expected to occur at runtime. For
example, a binding that is derived from user input can fail if the input is
invalid. However, to make the root cause of the exception clearer, you should
consider throwing the exception before or after triggering Guice provisioning so
that the root cause exception is not wrapped inside a ProvisionException
.
Examples:
final class FooModule extends AbstractModule {
@Provides
Foo provideFoo(FooRequest request) {
// FooFactory throws an exception if request is invalid. The exception will
// cause Guice to throw a ProvisionException with an
// ERROR_IN_CUSTOM_PROVIDER error, which may obscure the root cause of the
// exception.
return FooFactory.create(request);
}
}
final class RequestHandler {
private final Provider<Foo> fooProvider;
@Inject RequestHandler(Provider<Foo> fooProvider) {
this.fooProvider = fooProvider;
}
public FooResponse handleRequest() {
// Guice will throw a ProvisionException if request is invalid.
return handleFoo(fooProvider.get());
}
}
Validate input before Guice provisioning
final class RequestHandler {
private final Provider<Foo> fooProvider;
@Inject RequestHandler(Provider<Foo> fooProvider) {
this.fooProvider = fooProvider;
}
public FooResponse handleRequest(FooRequest request) {
// Validate the request and throw BadRequestException if request has invalid
// input, so the call to fooProvider.get() is guaranteed to succeed.
if (!isValid(request)) {
throw new BadRequestException("invalid request");
}
Foo foo = fooProvider.get();
return handleFoo(foo);
}
}
final class FooModule extends AbstractModule {
@Provides
Foo provideFoo(FooRequest request) {
// Since request is validated before provideFoo is called, FooFactory.create
// will not throw an exception.
return FooFactory.create(request);
}
}
Alternatively, perform the validation after Guice provisioning
final class FooModule extends AbstractModule {
@Provides
Foo provideFoo(FooRequest request) {
// FooFactory never throws exception and request validation is deferred
// until Foo.isValid is called.
return FooFactory.create(request);
}
}
final class RequestHandler {
private final Provider<Foo> fooProvider;
@Inject
RequestHandler(Provider<Foo> fooProvider) {
this.fooProvider = fooProvider;
}
public FooResponse handleRequest(FooRequest request) {
Foo foo = fooProvider.get();
// fooProvider never throws exception but can return Foo instances that
// returns false when isValid is called.
if (!foo.isValid()) {
throw new BadRequestException("invalid request");
}
return handleFoo(foo);
}
}
-
User's Guide
-
Integration
-
Extensions
-
Internals
-
Releases
-
Community