{"record":{"id":"47d5d9879cfad9c1","repo":"quarkusio/quarkus","slug":"usage-of-inject-is-not-allowed-in-jakarta-ws-r","errorCode":null,"errorMessage":"Usage of '@Inject' is not allowed in 'jakarta.ws.rs.core.Application' classes. Offending class is '${jakartaRestApplicationClass.name()}'","messagePattern":"Usage of '@Inject' is not allowed in 'jakarta\\.ws\\.rs\\.core\\.Application' classes\\. Offending class is '(.+?)'","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"extensions/resteasy-classic/resteasy-server-common/deployment/src/main/java/io/quarkus/resteasy/server/common/deployment/ResteasyServerCommonProcessor.java","lineNumber":1092,"sourceCode":"            annotatedProviders.removeAll(excludedClasses);\n        } else {\n            annotatedProviders.retainAll(allowedClasses);\n        }\n        providers.addAll(annotatedProviders);\n        contributedProviders.addAll(annotatedProviders);\n        return new JaxrsProvidersToRegisterBuildItem(\n                providers, contributedProviders, annotatedProviders, jaxrsProvidersToRegisterBuildItem.useBuiltIn());\n    }\n\n    /**\n     * @return the set of classes returned by the methods {@link Application#getClasses()} and\n     *         {@link Application#getSingletons()}.\n     */\n    private Set<String> getAllowedClasses(ClassInfo jakartaRestApplicationClass) {\n        final Set<String> allowedClasses = new HashSet<>();\n        Application application;\n        if (jakartaRestApplicationClass.annotationsMap().containsKey(ResteasyDotNames.CDI_INJECT)) {\n            throw new RuntimeException(\n                    \"Usage of '@Inject' is not allowed in 'jakarta.ws.rs.core.Application' classes. Offending class is '\"\n                            + jakartaRestApplicationClass.name() + \"'\");\n        }\n\n        String applicationClass = jakartaRestApplicationClass.name().toString();\n        try {\n            Class<?> appClass = Thread.currentThread().getContextClassLoader().loadClass(applicationClass);\n            application = (Application) appClass.getConstructor().newInstance();\n            Set<Class<?>> classes = application.getClasses();\n            if (!classes.isEmpty()) {\n                for (Class<?> klass : classes) {\n                    allowedClasses.add(klass.getName());\n                }\n            }\n            classes = application.getSingletons().stream().map(Object::getClass).collect(Collectors.toSet());\n            if (!classes.isEmpty()) {\n                for (Class<?> klass : classes) {\n                    allowedClasses.add(klass.getName());","sourceCodeStart":1074,"sourceCodeEnd":1110,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/resteasy-classic/resteasy-server-common/deployment/src/main/java/io/quarkus/resteasy/server/common/deployment/ResteasyServerCommonProcessor.java#L1074-L1110","documentation":"Quarkus evaluates a JAX-RS Application class at build time (getAllowedClasses instantiates it directly, outside CDI) to determine which classes it selects. Because the instance is created by plain reflection rather than the CDI container, @Inject fields would not be populated; to fail fast instead of producing nulls, the processor rejects Application classes annotated with @Inject with this RuntimeException.","triggerScenarios":"Declaring a class extending jakarta.ws.rs.core.Application whose fields or methods are annotated with jakarta.inject.Inject (detected via the CDI_INJECT annotation in the build index) while the RESTEasy Classic server deployment runs getAllowedClasses for it.","commonSituations":"Developers porting a Spring/CDI-style Application class and injecting a config bean or service to compute getClasses()/getSingletons(); quarkus-arc enforcing that Application classes are not beans.","solutions":["Remove all @Inject annotations from the Application class; return classes/set from getClasses() statically.","If you need injectable config, read it via ConfigProvider.getConfig() or @ConfigProperty on the resource classes instead.","Rely on Quarkus annotation-based discovery (@Path, @Provider) and drop the Application class, or use the classes config properties to select resources."],"exampleFix":"// before\npublic class MyApp extends Application {\n    @Inject\n    SomeService service;\n    @Override public Set<Class<?>> getClasses() { return Set.of(service.endpoint()); }\n}\n\n// after\npublic class MyApp extends Application {\n    @Override public Set<Class<?>> getClasses() { return Set.of(MyEndpoint.class); }\n}","handlingStrategy":"validation","validationCode":"static void assertNoInject(Class<?> appClass) {\n    for (Field f : appClass.getDeclaredFields()) {\n        if (f.isAnnotationPresent(jakarta.inject.Inject.class))\n            throw new IllegalStateException(\"@Inject not allowed in Application class: \" + appClass.getName());\n    }\n}","typeGuard":"static boolean isCdiFreeApplication(Class<?> c) {\n    return Arrays.stream(c.getDeclaredFields())\n        .noneMatch(f -> f.isAnnotationPresent(jakarta.inject.Inject.class));\n}","tryCatchPattern":"// Deployment-time failure: cannot be caught at runtime.\n// Detect in CI with a unit test scanning the Application class for @Inject before building.","preventionTips":["Never put @Inject fields in classes extending jakarta.ws.rs.core.Application","Use static getClasses()/getPackages() with hardcoded classes","Use ConfigProvider.getConfig() instead of injected config in Application classes"],"tags":["jaxrs","cdi","deployment","resteasy","build-time"],"backgroundTag":"inject-not-allowed-in-application-class","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}