You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 11/Jersey/HK2依赖注入异常问题求助

Java 11/Jersey/HK2 依赖注入问题排查

在Java 11/Jersey/HK2环境下,资源类BackboneController注入IEnvironmentService等服务时出现依赖注入异常。其中IEnvironmentService的实现类EnvironmentService通过@Inject注入EnvironmentRepository失败,但将注入改为手动new EnvironmentRepository()可正常运行;结构类似的BackboneService与BackboneRepository注入却能正常工作。

相关代码

资源类 BackboneController

@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();
    }
}

IEnvironmentService 接口与实现

@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 接口与实现

@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();
    }
}

抽象绑定器与资源配置类

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");
    }
}

异常信息

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)

排查方向

  • 检查注入类型匹配:EnvironmentService中直接注入了实现类EnvironmentRepository,但绑定器仅配置了EnvironmentRepository.class到IEnvironmentRepository.class的映射,HK2不会自动将实现类本身注册到容器。对比BackboneService,其注入的是接口IBackboneRepository,与绑定规则匹配,所以能正常注入。
  • 补充实现类绑定:在BackboneBinder的configure()方法中添加bind(EnvironmentRepository.class).in(PerLookup.class);,显式将EnvironmentRepository实现类注册到HK2容器,让注入实现类的代码能找到实例。
  • 统一注入接口:修改EnvironmentService的注入代码为@Inject private IEnvironmentRepository _environmentRepository;,遵循依赖倒置原则,同时直接匹配现有绑定规则,这也是Backbone组件正常工作的核心原因。
  • 检查父类依赖:EnvironmentRepository继承自GenericRepository,确认GenericRepository中的_connector等依赖是否被正确注入,若父类存在未解决的依赖,会导致子类无法被实例化。
  • 验证扫描与绑定优先级:ApplicationConfiguration中调用packages("com.bfaconsultora")会让HK2自动扫描带@Service注解的类,但手动绑定的规则优先级更高。确认EnvironmentRepository的@Service注解是否生效,以及是否与手动绑定存在冲突。

内容的提问来源于stack exchange,提问作者Germán C. Basisty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 03:54:29