Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to delegate creation of some classes from Guice injector to another factory?

For instance, RESTEasy's ResteasyWebTarget class has a method proxy(Class<T> clazz), just like Injector's getInstance(Class<T> clazz). Is there a way to tell Guice that creation of some classes should be delegated to some instance?

My goal is the following behavior of Guice: when the injector is asked for a new instance of class A, try to instantiate it; if instantiation is impossible, ask another object (e. g. ResteasyWebTarget instance) to instantiate the class.

I'd like to write a module like this:

@Override
protected void configure() {
    String apiUrl = "https://api.example.com";
    Client client = new ResteasyClientBuilder().build();
    target = (ResteasyWebTarget) client.target(apiUrl);

    onFailureToInstantiateClass(Matchers.annotatedWith(@Path.class)).delegateTo(target);
}

instead of

@Override
protected void configure() {
    String apiUrl = "https://api.example.com";
    Client client = new ResteasyClientBuilder().build();
    target = (ResteasyWebTarget) client.target(apiUrl);

    bind(Service1.class).toProvider(() -> target.proxy(Service1.class);
    bind(Service2.class).toProvider(() -> target.proxy(Service2.class);
    bind(Service3.class).toProvider(() -> target.proxy(Service3.class);
}

I've thought about implementing Injector interface and use that implementation as a child injector, but the interface has too much methods.

I can write a method enumerating all annotated interfaces in some package and telling Guice to use provider for them, but that's the backup approach.

like image 647
Kirill Gamazkov Avatar asked Feb 05 '16 11:02

Kirill Gamazkov


2 Answers

Guice does not support this, it has no hooks for you to listen too. The hooks it does provide (ProvisionListener & TypeListener) don't get called if a binding can not be found.

I can write a method enumerating all annotated interfaces in some package and telling Guice to use provider for them, but that's the backup approach.

That is your only option. The optional injections only work if you are willing to spread your target.proxy love all over the codebase.

EDIT (2017-02-28): If you are going to do this, I've already done the basics to make it happen as part of my magic-provider-guice project, with examples for JDBI and Feign.

implementing Injector interface and use that implementation as a child injector

I don't believe you can set a child injector (just have Guice create one with a set of modules), so this would not work either.

like image 163
Michael Lloyd Lee mlk Avatar answered Oct 23 '22 06:10

Michael Lloyd Lee mlk


https://github.com/google/guice/wiki/Injections Check out Optional Injections, you can create a fall back with that.

like image 1
Drusantia Avatar answered Oct 23 '22 07:10

Drusantia