Maybe filter was not the best choice of a name. So don't let yourself be 
tricket by this. At the end the interface method is:

List<User> getUsers(List<User> users);

And the concrete implementation is absolutely free to add, remove or replace 
users from the list.

Am 7. Februar 2015 18:10:14 MEZ, schrieb "Aurélien" <[email protected]>:
>Yes exactly: I want a chain like behavior where the order of the
>modules in 
>the createInjector method determines the order in the chain.
>However, I think the Multibinder Set binder does preserve the ordering.
>
>Indeed, Multibinder is using an ImmutableSet which preserves the order
>from 
>construction time : 
>https://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained
>
>But ultimately, I also want to be able to create the Framework without 
>thinking about how plugins will alter the base functionalities.
>The ChainedUserService example have one main problem for me : code have
>to 
>be added in the Framework to enable plugins to filter the result. So if
>a 
>new plugin does not want to filter the result, but merge the result
>with 
>another result (from a web-service for instance), the Framework will
>have 
>to be modified in order to build the new plugin.
>
>Looking at the code of the multibindings extension, it seems it isn't
>to 
>hard to extend Guice. I will try to implement a POC of my use case and
>I 
>will come back here to talk about it.
>
>Thank you all for your answers, you enable me to understand my need
>better !
>
>On Thursday, February 5, 2015 at 9:00:39 AM UTC+1, scl wrote:
>>
>>  So what you want is a chain like behavior where the order of the
>modules 
>> in the createInjector method determines the order in the chain.
>> I don't think this is easily possible with the current guice
>extensions. 
>> Multibinder offers a Set and a Map binder. Neither of them preserves
>the 
>> ordering.
>>
>> You could make a hacky thing where you use Integer as key for the 
>> MapBinder. During injector creation you could have a static counter
>which 
>> will map each binding to a unique increasing value (0, 1, 2, ...). In
>the 
>> application you can then iterate over the number of elements in the
>Map and 
>> retrieve them by their key.
>>
>> Something like this (sorry pseudo code, not my dev machine...):
>>
>> ----
>>
>> private static int userServiceCounter;
>>
>> public static addBindingToUserServiceChain(Binder binder, Class<?
>extends 
>> UserServiceFilter> implementation) {
>>     // make the binding here
>> }
>>
>> ----
>>
>> class ChainedUserService implements UserService {
>>
>> private final CoreUserService coreService
>> private final Map<Integer, UserServiceFilter> filterServices;
>>
>> @Override
>> public List<User> getUsers() {
>>     final int n = services.size();
>>     List<User> result = coreService.getUsers();
>>     
>>     for (int i = 0; i < n; i++) {
>>         final UserServiceFilter filter = filterServices.get(i);
>>         result = filter.getUser(result);
>>     }
>> }
>>
>> ----
>>
>> Core would then bind ChainedUserService to UserService.
>>
>>         
>>
>>
>> On 02/04/2015 11:34 PM, Aurélien wrote:
>>  
>> Thank you for your responses.
>>
>> The OptionalBinder lead me to what I want : a plugin-type
>architecture.
>> I could not reference a parent implementation with OptionalBinder.
>> However, the Multibinder enable to add multiple implementations and
>to 
>> reference all these implementations.
>>
>> Although the Multibinder pattern is good, it means the Framework 
>> implementation needs to guess most of the sub plugins uses.
>>
>> Here is an example of what I would like to do :
>> 1/ The Framework defines a method to fetch the application users : 
>> List<User> users();
>> The base implementation connect to a database and fetch all the
>users.
>>
>> 2/ The plugin web-service fetch users on an API on the Internet and
>add 
>> them to the default implementation : 
>> list(parent.users()).addAll(ws.users());
>>
>> 3/ The plugin group filter users who are in the same group as the
>current 
>> user : parent.users().filter(user -> user.group() ==
>currentUser.group());
>>
>> Then in the application, I will be able to :
>> - use the framework only : users() returns all the users in the
>database,
>> - use the group plugin : users() returns all the users in the
>database who 
>> are in the same group as the current user
>> - use the web-service plugin : users() returns all the users in the 
>> database plus all the users provided by some web-service
>> - use both the group plugin and the web-service plugin : users()
>returns 
>> database users and web-service users but filtered by the group
>>
>> This would be awesome because in the Framework I wouldn't have to
>think 
>> how plugins will change the default features.
>>
>> To achieve this, using the MultiBindings Guice extension style, I
>would 
>> have framework and plugins declare modules this way :
>>  public class ModuleGuice extends AbstractModule {
>>     @Override protected void configure() {
>>         Parentbinder
>>                 .newBinder(binder(), UserService.class)
>>                 .setBinding()
>>                 .to(UserFrameworkService.class);
>>     }
>> }
>>  
>> Then, in the plugins service overriding, I would have something like
>:
>>  public class UserWsService implements UserService {
>>
>>     private final UserService parent;
>>     private final UserApi userApi;
>>
>>     @Inject public UserWsService(@Parent UserService parent, UserApi 
>> userApi) {
>>         this.parent = parent;
>>         this.userApi = userApi;
>>     }
>>
>>     @Override public List<User> users() {
>>         return
>ImmutableList.builder().addAll(parent.users()).addAll(ws.
>> users()).build();
>>     }
>>
>> }
>>  
>> And eventually, in the Application, I would just have to do :
>>  Injector injector = Guice.createInjector(new FrameworkModule(), new 
>> WebServiceModule(), new GroupModule());
>> injector.getInstance(UserService.class).users(); // database + ws
>users 
>> filtered by group
>>  
>> Do I have to look in ExtendingGuice documentation 
>> <https://github.com/google/guice/wiki/ExtendingGuice> to implement
>this 
>> or another class in the MultiBindings Guice extension might do the
>job (or 
>> elsewhere!) ?
>>
>> Thank you for your help!
>> Aurélien
>>
>> On Wednesday, February 4, 2015 at 10:42:46 PM UTC+1, scl wrote: 
>>>
>>> One thing that will not work is injecting A into either ASub or 
>>> AOtherSub. Because this will create an endless loop sinc A is bound
>to ASub 
>>> resp. AOtherSub.
>>> You need to be more specific and either request ACore or introduce a
>name 
>>> for the parent so you could inject (@Parent A)
>>>
>>> Am 4. Februar 2015 16:59:09 MEZ, schrieb Joshua Moore-Oliva <
>>> [email protected]>: 
>>>>
>>>> If I am understanding your use case correctly, it sounds like you
>may be 
>>>> interested in using the OptionalBinder that is new in guice4. It
>would 
>>>> allow you to set up a default binding (setDefault) in core, and
>then 
>>>> override that in a sub (setBinding). 
>>>>
>>>>  The javadoc is fairly thorough and has some examples here:
>>>>
>>>>  
>>>>
>http://google.github.io/guice/api-docs/latest/javadoc/com/google/inject/multibindings/OptionalBinder.html
>>>>  
>>>>  
>>>>  
>>>> On Tuesday, February 3, 2015 at 3:36:28 PM UTC-7, Aurélien wrote: 
>>>>>
>>>>> Hi,
>>>>>
>>>>> I have a peculiar use case:
>>>>> - I have 3 libraries, Core, Sub and OtherSub
>>>>> - Sub and OtherSub do not know anything about each other, but they
>know 
>>>>> the existence of Core
>>>>> - Sub and OtherSub override the same functionality in Core
>>>>> - In a project, I want to combine Sub and OtherSub.
>>>>>
>>>>> It does not work, but here is how I wanted to implement this
>pattern 
>>>>> with Guice:
>>>>> - in the Core library:
>>>>>     o bind(A.class).to(ACore.class)
>>>>>     o class ACore implements A {
>>>>>         @Override public String a() { "a"; }
>>>>>     }
>>>>> - in the Sub library:
>>>>>     o bind(A.class).to(ASub.class)
>>>>>     o class ASub implements A {
>>>>>         private final A parent; // instance of ACore or AOtherSub
>>>>>         @Inject ASub(A parent) { this.a = parent; }
>>>>>         @Override public String a() { parent.a() + " overriden"; }
>>>>>     }
>>>>> - in the OtherSub library:
>>>>>     o bind(A.class).to(AOtherSub.class)
>>>>>     o class AOtherSub implements A {
>>>>>         private final A parent; // instance of ACore or ASub
>>>>>         @Inject ASub(A parent) { this.a = parent; }
>>>>>         @Override public String a() { parent.a() + " !"; }
>>>>>     }
>>>>>
>>>>> then in the projet using this set of libraries, I would have been
>able 
>>>>> to do:
>>>>> - Guice.createInjector(Modules.override(new ModuleCore()).with(new
>
>>>>> AOtherSub())).getInstance(A.class).a() // returns "a !"
>>>>> - Guice.createInjector(Modules.override(Modules.override(new 
>>>>> ModuleCore()).with(new ASub())).with(new 
>>>>> AOtherSub())).getInstance(A.class).a() // returns "a overriden !"
>>>>> - Guice.createInjector(Modules.override(Modules.override(new 
>>>>> ModuleCore()).with(new AOtherSub())).with(new 
>>>>> ASub())).getInstance(A.class).a() // returns "a ! overriden"
>>>>>
>>>>> In this implementation, this throws a StackOverflowError because
>in 
>>>>> ASub or in AOtherSub the instance creation falls in an infinite
>loop.
>>>>>
>>>>> Is there a way of doing something like that with Guice ?
>>>>> Else do you have any insight on how I should implement this use
>case ?
>>>>>
>>>>> Cheers,
>>>>> Aurélien
>>>>>  
>>>>     -- 
>> 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 [email protected] <javascript:>.
>> To post to this group, send email to [email protected] 
>> <javascript:>.
>> Visit this group at http://groups.google.com/group/google-guice.
>> To view this discussion on the web visit 
>>
>https://groups.google.com/d/msgid/google-guice/f348749b-8b33-4d81-a8c4-c5d1256805e7%40googlegroups.com
>
>>
><https://groups.google.com/d/msgid/google-guice/f348749b-8b33-4d81-a8c4-c5d1256805e7%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>> For more options, visit https://groups.google.com/d/optout.
>>
>>
>> 
>
>-- 
>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 [email protected].
>To post to this group, send email to [email protected].
>Visit this group at http://groups.google.com/group/google-guice.
>To view this discussion on the web visit
>https://groups.google.com/d/msgid/google-guice/e544b9cb-51fa-482e-9ba6-2ba27a153c32%40googlegroups.com.
>For more options, visit https://groups.google.com/d/optout.

-- 
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 [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/google-guice.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/google-guice/82C9FD6C-39D4-48FA-8ED1-561D58849DFE%40gmx.ch.
For more options, visit https://groups.google.com/d/optout.

Reply via email to