{"record":{"id":"f3a4a4aaa38decd3","repo":"hibernate/hibernate-orm","slug":"encountered-injectservice-on-method-with-unexpect","errorCode":null,"errorMessage":"Encountered @InjectService on method with unexpected number of parameters","messagePattern":"Encountered @InjectService on method with unexpected number of parameters","errorType":"exception","errorClass":"ServiceDependencyException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/service/internal/AbstractServiceRegistryImpl.java","lineNumber":339,"sourceCode":"\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\ttry {\n\t\t\t\tinjectionMethod.invoke( service, dependantService );\n\t\t\t}\n\t\t\tcatch ( Exception e ) {\n\t\t\t\tthrow new ServiceDependencyException( \"Cannot inject dependency service\", e );\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static Class<? extends Service> dependentServiceRole(\n\t\t\t@Nonnull Method injectionMethod,\n\t\t\t@Nonnull InjectService injectService) {\n\t\tfinal var parameterTypes = injectionMethod.getParameterTypes();\n\t\tif ( injectionMethod.getParameterCount() != 1 ) {\n\t\t\tthrow new ServiceDependencyException(\n\t\t\t\t\t\"Encountered @InjectService on method with unexpected number of parameters\"\n\t\t\t);\n\t\t}\n\n\t\tfinal var dependentServiceRole = injectService.serviceRole();\n\t\tif ( dependentServiceRole == null\n\t\t\t\t|| Void.class.equals( dependentServiceRole )  // old default value\n\t\t\t\t|| Service.class.equals( dependentServiceRole ) ) {  // new default value\n\t\t\treturn (Class<? extends Service>) parameterTypes[0];\n\t\t}\n\t\telse {\n\t\t\treturn dependentServiceRole;\n\t\t}\n\t}\n\n\t@Override\n\tpublic <R extends Service> void startService(ServiceBinding<R> serviceBinding) {\n\t\tif ( serviceBinding.getService() instanceof Startable startable ) {","sourceCodeStart":321,"sourceCodeEnd":357,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/service/internal/AbstractServiceRegistryImpl.java#L321-L357","documentation":"Hibernate's dependency scanner only accepts @InjectService on methods with exactly one parameter (the dependent service). dependentServiceRole() throws ServiceDependencyException at registry build time when it finds an annotated method with zero or two-plus parameters. This is a pure programming-error guard for code implementing Hibernate's service SPI.","triggerScenarios":"Annotating an overloaded convenience method, a method taking extra context arguments, or (mistakenly, since only methods are scanned) expecting field injection semantics; copy-pasting @InjectService onto a lifecycle method with multiple parameters.","commonSituations":"Writing a custom org.hibernate.service.Service without following the setter-injection convention; refactoring a single-arg setter into a multi-arg method while leaving the annotation.","solutions":["Change the annotated method to take exactly one parameter of the dependency type","If the role differs from the parameter type, specify it: @InjectService(serviceRole = MyRole.class)","Add a startup smoke test that builds the registry so signature errors fail the build, not production boot"],"exampleFix":"// before\n@InjectService\npublic void configure(JdbcServices jdbcServices, ClassLoaderService cls) { ... } // 2 params\n\n// after\n@InjectService\npublic void setJdbcServices(JdbcServices jdbcServices) { this.jdbcServices = jdbcServices; }\n\n@InjectService\npublic void setClassLoaderService(ClassLoaderService cls) { this.cls = cls; }","handlingStrategy":"validation","validationCode":"// startup self-check for service classes you ship\nfor (Method m : MyService.class.getDeclaredMethods()) {\n    if (m.isAnnotationPresent(InjectService.class)\n            && m.getParameterCount() != 1) {\n        throw new IllegalStateException(\n            \"@InjectService on non-single-arg method: \" + m);\n    }\n}","typeGuard":"boolean isValidInjectServiceMethod(Method m) {\n    return m.isAnnotationPresent(InjectService.class) && m.getParameterCount() == 1;\n}","tryCatchPattern":null,"preventionTips":["Follow the single-parameter setter convention for all @InjectService methods","Add a reflection-based build-time check for custom service classes","Registry smoke tests in CI catch signature mistakes before deployment"],"tags":["service-registry","dependency-injection","api-contract"],"backgroundTag":"dependency-injection-failure","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}