Spring API Compatibility Extensions
|
This section documents Quarkus 3.39.x (current) with 3.33.x LTS as the production recommendation, on the Java 17+ baseline, as published at the official Quarkus guides — which are the reference these pages are written and verified against. Quarkus 4 raises the baseline to Java 21 (first release candidate planned for end of September 2026, see the Quarkus blog); readers upgrading past 3.39.x/3.33.x LTS should expect that change. This content was generated with the assistance of AI and should be verified against those official guides before being relied on in production. This section’s bibliography lists the reference material consulted while preparing these pages. |
Quarkus ships a family of Spring API compatibility extensions that let existing Spring-annotated code compile
and run on Quarkus with little or no change to that code — but they implement the annotation APIs, translated
onto Quarkus’s own build-time-resolved machinery, not Spring itself. There is no Spring ApplicationContext
anywhere underneath, no Spring BeanFactory, and no guarantee that an arbitrary third-party Spring library will
work simply because it is on the classpath. This page scopes each compatibility extension honestly — what it
supports and what it deliberately does not — maps each Spring idiom to the Quarkus-native equivalent it sits in
front of, and lays out a realistic migration path for an existing Spring Boot service.
What "compatibility" actually means here
Every extension below recognizes a specific, fixed set of Spring annotations at build time and translates each
one into a call onto the corresponding Quarkus subsystem — CDI/ArC for dependency injection, Quarkus REST for
web endpoints, the Quarkus Scheduler for @Scheduled, and so on. Recognizing an annotation is not the same as
implementing the framework it came from: none of these extensions load Spring’s own core, instantiate a
GenericApplicationContext, or support Spring’s runtime bean-post-processing SPI, ApplicationContextAware,
Environment abstraction, or arbitrary @Conditional implementations. A Spring library that expects to
participate in a real Spring context (registering its own BeanFactoryPostProcessor, reading
ApplicationContext events, or relying on Spring AOP proxying beyond what the compatibility layer recognizes)
will not work on Quarkus regardless of which compatibility extensions are added.
The extensions
| Extension | Supports |
|---|---|
Does not support |
|
|
A real |
|
|
Spring MVC’s |
|
Spring Data-style repository interfaces ( |
The full Spring Data infrastructure — no QueryDSL integration, a narrower derived-query-method keyword vocabulary than upstream Spring Data JPA, and no custom-repository-fragment auto-wiring beyond the basic interface-inheritance pattern. |
|
Exposing a |
Spring Data REST’s full HATEOAS feature set (HAL/ALPS representations, projection/excerpt configuration, event-based hooks) — treat this as a convenience subset, not a like-for-like port. |
|
|
Spring’s own |
|
A subset of Spring Security’s method-security annotations ( |
Spring Security’s filter-chain configuration ( |
|
|
Spring’s |
|
|
Spring’s |
|
|
Spring Boot’s relaxed-binding edge cases in full, its |
|
Fetching configuration from an existing Spring Cloud Config Server as one more Quarkus config source, useful specifically for adopting Quarkus incrementally alongside a Spring Cloud estate that already centralizes configuration this way. |
Any other part of Spring Cloud (service discovery, circuit breakers, gateway) — Quarkus’s own equivalents for those concerns (Fault Tolerance and Resilience, Kubernetes and OpenShift) are unrelated to this extension. |
|
A small set of Spring Test annotations recognized on top of
|
|
Mapping table: Spring idiom to Quarkus-native equivalent
| Spring idiom | Quarkus-native equivalent | Notes |
|---|---|---|
|
|
Direct, mechanical rename in the common case; see CDI and the Programming Model. |
|
|
Also mechanical, though the default scope differs conceptually — CDI has no single "just a bean" stereotype the way Spring’s component-scanning does; picking the right scope is a small, deliberate step. |
|
|
Mechanical for a plain CRUD-style controller; a controller with custom `HandlerInterceptor`s or content-negotiation configuration needs a rewrite against Quarkus REST’s own extension points. |
|
|
Same annotation name, different package and underlying transaction manager — an import change more than a logic change for the common propagation cases. |
|
|
Cron/fixedRate/fixedDelay semantics carry over directly; see Scheduling and Mail. |
|
|
Same shape, different annotation names and package — see Caching. |
|
|
A |
|
|
A simple role check maps directly; a |
|
|
Programmatic context lookups are a code smell in CDI the same way they are increasingly discouraged in modern Spring — a genuine migration is the moment to remove them, not translate them. |
Spring AOP |
A CDI interceptor ( |
Conceptually equivalent, covered on CDI and the Programming Model, but the binding mechanism (interceptor-binding annotation vs. pointcut expression) is different enough to need a genuine rewrite, not a search-and-replace. |
A realistic migration path
What transfers close to annotation-for-annotation, once the corresponding compatibility extension is added:
simple @Component/@Service/@Autowired wiring, a CRUD-shaped @RestController, @Transactional service
methods with ordinary propagation, @Scheduled jobs, and @Cacheable/@CacheEvict caching. A service built
mostly from these idioms, with no deep Spring-specific configuration, can often be recompiled against the
compatibility extensions and run with only import and small annotation-attribute changes.
What must be rewritten, not translated: Spring Security’s filter-chain configuration and anything beyond
simple role checks in @PreAuthorize; Spring AOP pointcut expressions beyond what a CDI interceptor binding
naturally expresses; any code that calls ApplicationContext/BeanFactory directly; Spring Boot Actuator
(Quarkus’s own observability stack, Observability, is the replacement);
Spring Cloud beyond the config-client extension above; and Spring WebFlux’s Mono/Flux-based reactive
controllers, which have no compatibility-extension equivalent at all — a reactive Quarkus REST endpoint is
written against Uni/Multi from the start (Reactive
Programming and Mutiny).
When a rewrite is cheaper than a port: a service whose value is concentrated in Spring-specific infrastructure — heavy custom Spring AOP, a deep Spring Cloud microservices setup (service discovery, a Spring Cloud Gateway front end, Spring Cloud Stream bindings), or WebFlux-based reactive pipelines — typically costs more effort to keep working through the compatibility layer than to rewrite directly against Quarkus’s native equivalents, because the compatibility extensions were never meant to replicate that infrastructure. A service whose logic is mostly plain CRUD, straightforward REST endpoints, and ordinary transactional/scheduled/cached methods is the profile where the compatibility extensions genuinely shorten a migration; anything past that profile is worth prototyping natively before committing to a port.