Im having some problems with dependency injections in java 11 / jersey / hk2. I have a simple resource class which injects a service class:
@Path("/backbone")
public class BackboneController extends GenericController {
@Inject
private IEnvironmentService _environmentService;
@Inject
private IAuthenticationHelper _authenticationHelper;
@Inject
private IBackboneService _backboneService;
@GET
@Path("version")
@Produces(MediaType.APPLICATION_JSON)
public Response version(
@HeaderParam("Authorization") String token) throws Exception {
var credentials = _authenticationHelper.detokenizeCredentials(token);
var backendVersionHandler = new BackendVersionResponseDto(_backboneService.getBackendVersion(credentials));
var apiVersionHandler = new Properties();
apiVersionHandler.load(BackboneController.class.getResourceAsStream("/project.properties"));
return Response.status(Status.OK)
.entity(new GenericResponse(
new VersionResponseDto(backendVersionHandler.getBackend(),
apiVersionHandler.getProperty("version"))))
.build();
}
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("url")
public Response getUrl(
@HeaderParam("Authorization") String token) throws Exception {
var credentials = _authenticationHelper.detokenizeCredentials(token);
var urlDto = new UrlResponseDto(_backboneService.getUrl(credentials));
return Response.status(Status.OK).entity(new GenericResponse(urlDto)).build();
}
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("context-path-to-etc")
public Response getContextPathToEtc(
@HeaderParam("Authorization") String token) throws Exception {
var credentials = _authenticationHelper.detokenizeCredentials(token);
if (!_backboneService.areCredentialsValid(credentials))
throw new WebApplicationException(Response.status(Status.UNAUTHORIZED).build());
var contextPathToEtcDto = new ContextPathToEtcResponseDto(_environmentService.getEtcPathInContext());
return Response.status(Status.OK).entity(new GenericResponse(contextPathToEtcDto)).build();
}
}
The problem is related with the IEnvironmentService, which injects IEnvironmentRepository. Here are the interface and the class itself:
@Contract
public interface IEnvironmentService {
public void environmentSet(Credentials credentials, String key, String value) throws Exception;
public void environmentUnset(Credentials credentials, String key) throws Exception;
public String environmentGet(Credentials credentials, String key) throws Exception;
public String getEtcPathInContext();
}
@Service
public class EnvironmentService implements IEnvironmentService {
@Inject
private EnvironmentRepository _environmentRepository;
@Override
public void environmentSet(Credentials credentials, String key, String value) throws Exception {
_environmentRepository.environmentSet(credentials, key, value);
}
@Override
public void environmentUnset(Credentials credentials, String key) throws Exception {
_environmentRepository.environmentUnset(credentials, key);
}
@Override
public String environmentGet(Credentials credentials, String key) throws Exception {
return _environmentRepository.environmentGet(credentials, key);
}
@Override
public String getEtcPathInContext() {
return _environmentRepository.getEtcPathInContext();
}
}
IEnvironmentRepository and EnvironmentRepository here:
@Contract
public interface IEnvironmentRepository {
public void environmentSet(Credentials credentials, String key, String value) throws Exception;
public void environmentUnset(Credentials credentials, String key) throws Exception;
public String environmentGet(Credentials credentials, String key) throws Exception;
public String getEtcPathInContext();
}
@Service
public class EnvironmentRepository extends GenericRepository implements IEnvironmentRepository {
@Inject
private IContextFinder _contextFinder;
@Override
public void environmentSet(Credentials credentials, String key, String value) throws Exception {
_connector.execute(credentials.getUsername(), credentials.getPassword(),
String.format("SELECT backbone.environment_set(%s, %s)'", new SqlParameter("p_key", key),
new SqlParameter("p_value", value)));
}
@Override
public void environmentUnset(Credentials credentials, String key) throws Exception {
_connector.execute(credentials.getUsername(), credentials.getPassword(),
String.format("SELECT backbone.environment_unset(%s)", new SqlParameter("p_key", key)));
}
@Override
public String environmentGet(Credentials credentials, String key) throws Exception {
return _connector.queryText(credentials.getUsername(), credentials.getPassword(),
String.format("SELECT backbone.environment_get(%s)", new SqlParameter("p_key", key)));
}
@Override
public String getEtcPathInContext() {
return _contextFinder.getEtcPathInContext();
}
}
And at last, the abstract binder and the resource config:
public class BackboneBinder extends AbstractBinder {
@Override
protected void configure() {
bind(BackboneRepository.class).to(IBackboneRepository.class);
bind(BackboneService.class).to(IBackboneService.class);
bind(EnvironmentRepository.class).to(IEnvironmentRepository.class).in(PerLookup.class);
bind(EnvironmentService.class).to(IEnvironmentService.class);
bind(ContextFinder.class).to(IContextFinder.class);
bind(ParametersHandler.class).to(IParametersHandler.class);
bind(AuthenticationHelper.class).to(IAuthenticationHelper.class);
}
}
public class ApplicationConfiguration extends ResourceConfig {
public ApplicationConfiguration() {
// Dependencies binders
register(new BackboneBinder());
packages("com.bfaconsultora");
}
}
Now, when I consume the resource via postman, I get the following error:
javax.servlet.ServletException: A MultiException has 5 exceptions. They are:
1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=EnvironmentRepository,parent=EnvironmentService,qualifiers={},position=-1,optional=false,self=false,unqualified=null,804331421)
2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of com.bfaconsultora.rest.backbone.services.EnvironmentService errors were found
3. java.lang.IllegalStateException: Unable to perform operation: resolve on com.bfaconsultora.rest.backbone.services.EnvironmentService
4. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of com.bfaconsultora.rest.backbone.controllers.BackboneController errors were found
5. java.lang.IllegalStateException: Unable to perform operation: resolve on com.bfaconsultora.rest.backbone.controllers.BackboneController
org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:408)
org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:346)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:365)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:318)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:205)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
I'm really lost with this. If I remove the injection of the IEnvironmentRepository in the EnvronmentService class, and replace it with a regular new EnvironmentRepository() everything works OK. The strange thing is that with Backbone Service and Repository, which are very similar to Environment stuff, injection works just fine.
Could you please point me in the right direction?
Thank you in advance.
Regards