////
This guide is maintained in the main Quarkus repository
and pull requests should be submitted there:
https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc
////
= Quarkus Extension for Spring DI API

include::./attributes.adoc[]

While users are encouraged to use CDI annotations for injection, Quarkus provides a compatibility layer for Spring dependency injection in the form of the `spring-di` extension.

This guide explains how a Quarkus application can leverage the well known Dependency Injection annotations included in the Spring Framework.

== Prerequisites

include::includes/devtools/prerequisites.adoc[]

== Solution

We recommend that you follow the instructions in the next sections and create the application step by step.
However, you can go right to the completed example.

Clone the Git repository: `git clone {quickstarts-clone-url}`, or download an {quickstarts-archive-url}[archive].

The solution is located in the `spring-di-quickstart` {quickstarts-tree-url}/spring-di-quickstart[directory].

== Creating the Maven project

First, we need a new project. Create a new project with the following command:

:create-app-artifact-id: spring-di-quickstart
:create-app-extensions: resteasy,spring-di
include::includes/devtools/create-app.adoc[]

This command generates a project which imports the `spring-di` extension.

If you already have your Quarkus project configured, you can add the `spring-di` extension
to your project by running the following command in your project base directory:

:add-extension-extensions: spring-di
include::includes/devtools/extension-add.adoc[]

This will add the following to your build file:

[source,xml,role="primary asciidoc-tabs-target-sync-cli asciidoc-tabs-target-sync-maven"]
.pom.xml
----
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-spring-di</artifactId>
</dependency>
----

[source,gradle,role="secondary asciidoc-tabs-target-sync-gradle"]
.build.gradle
----
implementation("io.quarkus:quarkus-spring-di")
----

== Add beans using Spring annotations

Let's proceed to create some beans using various Spring annotations.

First we will create a `StringFunction` interface that some of our beans will implement and which will be injected into another bean later on.
Create a `src/main/java/org/acme/spring/di/StringFunction.java` file and set the following content:

[source,java]
----
package org.acme.spring.di;

import java.util.function.Function;

public interface StringFunction extends Function<String, String> {

}
----

With the interface in place, we will add an `AppConfiguration` class which will use the Spring's Java Config style for defining a bean.
It will be used to create a `StringFunction` bean that will capitalize the text passed as parameter.
Create a `src/main/java/org/acme/spring/di/AppConfiguration.java` file with the following content:

[source,java]
----
package org.acme.spring.di;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfiguration {

    @Bean(name = "capitalizeFunction")
    public StringFunction capitalizer() {
        return String::toUpperCase;
    }
}
----
As a Spring developer, you might be tempted to add the `@ComponentScan` annotation in order to define specific packages to scan for additional beans. Do note that `@ComponentScan` is entirely unnecessary since Quarkus performs xref:cdi-reference.adoc#bean_discovery[bean discovery] only in `annotated` mode with no visibility boundaries. Moreover, note that the bean discovery in Quarkus happens at build time.
In the same vein, Quarkus does not support the Spring `@Import` annotation.

Now we define another bean that will implement `StringFunction` using Spring's stereotype annotation style.
This bean will effectively be a no-op bean that simply returns the input as is.
Create a `src/main/java/org/acme/spring/di/NoOpSingleStringFunction.java` file and set the following content:

[source,java]
----
package org.acme.spring.di;

import org.springframework.stereotype.Component;

@Component("noopFunction")
public class NoOpSingleStringFunction implements StringFunction {

    @Override
    public String apply(String s) {
        return s;
    }
}
----

Quarkus also provides support for injecting configuration values using Spring's `@Value` annotation.
To see that in action, first edit the `src/main/resources/application.properties` with the following content:

[source,properties]
----
# Your configuration properties
greeting.message = hello
----

Next create a new Spring bean in `src/main/java/org/acme/spring/di/MessageProducer.java` with the following content:


[source,java]
----
package org.acme.spring.di;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class MessageProducer {

    @Value("${greeting.message}")
    String message;

    public String getPrefix() {
        return message;
    }
}
----

The final bean we will create ties together all the previous beans.
Create a `src/main/java/org/acme/spring/di/GreeterBean.java` file and copy the following content:

[source,java]
----
package org.acme.spring.di;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class GreeterBean {

    private final MessageProducer messageProducer;

    @Autowired
    @Qualifier("noopFunction")
    StringFunction noopStringFunction;

    @Autowired
    @Qualifier("capitalizeFunction")
    StringFunction capitalizerStringFunction;

    @Value("${greeting.suffix:!}")
    String suffix;

    public GreeterBean(MessageProducer messageProducer) {
        this.messageProducer = messageProducer;
    }

    public String greet(String name) {
        final String initialValue = messageProducer.getPrefix() + " " + name + suffix;
        return noopStringFunction.andThen(capitalizerStringFunction).apply(initialValue);
    }
}
----

