Changing the injection key for a binding

56 views
Skip to first unread message

John Gardiner Myers

unread,
Mar 29, 2016, 3:16:57 PM3/29/16
to google...@googlegroups.com
I am attempting to implement some auxiliary EDSLs for accessing a
library through Guice. I am having trouble figuring out how to implement
.annotatedWith() in situations where the caller doesn't have to specify
an implementation.

This is easy enough to do when the library needs to consume a
mapping--one can have

reportBinder(binder).export(SomeClass.class);

throw into a multibinder a package local Mapping object containing a
field with Key.get(SomeClass.class) and defaults for other fields, then
.annotatedWith(...) can later replace that injection key field. Other
EDSL methods can later replace other fields to have non-default values.
So a caller could do:

reportBinder(binder).export(SomeClass.class).annotatedWith(SomeAnnotation.class).withTags(whatever);

What I can't figure out how to implement is the situation where I need
the EDSL to create a new binding.

reportBinder(binder).createReportCollection(SomeInterface.class);

needs to bind Key.get(SomeInterface.class) to some default
implementation the library constructs, but

reportBinder(binder).createReportCollection(SomeInterface.class).annotatedWith(SomeAnnotation.class);

needs to bind Key.get(SomeInterface.class, SomeAnnotation.class) to a
default implementation, but not provide any binding for
Key.get(SomeInterface.class).

Any suggestions for how to accomplish this?

Stephan Classen

unread,
Mar 29, 2016, 5:07:30 PM3/29/16
to google...@googlegroups.com
OK, I read you post several times still I am not 100% sure if I understood your problem entirely.
Maybe some more code or concrete examples would be helpful...

From what I think you are trying to achieve I have done something similar myself once before.
Have a look at the following classes:
- PersistenceModule [1]
- PersistenceUnitModuleConfiguration [2]
- PersistenceUnitModule [3]

An example of the usage of above classes can be found here [4].

The idea behind my approach is that the PersistenceModule holds the EDSL (bunch of protected methods).
The EDSL methods store the configuration in the PersistenceUnitModuleConfiguration. When the injector is created the PersistenceUnitModuleConfigurations are used to create PersistenceUnitModules (see PersistenceModule. configurePersistenceUnits).
The PersistenceUnitModule will add the bindings to the injector.

I hope I am not totally off topic with my response.

Cheers


[1] https://svn.apache.org/viewvc/onami/tags/org.apache.onami.persist-1.0.1/src/main/java/org/apache/onami/persist/PersistenceModule.java?revision=1633051&view=markup
[2] https://svn.apache.org/viewvc/onami/tags/org.apache.onami.persist-1.0.1/src/main/java/org/apache/onami/persist/PersistenceUnitModuleConfiguration.java?revision=1633051&view=markup
[3] https://svn.apache.org/viewvc/onami/tags/org.apache.onami.persist-1.0.1/src/main/java/org/apache/onami/persist/PersistenceUnitModule.java?revision=1633051&view=markup
[4] http://onami.apache.org/persist/complexWebApp.html

Fred Faber

unread,
Mar 29, 2016, 5:35:41 PM3/29/16
to google...@googlegroups.com
Is the question basically how to know whether to take an action when .createReportCollection() is called, because you don't know whether .annotatedWith() will be called or not?

--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-guice...@googlegroups.com.
To post to this group, send email to google...@googlegroups.com.
Visit this group at https://groups.google.com/group/google-guice.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-guice/56FAEE8F.1040203%40gmx.ch.

For more options, visit https://groups.google.com/d/optout.

John Gardiner Myers

unread,
Mar 30, 2016, 7:25:32 PM3/30/16
to google-guice


On Tuesday, March 29, 2016 at 2:07:30 PM UTC-7, scl wrote:
OK, I read you post several times still I am not 100% sure if I understood your problem entirely.
Maybe some more code or concrete examples would be helpful...

I was trying to avoid posting a wall of code. A non-working attempt of mine is at https://github.com/johngmyers/platform/commit/ffac3e042bbf530f3af09f7072eba91e742e6471
 

From what I think you are trying to achieve I have done something similar myself once before.
Have a look at the following classes:

This looks pretty close to what I am attempting. How do you ensure that Guice doesn't configure your PersistenceModule until all users of the EDSL are done? In my attempt, the ReportCollectionModule is configured immediately upon installation, before the calling Module finishes calling the EDSL methods.

Stephan Classen

unread,
Mar 30, 2016, 7:40:51 PM3/30/16
to google...@googlegroups.com
I only allow usage of the EDSL within the abstract method PersistenceModule.configurePersistence().
All EDSL methods have a check as the very first statement to ensure that they are called from within the configurePersistence().

The configurePersistence() itself is a callback which will be called when the injector is created (i.e. during Module.configure() )

I know this is a very strong limitation. I don't know how strict you want to hide guice from the user of the EDSL. If they are awear of guice then they know about the configure() method. So the concept of your own configureXxx() method is nothing new.
--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-guice...@googlegroups.com.
To post to this group, send email to google...@googlegroups.com.
Visit this group at https://groups.google.com/group/google-guice.

John Gardiner Myers

unread,
Mar 30, 2016, 8:04:51 PM3/30/16
to google...@googlegroups.com
While the users of the EDSL are aware of Guice, the requirement for
callers to extend a particular abstract class
is too strong, not to mention incompatible with previous versions of the
EDSL. This is not a requirement that Guice EDSLs typically impose, and a
module would not be able to use two such EDSLs because one cannot extend
two abstract classes.

So I seem to need some way to do one of:

* Change the injection key for a binding
* Defer configuration of an installed module at least until the
enclosing module returns from its configure method
* Remove a binding made earlier in the module

John Gardiner Myers

unread,
Mar 31, 2016, 1:46:59 PM3/31/16
to google-guice
It works if I make out-of-order calls to the Guice binding EDSL methods:

public class ReportCollectionBinder<T>
{
    private final ReportCollectionProvider<T> provider;
    private final AnnotatedBindingBuilder<T> bindingBuilder;

    ReportCollectionBinder(Binder binder, Class<T> iface)
    {
        provider = new ReportCollectionProvider<>(iface);
        bindingBuilder = binder.bind(iface);
        bindingBuilder.toProvider(provider).in(SINGLETON);
    }

    public NamedReportCollectionBinder<T> annotatedWith(Annotation annotation)
    {
        bindingBuilder.annotatedWith(annotation);
        return new NamedReportCollectionBinder<>(provider);
    }
}

This usage pattern isn't documented, though, and it's not clear whether it might break in a future version of Guice.


Reply all
Reply to author
Forward
0 new messages