Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

custom Guice binding annotations with parameters

I have successfully created a Guice binding annotation to inject single threaded java.util.concurrent.ExecutorService instances into a constructor.

here is an example usage:

public class ContainsSingleThreadedExecutorService {


    private final ExecutorService executorService;

    @Inject
    public ContainsSingleThreadedExecutorService(@SingleThreaded ExecutorService executorService) {

        this.executorService = executorService;
    }

}

I now want to create a similar annotation for multi-threaded executors, specifying the ThreadPool size in the annotation. For example:

public class ContainsMultiThreadedExecutorService {


    private final ExecutorService executorService;

    @Inject
    public ContainsMultiThreadedExecutorService(@MultiThreaded(poolSize = 5) ExecutorService executorService) {

        this.executorService = executorService;
    }

}

Does anyone out there know how I can access the value of the "poolSize" parameter from a Guice Provider?

like image 860
murungu Avatar asked Apr 18 '11 15:04

murungu


4 Answers

You can't. That's not how binding annotations are intended to be used... the parameter would only serve to differentiate an ExecutorService bound with @MultiThreaded(poolSize = 5) from one bound with @MultiThreaded(poolSize = 2). It's not metadata to help configure a Provider.

If you inject something annotated with @MultiThreaded(poolSize = 5), you need to have bound something with the annotation @MultiThreaded(poolSize = 5). If you then want to change the pool size you're using in all those places, you need to change poolSize = 5 to poolSize = 4 in both the place(s) where you bind it and in all the places you inject it. This doesn't make much sense to me.

Instead of binding ExecutorServices by how many threads they have in their thread pool, you should bind them according to what you want to use them for. Then you can adjust the numbers of threads each one uses in one place.

like image 170
ColinD Avatar answered Nov 11 '22 22:11

ColinD


Look at NamedImpl that implements @Named and method Names.named(). I think you should have same implementation.

UPDATED Guice compares annotations by hashCode(). So, if you wont use @MultiThreaded(poolSize = 5) you should map it before instancing. It seems like dirty workaround, but you can write smt like

    for (int i = 1; i < 20; i++){
        bind(ExecutorService.class).annotatedWith(Qualifiers.withValue(i)).toProvider(new DependencyProvider(i));
    } 

If you would like to do this. Remember, that your MultiThreadedImpl should override hashCode in proper way. It could be smt like

@Override
public int hashCode() {
    return  (127 * "poolSize".hashCode()) ^ value;
}
like image 32
Stan Kurilin Avatar answered Nov 11 '22 20:11

Stan Kurilin


You can do this sort of thing (I once did almost exactly this) with Guice, but Guice really needs to know up-front what it's binding. So you would need to do something like:

for (int i=1; i < 100; i++) {
  ExecutorService svc = Executors.newFixedThreadPool(i);
  bind (ExecutorService.class).annotatedWith(new MultiThreadedImpl(i)).toInstance(svc);
}

(or more likely, bind to a Provider that lazily initializes it).

This is ugly enough that you probably don't actually want to do it. It's more useful to just use @Named and have a handful of ExecutorService instances which are tied to a name for the specific thing they are good for, anyway - then you can configure how many threads are used in one place, rather than having to wonder "is anybody using a 73-thread ExecutorService?"

like image 40
Tim Boudreau Avatar answered Nov 11 '22 22:11

Tim Boudreau


Yes, you can. without iterator all situations.

Actually, I have the almost the same problem like your's. Here is my answer and question, with all my code. I only know how to do with field not parameter, but I think this is not a big problem, right ?

Follow CustomInjections in wiki you will know how.

like image 27
wener Avatar answered Nov 11 '22 22:11

wener