Consider a MVP-ish set of types. An abstract Presenter exists, with a View interface:
public interface View {
//...
}
public abstract class AbstractPresenter<V extends View> {
#Inject V view;
//...
}
Then, lets have a specific concrete presenter subclass, with its view interface and implementation:
public interface LoginView extends View {
//...
}
public LoginPresenter extends AbstractPresenter<LoginView> {
//...
}
public class LoginViewImpl implements LoginView {
//...
}
In a Dagger module, of course we would define a #Provides method:
#Provides
LoginView provideLoginView() {
return new LoginViewImpl();
}
In Guice you could write this the same way, or just bind(LoginView.class).to(LoginViewImpl.class).
However, in Dagger (both v1 and the 2.0-SNAPSHOT from Google), this produces an error, since it can't figure out what V is when creating the binding wiring for AbstractPresenter<V>. On the other hand, Guice figures out that that because it is actually creating a LoginPresenter, so it needs an implementation of LoginView.
Dagger 1.2.2:
foo.bar.AbstractPresenter$$InjectAdapter.java:[21,31] cannot find symbol
symbol: class V
location: class foo.bar.AbstractPresenter$$InjectAdapter
Dagger 2.0-SNAPSHOT:
Caused by: java.lang.IllegalArgumentException: V
at dagger.internal.codegen.writer.TypeNames$2.defaultAction(TypeNames.java:39)
at dagger.internal.codegen.writer.TypeNames$2.defaultAction(TypeNames.java:36)
at javax.lang.model.util.SimpleTypeVisitor6.visitTypeVariable(SimpleTypeVisitor6.java:179)
at com.sun.tools.javac.code.Type$TypeVar.accept(Type.java:1052)
at dagger.internal.codegen.writer.TypeNames.forTypeMirror(TypeNames.java:36)
at dagger.internal.codegen.MembersInjectorGenerator.write(MembersInjectorGenerator.java:142)
at dagger.internal.codegen.MembersInjectorGenerator.write(MembersInjectorGenerator.java:61)
at dagger.internal.codegen.SourceFileGenerator.generate(SourceFileGenerator.java:53)
at dagger.internal.codegen.InjectBindingRegistry.generateSourcesForRequiredBindings(InjectBindingRegistry.java:101)
at dagger.internal.codegen.ComponentProcessor.process(ComponentProcessor.java:149)
My question: Is this a bug? Is this a missing feature? Or is this a performance issue that Dagger is protecting us from (a la SerializableTypeOracleBuilder in GWT RPC)?
Note that this same issue occurs when V is referred to as Provider<V>, Lazy<V>, etc.
That looks like a bug as it shouldn't throw an exception, but it should log a warning explaining that type parameters need to be bound to a specific type.
The rest is for Dagger2, and I'm using 2.1-SNAPSHOT. You haven't provided an example #Component that will do the injection and without it Dagger2 2.1-SNAPSHOT doesn't actually report a problem. It's possible that it has already fixed your problem and I'm seeing a slightly different version but if not then I presume your component looks something like this:
#Component
public interface PresenterComponent {
<V extends View> void inject(AbstractPresenter<V> presenter);
}
When Dagger2 is processing this it cannot determine a concrete type for V, and so it doesn't know what type to insert. It can't just insert say LoginView because that would break if it was passed a AbstractPresenter<LogoutView>.
However, if you use say the following then Dagger2 can determine that it needs to inject a LoginView into AbstractPresenter<LoginView> and will do so safely.
#Module
public class LoginModule {
#Provides LoginView provideLoginView() {
return new LoginViewImpl();
}
}
#Component(modules = LoginModule.class)
public interface LoginComponent {
void inject(LoginPresenter presenter);
}
Unless you have no control over when an object is created, e.g. if some framework creates it for you and then passes in for you to initialize, it is much better to use #Inject on the constructor if you can, e.g. like this:
public LoginPresenter extends AbstractPresenter<LoginView> {
//...
#Inject LoginPresenter(LoginView view) {
super(view);
//...
}
}
This is because of the Type arguments. Injects does not work when u have a type arguments. U need to do something like this,
bind(new LoginPresenter<LoginViewImpl>(){});
Related
Small question regarding Java Spring Webflux and type incompatibility issues please.
I have a very simple Spring Webflux application, where I declare a common interface for all my repositories to save a pojo:
public interface MyInterface {
Mono<MyPojo> save(MyPojo myPojo);
}
Here are example of a concrete implementation, for instance, Redis:
#Repository("redis")
public class MyRedisRepository implements MyInterface {
private final ReactiveRedisOperations<String, String> reactiveRedisOperations;
public MyRedisRepository(ReactiveRedisOperations<String, String> reactiveRedisOperations) {
this.reactiveRedisOperations = reactiveRedisOperations;
}
#Override
public Mono<MyPojo> save(MyPojo myPojo) {
return reactiveRedisOperations.opsForValue().set("someKey", "someValue").map(__ -> myPojo);
}
}
And now an example with Elastic.
#Repository("elastic")
public interface MyElasticRepository extends ReactiveElasticsearchRepository<MyPojo, String>, MyInterface {
}
Please note, the important point is that some are regular classes (like Redis) which needs to implement the save method.
On the other hand, some are interface which implements Reactive___Repository<MyPojo, String> (which already have a save method)
When trying to compile, I am faced with this issue:
types question.MyInterface and org.springframework.data.repository.reactive.ReactiveCrudRepository<question.MyPojo,java.lang.String> are incompatible;
This is a bit strange to me, as my intention is just to have all the repositories under a common MyInterface , with a save method.
May I ask why I am facing this issue, and most of all, how to resolve this (keeping the MyInterface ) please?
Thank you
The return type and parameter type of the save method defined on the two interfaces are different, which makes them incompatible.
The ReactiveCrudRepository that ReactiveElasticsearchRepository extends, specifies that types derived from MyPojo can be passed to and will be returned from the save method.
In your custom interface you limit the passed argument and return type strictly to MyPojo. So the compiler recognizes there is no way to determine which save method is called at runtime and complains.
Try adjusting the return type of your interface to the following and adjusting your implementations:
public interface MyInterface<T extends MyPojo> {
Mono<T> save(T myPojo);
}
I'm quite new to Dagger 2 and I'm looking for a way to have a "configurable component".
Essentially this is what I want to achieve:
public interface ErrorReporter{
...
}
public class ConsoleErrorReporter implements ErrorReporter{
... // Print to System.err
}
public class DialogErrorReporter implements ErrorReporter{
... // Show modal dialog to user
}
#Module
public interface UIModule{
#Provides
ErrorReporter provideErrorReporter();
}
#Module
public class ConsoleUIModule{
#Override
#Provides
ErrorReporter provideErrorReporter(ConsoleErrorReporter cer){
return cer;
}
}
#Module
public class GraphicalUIModule{
#Override
#Provides
ErrorReporter provideErrorReporter(DialogErrorReporter der){
return der;
}
}
#Component(modules = {UIModule.class, OtherUniversalModule.class})
public interface ApplicationComponent{
ErrorReporter errorReporter();
}
void main(String[] args){
final UIModule uiModule;
if(args.length == 1 && args[0].equals("gui")){
uiModule = new GraphicalUIModule();
}else{
uiModule = new ConsoleUIModule();
}
DaggerApplicationComponentdac = DaggerApplicationComponent.builder()
.uiModule(uiModule).build();
dac.errorReporter().showError("Hello world!");
}
The above fails with #Provides methods cannot be abstract unfortunately both for interfaces and abstract classes. I have also tried non-abstract base class with concrete implementations that return null and then overriding these in sub classes. However this also fails with #Provides methods may not override another method.
In short I want to define a contract for a module and choose different modules during runtime. I know that Dagger 2 compile time validates the object graph, but if I have a well defined contract that should still be possible right? Or am I forced to create two different components with duplicate code for both user interfaces? Are there other solutions that I'm missing?
I don't think using a module this way is possible, because...
Suppose you have the following two constructors for your classes
#Inject ConsoleErrorReporter(Console console);
#Inject DialogErrorReporter(Graphics graphics);
This would mean that ConsoleUIModule would require a Console and DialogErrorReporter would require a Graphics object to create their respecitve implementation of ErrorReporter.
But if dagger only knows about UIModule because you use the interface there...well...it could not provide the dependencies for either, because it doesn't know about any of them.
And if you don't know the dependencies building a dependency graph at compile time won't work. Also this won't compile even without dagger because provideErrorReporter(ConsoleErrorReporter cer) does not override provideErrorReporter().
What you can and should do is use different components. Because a component is the thing that actually knows how to provide things. And a component already is an interface—and that's what you wanted, right?
You can have component dependencies, where one component depends on another. E.g. have a DependentComponent that provides a NeedsErrorReporter that needs an implementation of ErrorReporter. We also depend on an interface, rather than the actual component (and that's what you wanted after all, right?)
You then implement the interface by actual components, and each component has its respective modules (and maybe even further dependencies). In the end you have a component that you can switch and will provide different versions of an object, properly encapsulated!
#Component(dependencies = UIComponent.class) /* <- an interface! */
interface DependentComponent {
NeedsErrorReporter needsErrorReporter();
}
class NeedsErrorReporter {
#Inject public NeedsErrorReporter(ErrorReporter reporter) { }
}
/* this is _not_ a component, but a simple interface! */
interface UIComponent {
ErrorReporter errorReporter();
}
/* Console */
#Component(modules = ConsoleUIModule.class)
interface ConsoleUIComponent extends UIComponent { }
#Module interface ConsoleUIModule {
#Binds ErrorReporter provideErrorReporter(ConsoleErrorReporter cer);
}
/* Graphic */
#Component(modules = GraphicalUIModule.class)
interface GraphicUIComponent extends UIComponent { }
#Module interface GraphicalUIModule {
#Binds ErrorReporter provideErrorReporter(DialogErrorReporter der);
}
/* The error reporter variants */
interface ErrorReporter {
}
class ConsoleErrorReporter implements ErrorReporter {
#Inject public ConsoleErrorReporter() { }
}
class DialogErrorReporter implements ErrorReporter {
#Inject public DialogErrorReporter() { }
}
Now all you have to do is pick the right component ;)
DaggerDependentComponent.builder().uIComponent(DaggerConsoleUIComponent.create()).build();
// or
DaggerDependentComponent.builder().uIComponent(DaggerGraphicUIComponent.create()).build();
I recently ran across this scenario in code that I didn't write and while there may be some design benefit to this approach, I can't seem to squeeze this rationale out of my own brain. So before I go and look foolish, I'm hoping for some feedback here.
Service interface something like this:
public interface Service {...}
Then, a base class that adds a generic reference to the Service interface where T extends the Service, but then the overall base class also implements the interface. Something like this:
public class ServiceBase<T extends Service> implements Service {...}
Why would you do this? I'm noticing that in practice the extension of ServiceBase always uses the same class name as T as the one that is being declared; so there's not really any magic polymorphic benefit here. Something like this:
public class MyService extends ServiceBase<MyService> {...}
and, the MyService class is never a container for the generic (e.g., I don't believe this is signaling some kind of self-containing list, where MyService could contain a list of MyServices).
Any ideas/thoughts on why someone would do this?
Why would you do this? I'm noticing that in practice the extension of
ServiceBase always uses the same class name as T as the one that is
being declared; so there's not really any magic polymorphic benefit
here.
Generics don't exist to create magic polymorphim. It is mainly a way to add constraints on types at compile time in order to reduce clumsy cast and error type at runtime.
In your case, suppose that ServiceBase class is abstract and has a process() method which needs to create at each call a new instance of the concrete class we declare in the parameterized type.
We call this abstract method createService().
Without using generics, we could declare the method like that public abstract ServiceBase createService().
ServiceBase without generics
public abstract class ServiceBase implements Service {
public abstract ServiceBase createService();
#Override
public void process() {
createService().process();
}
}
With this declaration, the concrete class may return any instance of ServiceBase.
For example, the following child class will compile because we are not forced to change the returned type of createService() to the current declared type.
MyService without generics
public class MyService extends ServiceBase {
#Override
public ServiceBase createService() {
return new AnotherService();
}
}
But if I use generics in base class :
ServiceBase with generics
public abstract class ServiceBase<T extends Service> implements Service {
public abstract T createService();
#Override
public void process() {
createService().process();
}
}
The concrete class has no choice, it is forced to change the returned type of createService() with the parameterized type declared.
MyService with generics
public class MyService extends ServiceBase<MyService> {
#Override
public MyService createService() {
return new MyService();
}
}
I made up an example using your class and interface declarations (except that I made ServiceBase abstract) which should illustrate the use of the generic types:
public interface Service {
int configure(String cmd);
}
public abstract class ServiceBase<T extends Service> implements Service {
private ServiceManager manager;
public ServiceBase(ServiceManager manager){
this.manager = manager;
}
public final void synchronize(T otherService){
manager.configureEnvironment(otherService.configure("syncDest"), configure("syncSrc"));
synchronizeTo(otherService);
}
protected abstract void synchronizeTo(T otherService);
}
public class ProducerService extends ServiceBase<ConsumerService> {
public ProducerService(ServiceManager manager) {
super(manager);
}
#Override
protected void synchronizeTo(ConsumerService otherService) {
/* specific code for synchronization with consumer service*/
}
#Override
public int configure(String cmd) { ... }
}
public class ConsumerService extends ServiceBase<ProducerService> {
public ConsumerService(ServiceManager manager) {
super(manager);
}
#Override
protected void synchronizeTo(ProducerService otherService) {
/* specific code for synchronization with producer service */
}
#Override
public int configure(String cmd) { ... }
}
Imagine we have services managed by a ServiceManager which can configure the environment of the services so that they are ready for synchronization with each other. How a configure command is interpreted is up to the specific service. Therefore a configure() declaration resides in our interface.
The ServiceBase handles the basic synchronization stuff that has to happen generally when two services want to synchronize. The individual implementations of ServiceBase shouldn't have to deal with this.
However ServiceBase doesn't know how a specific implementation of itself synchronizes to a specific other implementation of service. Therefore it has to delegate this part of synchronization to its subclass.
Now generics come into the play. ServiceBase also doesn't know to which type of service it is able to synchronize to. He has also to delegate this decision to its subclass. He can do this using the construct T extends Service
Given this structure now imagine two concrete subclasses of ServiceBase: ProducerService and ConsumerService; The consumer service can only synchronize to the producer service and the other way around. Therefore the two classes specify in their declaration ServiceBase<ConsumerService> respectively ServiceBase<ProducerService>.
Conclusion
Just like abstract methods can be used by superclasses to delegate the implementation of functionality to their subclasses, generic type parameters can be used by superclasses to delegate the "implementation" of type placeholders to their subclasses.
You haven't posted any of the definitions of these classes where the type parameter is used (which would most likely convey the rationale behind this design, or maybe the lack of it...), but in all cases, a type parameter is a way of parameterizing a class, just like a method can be parameterized.
The ServiceBase class implements a Service. This tells us that it implements the contract (methods) of a Service (to be more precise, subclasses of it can act as the implementation).
At the same time, ServiceBase takes a type argument that is a subtype of Service. This tells us that a service implementation probably has a "relationship" with another implementation type (possibly the same type as the current one). This relationship could be anything needed by the specific design requirement, e.g. the type of Service that this implementation can delegate to, the type of Service that can call this service, etc.
The way I read the following declaration
public class ServiceBase<T extends Service> implements Service {...}
is roughly: ServiceBase is a base implementation of a service, which can have a statically typed relationship with some other type of service.
These two aspects are completely independent.
Is there a way to declare default binding in Guice 3.0 ?
Here is an example of what I expected :
//Constructor for Class Impl1
#Inject
public Impl1 (#One IMyOwn own)
{
...
}
//Constructor for Class Impl2
#Inject
public Impl2 (#Two IMyOwn own)
{
...
}
//Declare a default binding
bind(IMyOwn.class).to(DefaultMyOwn.class);
//Then, if I want to bind a custom implementation for #Two
bind(IMyOwn.class).annotatedWith(Two.class).to(TwoMyOwn.class);
Actually, this example can't works because I must declare a binding for all annotation (#One, #Two).
Are there solutions to do that with Guice ?
Thanks.
Use the #Named binding.
From Guice Reference on Github:
Guice comes with a built-in binding annotation #Named that uses a string:
public class RealBillingService implements BillingService {
#Inject
public RealBillingService(#Named("Checkout") CreditCardProcessor processor) {
...
}
To bind a specific name, use Names.named() to create an instance to pass to annotatedWith:
bind(CreditCardProcessor.class)
.annotatedWith(Names.named("Checkout"))
.to(CheckoutCreditCardProcessor.class);
So in your case,
//Constructor for Class Impl1
#Inject
public Impl1 (#Named("One") IMyOwn own)
{
...
}
//Constructor for Class Impl2
#Inject
public Impl2 (#Named("Two") IMyOwn own)
{
...
}
and your module will look like:
public class MyOwnModule extends AbstractModule {
#Override
protected void configure() {
bind(IMyOwn.class)
.annotatedWith(Names.named("One"))
.to(DefaultMyOwn.class);
bind(IMyOwn.class)
.annotatedWith(Names.named("Two"))
.to(TwoMyOwn.class);
}
}
With Guice 4.X there is Optional Binder.
public class FrameworkModule extends AbstractModule {
protected void configure() {
OptionalBinder.newOptionalBinder(binder(), Renamer.class);
}
}
public class FrameworkModule extends AbstractModule {
protected void configure() {
OptionalBinder.newOptionalBinder(
binder(),
Key.get(String.class, LookupUrl.class))
.setDefault().toInstance(DEFAULT_LOOKUP_URL);
}
}
In Guice 3.0 you may be able to exploit the automatic binding of the default constructor.
Use a single #Inject or public no-arguments constructor.
But this has constraints, as your default constructor needs to be of the same concrete class so derivation may become cumbersome.
Guice tries to check as much of your configuration (aka. Binding) as possible. This also means, that Guice cannot tell whether a missing binding for #One is an error or should map to some default case.
If you are interested in the details, lookup the BindingResolution sequence in Guice. Since step 4 and step 6 deal with binding annotation and step 6 explicitly forbids default, I think you are out of luck.
.6. If the dependency has a binding annotation, give up. Guice will not create default bindings for annotated dependencies.
So the best you can do is to provide Guice with a hint, that #One should map to the default like this:
bind(IMyOwn.class).annotatedWith(One.class).to(IMyOwn.class);
So you do not need to state the concrete default class DefaultMyOwn multiple times.
So far, I successfully used google guice 2. While migrating to guice 3.0, I had troubles with assisted inject factories. Assume the following code
public interface Currency {}
public class SwissFrancs implements Currency {}
public interface Payment<T extends Currency> {}
public class RealPayment implements Payment<SwissFrancs> {
#Inject
RealPayment(#Assisted Date date) {}
}
public interface PaymentFactory {
Payment<Currency> create(Date date);
}
public SwissFrancPaymentModule extends AbstractModule {
protected void configure() {
install(new FactoryModuleBuilder()
.implement(Payment.class, RealPayment.class)
.build(PaymentFactory.class));
}
}
While creating the injector, I get the following exception:
com.google.inject.CreationException: Guice creation errors:
1) Payment<Currency> is an interface, not a concrete class.
Unable to create AssistedInject factory. while locating Payment<Currency>
at PaymentFactory.create(PaymentFactory.java:1)
With the assisted inject creator from guice 2 my configuration works:
bind(PaymentFactory.class).toProvider(
FactoryProvider.newFactory(PaymentFactory.class, RealPayment.class));
The only workaround I found so far is to remove the generic parameter from the return type of the factory method:
public interface PaymentFactory {
Payment create(Date date);
}
Does anybody know, why guice 3 doesn't like the generic parameter in the factory method or what I generally misunderstood about assisted inject factories? Thanks!
There are two issues with your code above.
First, RealPayment implements Payment<SwissFrancs>, but PaymentFactory.create returns Payment<Currency>. A Payment<SwissFrancs> cannot be returned from a method that returns Payment<Currency>. If you change the return type of create to Payment<? extends Currency>, then RealPayment will work (because it's a Payment for something that extends Currency).
Second, you DO need to use the version of implement that takes a TypeLiteral as its first argument. The way to do that is to use an anonymous inner class. To represent `Payment' you can use
new TypeLiteral<Payment<? extends Currency>>() {}
See the Javadoc for that TypeLiteral constructor for more information.