Novice here trying to use a dummy Java Facebook app that uses Guice to inject a database dependency into the Facebook factory but continue to have Guice error out telling me:
### No implementation for com.example.storage.Db annotated with #com.example.storage.annotations.SystemDb() was bound while locating com.example.storage.Db annotated with #com.example.storage.annotations.SystemDb() for parameter 0 at com.example.facebook.client.exceptions.FacebookExceptionHandlerDb at com.example.facebook.client.guice.FacebookClientModule.configure
### Could not find a suitable constructor in com.example.facebook.statsd.StatsdClient. Classes must have either one (and only one) constructor annotated with #Inject or a zero-argument constructor that is not private. at com.example.facebook.statsd.StatsdClient.class while locating com.example.facebook.statsd.StatsdClient for parameter 1 at com.example.facebook.client.exceptions.FacebookExceptionHandlerDb. com.example.facebook.client.guice.FacebookClientModule.configure
Code for app:
app.java
package com.example.facebook;
import com.google.inject.Guice;
import com.restfb.Connection;
import com.restfb.types.Post;
import com.example.facebook.client.FacebookClientFactory;
import com.example.facebook.client.RobustFacebookClient;
import com.example.facebook.client.guice.FacebookClientModule;
import com.example.facebook.statsd.StatsdClient;
public class App {
public static void main ( String[] args ) {
final FacebookClientFactory facebookClientFactory =
Guice.createInjector(new FacebookClientModule()).getInstance(FacebookClientFactory.class);
//error from line above
final RobustFacebookClient robustFacebookClient =
facebookClientFactory.create("accessToken");
//more ...
}
The resulting error points me to the FacebookClientModule binding:
FacebookClientModule.java
public class FacebookClientModule extends AbstractModule {
bind(FacebookExceptionHandler.class).to(FacebookExceptionHandlerDb.class);
//error resulting from the failed binding on the FacebookExceptionHandlerDB class
install(new FactoryModuleBuilder()
.implement(FacebookClient.class, RobustFacebookClient.class)
.build(FacebookClientFactory.class));
}
}
Where inside the FacebookExceptionHandleDB class the constructor has the injection:
FacebookExceptionHandlerDB.java
public class FacebookExceptionHandlerDb implements FacebookExceptionHandler {
// list of class String variables ...
private final FacebookErrorParser parser;
private final Db db;
private StatsdClient statsd;
#Inject
public FacebookExceptionHandlerDb(#SystemDb Db db, StatsdClient statsd, FacebookErrorParser parser) {
this.db = db;
this.statsd = statsd;
this.parser = parser;
}
}
From what I can gleam, the dependency injection for parameters zero and one, db and statsD respectively, is failing. Could someone point out where or what in the app code is missing?
At first glance it seems like your missing the bindings for the Db annotated dependency and the StatsdClient.
You'll need to provide the missing bindings to your module like so
bind(Db.class).annotatedWith(SystemDb.class).to(DbImplOfSomeSort.class);
bind(StatsdClient.class).to(StatsdClientImplOfSomeSort.class);
Guice is able to automatically inject Concrete Class with either a public no argument constructor or a constructor with #Inject without any specific defined binding in your module but when it comes to Interfaces you have to define the necessary bindings.
Here Db.class and StatsdClient.class are interfaces which you need to bind to specific implementation.
Not the source of the issue in this particular case, but I ran across this issue when I had my implementation and interface classes backwards:
public class MyModule extends AbstractModule {
#Override
public void configure() {
bind(MyClassImpl.class).to(MyInterface.class);
}
}
Should have been:
bind(MyInterface.class).to(MyClassImpl.class);
Related
I've got an abstract class that has injectable field
public abstract class AbstractPopulator implements ITemplatePopulator {
#Inject
private ITemplatePopulator next;
I have multiple classes that inherit AbstractPopulator. They are simple in a sense
public class ImportsPopulator extends AbstractPopulator
public class FieldsPopulator extends AbstractPopulator
public class LeftHandSidePopulator extends AbstractPopulator
But I need for each of them to have their own injected next field. For example for leftHandSide I want righthandside and so on.
How to achieve that using google guice?
As a solution, I decided to do this.
In AbstractPopulator I added abstract method injectNext
protected abstract void injectNext(ITemplatePopulator next);
and removed #Inject annotation for the field next itself.
In each child class I implemented this method like this
#Override
#Inject
protected void injectNext(#Named("rightHandSidePopulator") ITemplatePopulator next) {
setNext(next);
}
where I specified via #Named the name of the next populator in the chain of responsibility.
The last one populator is special
#Override
#Inject(optional = true)
protected void injectNext(#Named("null") ITemplatePopulator next) {
setNext(next);
}
I set the optional parameter of Inject annotation to true because according to Guice documentation
Method and field injections may be optional, which causes Guice to silently
ignore them when the dependencies aren't available
So if no object with null name found it won't wire next.
In the module class, I bound classes
#Override
protected void configure() {
bind(ITemplatePopulator.class)
.annotatedWith(Names.named("packageNamePopulator")).to(PackageNamePopulator.class);
...
And guice used it like this where needed
Injector injector = Guice.createInjector(new PopulatorModule());
ITemplatePopulator first = injector.getInstance(PackageNamePopulator.class); // first in chain
It seems to be working ok, but I am not sure whether it is the best solution and annotation imports are
import com.google.inject.Inject;
import com.google.inject.name.Named;
I am very familiar with using spring to inject using #Bean & #Autowired. I have switched over to looking at guice and I am wondering what is the minimum involved to have it functioning. The following basic example throws a NPE:
import javax.inject.Inject;
public class ClassA {
String a = "test";
#Inject
public ClassA() {
System.out.println(a);
}
public void go() {
System.out.println("two");
}
}
The following class attempting to instantiate a new instance of ClassA:
import javax.inject.Inject;
public class ClassB {
#Inject
ClassA guice;
public ClassB() {
guice.go();
}
public static void main(String[] args) {
ClassB b = new ClassB();
}
}
I have tried all sorts of combinations of the following with no success:
public class SupportModule extends AbstractModule {
#Override
protected void configure() {
bind(ClassA.class);
//bind(ClassA.class).to(ClassB.class);
//others too
}
}
I must be missing a key thing somewhere here, I'm not quite sure where? do I need some manual instantiation of guice/configuration itself? I assume I possibly do.
guice.go(); <= NullPointerException occurs here, obviously the obj is null because my guice setup isn't right
In Spring i can do the following, I assume Guice can aid me in doing this too:
#Bean
public FrameworkProperties properties() {
return new FrameworkProperties();
}
and then just:
#Autowired
FrameworkProperties props;
do I need some manual instantiation of guice/configuration itself? I assume I possibly do.
Yes, you assumed right. You'll have to bootstrap the Injector modules that you have defined using the Guice.createInjector() method. Also, one other thing to note is when using a custom defined constructor like in ClassB, you'll have to use constructor injection. So in order to get this working, ClassB should look like:
public class ClassB {
private ClassA guice;
#Inject //This will inject the dependencies used in the constructor arguments
public ClassB(final ClassA guice) {
this.guice = guice;
guice.go();
}
public static void main(String[] args) {
/**
* If only type to type binding is required, you can skip creating a Module class &
* bootstrap the injector with empty argument createInjector like used below. But, when
* there are other kind of bindings like Type to Implementations defined in modules, you can use:
* final Injector injector1 = Guice.createInjector(new GuiceModule1(), new GuiceModule2());
*/
final Injector injector = Guice.createInjector();
final ClassB b = injector.getInstance(ClassB.class); //This will create dependency graph for you and inject all dependencies used by ClassB and downwards
}
}
Also, you can remove the #Inject annotation used in ClassA's constructor as you are not injecting any external dependencies in that constructor. You can look up the Guice's getting started wiki for more documentation.
I have the following class wherein I need method injection using Guice.
#Singleton
public class A {
private final Injector injector;
#Inject
public A(Injector injector) {
this.injector = injector;
}
public void method1() {
...
final XInterface x = this.injector.getInstance(Key.get(XInterface.class, Names.named("provideX")));
...
}
}
And the module contains the following provides method:
public class MyModule extends AbstractModule {
#Override void configure() {
// no binding and scope for class A
}
#Provides
#Named("provideX")
public XInterface provide(#Named("isTest") boolean isTest, X x, XMock xMock) {
return isTest ? xMock : x;
}
}
Where isTest has a provider in the same module and can be ignored for this discussion.
Now, this injection in class A gives me the following error:
Unable to create binding for `A`. It was already configured on one or more child injectors or private modules. If it was in a PrivateModule, did you forget to expose the binding?
and the rest of the stacktrace isn't very helpful.
After digging around for a while and trying out a few things, I found that just defining a Singleton scope for class A in the MyModule.configure() like so : bind(A.class).in(Singleton.class); and removing the existing #Singleton annotation on the class A solved the error. Now my question is two fold:
What caused the error in my first implementation?
What is the difference between defining a singleton scope in the module and annotating a class with singleton scope and why did that solve the problem?
Thanks in advance!
I have this interface and simple implementation:
public interface Data {
}
import java.nio.file.Path;
import javax.annotation.Nullable;
import javax.inject.Inject;
import com.google.inject.assistedinject.Assisted;
public class SimpleData implements Data {
#Inject
public SimpleData(#Assisted #Nullable Path path) {
}
}
I want to generate a Factory with different methods using guice.
import java.nio.file.Path;
import javax.annotation.Nullable;
public interface Factory {
Data create();
Data load(#Nullable Path path);
}
But the following module configuration:
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.assistedinject.FactoryModuleBuilder;
public class Main {
public static void main(String[] args) {
Injector injector = Guice.createInjector(
binder -> binder.install(
new FactoryModuleBuilder().implement(Data.class, SimpleData.class)
.build(Factory.class)));
Data data = injector.getInstance(Factory.class).create();
}
}
fails:
Exception in thread "main" com.google.inject.CreationException: Guice creation errors:
1) No implementation for java.nio.file.Path annotated with #com.google.inject.assistedinject.Assisted(value=) was bound.
while locating java.nio.file.Path annotated with #com.google.inject.assistedinject.Assisted(value=)
for parameter 0 at SimpleData.<init>(SimpleData.java:10)
at Factory.create(Factory.java:1)
at com.google.inject.assistedinject.FactoryProvider2.initialize(FactoryProvider2.java:539)
at com.google.inject.assistedinject.FactoryModuleBuilder$1.configure(FactoryModuleBuilder.java:335)
1 error
at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:435)
at com.google.inject.internal.InternalInjectorCreator.injectDynamically(InternalInjectorCreator.java:175)
at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:109)
at com.google.inject.Guice.createInjector(Guice.java:95)
at com.google.inject.Guice.createInjector(Guice.java:72)
at com.google.inject.Guice.createInjector(Guice.java:62)
at Main.main(Main.java:9)
I solved my problem using the annotation #AssistedInject. Quote from the javadoc:
When used in tandem with FactoryModuleBuilder, constructors annotated with #AssistedInject indicate that multiple constructors can be injected, each with different parameters.
So i add the annotation and a constructor to the SimpleData class:
public class SimpleData implements Data {
#AssistedInject
public SimpleData(#Assisted Path path) {
}
#AssistedInject
public SimpleData() {
}
}
i removed the #Nullable annotation from the factory:
import java.nio.file.Path;
public interface Factory {
Data create();
Data load(Path path);
}
#Nullable does not mean that if you don't have a binding, then null will be injected. It only allows writing bindings to null. If you don't have a binding and there is no applicable JIT-binding, then injection will fail.
Your factory's create() method requires Guice to find an #Assisted Path binding, but it obviously can't find it since you've never created one, so it fails.
Honestly, I'm not sure if there is a clean way to implement such defaulting. Ideally you should mark Path with some binding annotation and add a default binding to null for it, but #Assisted already is a binding annotation, and it is not possible to have multiple binding annotations on a single injection point. You can try creating a binding for #Assisted Path:
binder.bind(Path.class).annotatedWith(Assisted.class).toInstance(null);
However, I'm not sure if it would work because Assisted can be special to Guice. And even if it will work, it is not very clean - there may be conflicts with other assisted factories accepting Paths.
I would have Guice implement some kind of internal factory interface, then expose something else. Like this:
interface InternalFactory {
Data load(#Nullable Path path);
}
public interface Factory {
Data load();
Data load(#Nullable Path path);
}
class FactoryImpl implements Factory {
#Inject InternalFactory internalFactory;
#Override
public Data load() {
return load(null); // Pass your defaults here
}
#Override
public Data load(#Nullable Path path) {
// Sadly you'll have to explicitly forward arguments here, but it's not
// too bad IMO
return internalFactory.load(path);
}
}
public class MyModule extends AbstractModule {
#Override
protected void configure() {
install(new FactoryModuleBuilder()
.implement(Data.class, SimpleData.class)
.build(InternalFactory.class));
bind(Factory).to(FactoryImpl.class);
}
}
Is there a way to declare default binding in Guice 3.0 ?
Here is an example of what I expected :
//Constructor for Class Impl1
#Inject
public Impl1 (#One IMyOwn own)
{
...
}
//Constructor for Class Impl2
#Inject
public Impl2 (#Two IMyOwn own)
{
...
}
//Declare a default binding
bind(IMyOwn.class).to(DefaultMyOwn.class);
//Then, if I want to bind a custom implementation for #Two
bind(IMyOwn.class).annotatedWith(Two.class).to(TwoMyOwn.class);
Actually, this example can't works because I must declare a binding for all annotation (#One, #Two).
Are there solutions to do that with Guice ?
Thanks.
Use the #Named binding.
From Guice Reference on Github:
Guice comes with a built-in binding annotation #Named that uses a string:
public class RealBillingService implements BillingService {
#Inject
public RealBillingService(#Named("Checkout") CreditCardProcessor processor) {
...
}
To bind a specific name, use Names.named() to create an instance to pass to annotatedWith:
bind(CreditCardProcessor.class)
.annotatedWith(Names.named("Checkout"))
.to(CheckoutCreditCardProcessor.class);
So in your case,
//Constructor for Class Impl1
#Inject
public Impl1 (#Named("One") IMyOwn own)
{
...
}
//Constructor for Class Impl2
#Inject
public Impl2 (#Named("Two") IMyOwn own)
{
...
}
and your module will look like:
public class MyOwnModule extends AbstractModule {
#Override
protected void configure() {
bind(IMyOwn.class)
.annotatedWith(Names.named("One"))
.to(DefaultMyOwn.class);
bind(IMyOwn.class)
.annotatedWith(Names.named("Two"))
.to(TwoMyOwn.class);
}
}
With Guice 4.X there is Optional Binder.
public class FrameworkModule extends AbstractModule {
protected void configure() {
OptionalBinder.newOptionalBinder(binder(), Renamer.class);
}
}
public class FrameworkModule extends AbstractModule {
protected void configure() {
OptionalBinder.newOptionalBinder(
binder(),
Key.get(String.class, LookupUrl.class))
.setDefault().toInstance(DEFAULT_LOOKUP_URL);
}
}
In Guice 3.0 you may be able to exploit the automatic binding of the default constructor.
Use a single #Inject or public no-arguments constructor.
But this has constraints, as your default constructor needs to be of the same concrete class so derivation may become cumbersome.
Guice tries to check as much of your configuration (aka. Binding) as possible. This also means, that Guice cannot tell whether a missing binding for #One is an error or should map to some default case.
If you are interested in the details, lookup the BindingResolution sequence in Guice. Since step 4 and step 6 deal with binding annotation and step 6 explicitly forbids default, I think you are out of luck.
.6. If the dependency has a binding annotation, give up. Guice will not create default bindings for annotated dependencies.
So the best you can do is to provide Guice with a hint, that #One should map to the default like this:
bind(IMyOwn.class).annotatedWith(One.class).to(IMyOwn.class);
So you do not need to state the concrete default class DefaultMyOwn multiple times.