Is it ok to bind in interface with guice? the error is No implementation for com.tobris.apps.base.service.user.UserService was bound.
UserService is an interface.
@Inject
public SyncContactService(
PartnerRepository partnerRepo,
CompanyRepository companyRepo,
CityRepository cityRepo,
CountryRepository countryRepo,
AddressRepository addressRepo,
SyncContactRepository syncContactRepo,
EmailAddressRepository emailAddressRepo,
UserService userService,
FunctionRepository functionRepo) {
this.partnerRepo = partnerRepo;
this.companyRepo = companyRepo;
this.cityRepo = cityRepo;
this.countryRepo = countryRepo;
this.addressRepo = addressRepo;
this.syncContactRepo = syncContactRepo;
this.emailAddressRepo = emailAddressRepo;
this.userService = userService;
this.functionRepo = functionRepo;
}
this is the binding code :
// bind all the web service resources
for (Class<?> type :
MetaScanner.findSubTypesOf(Object.class)
.having(Path.class)
.having(Provider.class)
.any()
.find()) {
bind(type);
}
When you bind()
a type, you actually bind that type and not any of its interfaces or superclasses. That means that for a class such as ArrayList
, which implements several interfaces and has several super classes, only ArrayList
will be binded, not List
, not AbstractList
to take a few.
Therefore, the best approach is to find all subtypes of the type you want to bind, and make sure there's only one appropriate implementation.
In terms of code, what you should do is the following:
ScopedBindingBuilder bindScannedImplementation(Class<?> baseType) {
var subtypes = MetaScanner.findSubTypesOf(baseType)
.having(Path.class)
.having(Provider.class)
.any()
.find();
var implementations = subtypes.stream()
.filter(this::isConcreteClass)
.toList();
if (implementations.size() != 1) {
throw new RuntimeException("Too many or too few implementations for " + baseType.getName());
}
var implementation = implementations.get(0);
return bind(baseType.class).to(implementation);
}
private boolean isConcreteClass(Class<?> c) {
if (c.isInterface()) return false;
if ((c.getModifiers() & Modifier.ABSTRACT) != 0) return false;
return true;
}
Then, you have to explicitly bind the types you want:
bindScannedImplementation(UserService.class).in(Singleton.class);