In the code above, we see that both field injection and constructor injection are being used (note that constructor injection does not need the `@Autowired` annotation since there is a single constructor).
Furthermore, the `@Value` annotation on `suffix` has also a default value defined, which in this case will be used since we have not defined `greeting.suffix` in `application.properties`.


=== Create the JAX-RS resource

Create the `src/main/java/org/acme/spring/di/GreeterResource.java` file with the following content:

[source,java]
----
package org.acme.spring.di;

import org.springframework.beans.factory.annotation.Autowired;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/greeting")
public class GreeterResource {

    @Autowired
    GreeterBean greeterBean;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return greeterBean.greet("world");
    }
}
----

== Update the test

We also need to update the functional test to reflect the changes made to the endpoint.
Edit the `src/test/java/org/acme/spring/di/GreetingResourceTest.java` file and change the content of the `testHelloEndpoint` method to:


[source, java]
----
import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.is;

@QuarkusTest
public class GreetingResourceTest {

    @Test
    public void testHelloEndpoint() {
        given()
            .when().get("/greeting")
            .then()
                .statusCode(200)
                .body(is("HELLO WORLD!"));
    }

}
----

== Package and run the application

Run the application with:

include::includes/devtools/dev.adoc[]

Open your browser to http://localhost:8080/greeting.

The result should be: `HELLO WORLD!`.

== Run the application as a native

You can of course create a native image using instructions similar to xref:building-native-image.adoc[this] guide.

== Important Technical Note

Please note that the Spring support in Quarkus does not start a Spring Application Context nor are any Spring infrastructure classes run.
Spring classes and annotations are only used for reading metadata and / or are used as user code method return types or parameter types.
What that means for end users, is that adding arbitrary Spring libraries will not have any effect. Moreover Spring infrastructure
classes (like `org.springframework.beans.factory.config.BeanPostProcessor` , `org.springframework.context.ApplicationContext` for example) will not be executed.
Regarding the dependency injection in particular, Quarkus uses a Dependency Injection mechanism (called ArC) based on the https://jakarta.ee/specifications/cdi/2.0/cdi-spec-2.0.html[Contexts and Dependency Injection for Java 2.0] specification. If you want to learn more about it we recommend you to read the xref:cdi.adoc[Quarkus introduction to CDI] and the xref:cdi-reference.adoc#arc-configuration-reference[CDI reference guide]
The various Spring Boot test features are not supported by Quarkus. For testing purposes, please, check the xref:getting-started-testing.adoc[Quarkus testing guide].

== Conversion Table

The following table shows how Spring DI annotations can be converted to CDI and / or MicroProfile annotations.

|===
|Spring |CDI / MicroProfile |Comments

|@Autowired
|@Inject
|

|@Qualifier
|@Named
|

|@Value
|@ConfigProperty
|@ConfigProperty doesn't support an expression language the way @Value does, but makes the typical use cases much easier to handle

|@Component
|@Singleton
|By default Spring stereotype annotations are singleton beans

|@Service
|@Singleton
|By default Spring stereotype annotations are singleton beans

|@Repository
|@Singleton
|By default Spring stereotype annotations are singleton beans

|@Configuration
|@ApplicationScoped
|In CDI a producer bean isn't limited to the application scope, it could just as well be @Singleton or @Dependent

|@Bean
|@Produces
|

|@Scope
|
|Doesn't have a one-to-one mapping to a CDI annotation. Depending on the value of @Scope, one of the @Singleton, @ApplicationScoped, @SessionScoped, @RequestScoped, @Dependent could be used

|@ComponentScan
|
|Doesn't have a one-to-one mapping to a CDI annotation. It is not used in Quarkus because Quarkus does all classpath scanning at build time.

|@Import
|
|Doesn't have a one-to-one mapping to a CDI annotation.
|===

== More Spring guides

Quarkus has more Spring compatibility features. See the following guides for more details:

* xref:spring-web.adoc[Quarkus - Extension for Spring Web]
* xref:spring-data-jpa.adoc[Quarkus - Extension for Spring Data JPA]
* xref:spring-data-rest.adoc[Quarkus - Extension for Spring Data REST]
* xref:spring-security.adoc[Quarkus - Extension for Spring Security]
* xref:spring-cloud-config-client.adoc[Quarkus - Reading properties from Spring Cloud Config Server]
* xref:spring-boot-properties.adoc[Quarkus - Extension for Spring Boot properties]
* xref:spring-cache.adoc[Quarkus - Extension for Spring Cache]
* xref:spring-scheduled.adoc[Quarkus - Extension for Spring Scheduled]
