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 to implement this or another class in the MultiBindings Guice extension might do the job (or elsewhere!) ?
Thank you for your help!
Aurélien