Open rvdsoft opened 6 years ago
Please have a look at this. Currently it is not possible to use MapStruct with Dagger DI framework, when the mapper itself doesn't have dependencies. I would rather not create dummy dependencies, so ultimately I was not able to use MapStruct in my project
I am not quite following. Are you saying that dagger2 cannot instantiate a class if it doesn't have @Inject
on the constructor?
@guaranadev is it possible to create a small example that uses dagger2 so we can have a look at it?
Yes, exactly. Dagger always needs @Inject
on the constructor for the classes it's supposed to provide instances of, even if the constructor does not have any arguments or is not specified. https://dagger.dev/users-guide#declaring-dependencies (at the very end of Declaring Dependencies).
For now I was able to quickly piece together this example: https://gist.github.com/guaranadev/70b8bf1f03e631160992d0e866ca1bdb
Let me know if it's enough, if not I can expand upon this tomorrow. In this example MappingsImpl is generated by Mapstruct, but does not have specified and empty constructor with javax.inject.Inject annotation, which generates compiler error by Dagger
@filiphr In the end I just manually created and instance of MapperImpl in my DI module and used in in a provider. It would be cool if this issue was fixed though
@guaranadev I didn't know about the @Inject
fact on the constructor for Dagger. Perhaps we need a special componentModel
just for Dagger in this case.
I will mark this as "up-for-grabs" in case someone from the community would like to add this functionality. If you are interested in providing a PR @guaranadev let us know we can help you out.
Any new for this, example workaround maybe ? @guaranadev where did you create your instance ? I am trying to inject a Mapper with Dagger inside an Android application.
In your @Module
annotated class
@Provides
@Singleton
DtoMapper provideDtoMapper() {
return new DtoMapperImpl();
}
Where DtoMapperImpl is a class created by Mapstruct during build, so expect IDE errors if you did not run your Gradle build before. I cannot provide any more useful info about Mapstruct/Dagger integration, I have not used it in a long time
Thank you, I've ended up trying something similar.
@Provides
@Singleton
public DtoMapper dtoMapper() {
return DtoMapper.INSTANCE;
}
With the standard definition of the INSTANCE seen in documentation
@Mapper
public interface DtoMapper {
DtoMapper INSTANCE = Mappers.getMapper(DtoMapper.class);
(...)
}
@Varatnar that won't work if you want to inject other services or mappers within your mapper.
It was not required for my current setup, but that would indeed be the case. In that case, would @guaranadev 's way permit it ? I wonder if something like the following example would be possible ?
@Provides
@Singleton
DtoMapper provideDtoMapper(Object objectNeedingInjection) {
return new DtoMapperImpl(objectNeedingInjection);
}
When using dagger2, an object can only be injected if it has an
@Inject
constructor. When component model is set to jsr330, this constructor is added whenInjectionStrategy
is set toCONSTRUCTOR
and if there is at least one dependency used. If there are no dependencies then no constructor is created and thus it can't be injected.