quarkusio/quarkus · error · RuntimeException
Usage of '@Inject' is not allowed in 'jakarta.ws.rs.core.App
Error message
Usage of '@Inject' is not allowed in 'jakarta.ws.rs.core.Application' classes. Offending class is '${jakartaRestApplicationClass.name()}' What it means
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.
Source
Thrown at extensions/resteasy-classic/resteasy-server-common/deployment/src/main/java/io/quarkus/resteasy/server/common/deployment/ResteasyServerCommonProcessor.java:1092
annotatedProviders.removeAll(excludedClasses);
} else {
annotatedProviders.retainAll(allowedClasses);
}
providers.addAll(annotatedProviders);
contributedProviders.addAll(annotatedProviders);
return new JaxrsProvidersToRegisterBuildItem(
providers, contributedProviders, annotatedProviders, jaxrsProvidersToRegisterBuildItem.useBuiltIn());
}
/**
* @return the set of classes returned by the methods {@link Application#getClasses()} and
* {@link Application#getSingletons()}.
*/
private Set<String> getAllowedClasses(ClassInfo jakartaRestApplicationClass) {
final Set<String> allowedClasses = new HashSet<>();
Application application;
if (jakartaRestApplicationClass.annotationsMap().containsKey(ResteasyDotNames.CDI_INJECT)) {
throw new RuntimeException(
"Usage of '@Inject' is not allowed in 'jakarta.ws.rs.core.Application' classes. Offending class is '"
+ jakartaRestApplicationClass.name() + "'");
}
String applicationClass = jakartaRestApplicationClass.name().toString();
try {
Class<?> appClass = Thread.currentThread().getContextClassLoader().loadClass(applicationClass);
application = (Application) appClass.getConstructor().newInstance();
Set<Class<?>> classes = application.getClasses();
if (!classes.isEmpty()) {
for (Class<?> klass : classes) {
allowedClasses.add(klass.getName());
}
}
classes = application.getSingletons().stream().map(Object::getClass).collect(Collectors.toSet());
if (!classes.isEmpty()) {
for (Class<?> klass : classes) {
allowedClasses.add(klass.getName());View on GitHub (pinned to e1c734241f)
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.
Example fix
// before
public class MyApp extends Application {
@Inject
SomeService service;
@Override public Set<Class<?>> getClasses() { return Set.of(service.endpoint()); }
}
// after
public class MyApp extends Application {
@Override public Set<Class<?>> getClasses() { return Set.of(MyEndpoint.class); }
} Defensive patterns
Strategy: validation
Validate before calling
static void assertNoInject(Class<?> appClass) {
for (Field f : appClass.getDeclaredFields()) {
if (f.isAnnotationPresent(jakarta.inject.Inject.class))
throw new IllegalStateException("@Inject not allowed in Application class: " + appClass.getName());
}
} Type guard
static boolean isCdiFreeApplication(Class<?> c) {
return Arrays.stream(c.getDeclaredFields())
.noneMatch(f -> f.isAnnotationPresent(jakarta.inject.Inject.class));
} Try / catch
// Deployment-time failure: cannot be caught at runtime. // Detect in CI with a unit test scanning the Application class for @Inject before building.
Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- More than one Application class: ${jakartaRestApplicationCla
- Unable to handle class: ${applicationClass}
- Non static nested resources classes are not supported: '
- Method '' of class '' contains multiple HTTP method annotati
- Resource method '%s#%s' can only have a single body paramete
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/47d5d9879cfad9c1.
Report an issue: GitHub.