Binding different database sessions to different backends.

39 views
Skip to first unread message

Kevin Burton

unread,
Aug 6, 2016, 3:41:24 PM8/6/16
to google-guice
I can't find a decent way to do this and none of them pass my "smell test".. 

Basically we have a few Provider<Client> instances that each represent their own Elastisearch cluster.

We are decoupling our Elasticsearch clusters ... so we can no longer use a single Provider<Client>.

The problem is that I have a bunch of code written to use inject  Provider<Client>

I guess what I want to do is have specific components use specific Provider<Client> automatically within the same binding.

Is there a way I can do this without having to use a different injector/modules?

I can't think of an elegant way but maybe there's some Guice mojo I'm missing.

Tim Boudreau

unread,
Nov 1, 2016, 4:01:10 PM11/1/16
to google-guice
I worked on a project once that had a similar requirement - in my case it was a codebase littered with code to load legacy properties files, scattered throughout it, and I wanted to get that code out of the business of reading files and having to know where they were, and use @Named for the property values.  So I needed a way to annotate different packages with the name of what they needed to load.

I don't know if I'd do it again like this, but the solution was this feature of Giulius, a micro-framework on top of Guice for loading settings and application lifecycle:  https://github.com/timboudreau/giulius#using-namespaces-with-settings

Essentially how it works is:
 - A runtime annotation on classes or packages identifies which "namespace" (in your case, a name that specifies which back end) to use
 - An annotation processor puts a flat list of all known names used for that into META-INF, which is used when setting up bindings
 - A custom Provider will provide the Properties (or in your case, the Client)
 - A ProvisionListener wraps the call to actually do injection - when called it
   - Looks up the class being instantiated
   - Looks for the annotation on the class
     - If not present, looks for the annotation on the package and all parent packages, failing over to a default if none present
   - Sets a ThreadLocal with the current "namespace" or "context" (important: this can be called reentrantly, so save the old value of the ThreadLocal and restore it after provisioning)
 - The custom Provider looks in the ThreadLocal and provides a different object depending on what it contains

https://github.com/timboudreau/giulius/blob/master/giulius/src/main/java/com/mastfrog/giulius/Dependencies.java#L626

Hope that provides some inspiration,

Tim
Reply all
Reply to author
Forward
0 new messages