web-dev-qa-db-fra.com

Champ autowire impossible: RestTemplate dans l'application d'amorçage Spring

Je reçois une exception ci-dessous lors de l'exécution de l'application Spring Boot au démarrage:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.web.client.RestTemplate com.micro.test.controller.TestController.restTemplate; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.web.client.RestTemplate] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Je nage automatiquement RestTemplate dans mon TestController. J'utilise Maven pour la gestion de la dépendance.

TestMicroServiceApplication.Java

package com.micro.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class TestMicroServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(TestMicroServiceApplication.class, args);
    }
}

TestController.Java

    package com.micro.test.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class TestController {

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping(value="/micro/order/{id}",
        method=RequestMethod.GET,
        produces=MediaType.ALL_VALUE)
    public String placeOrder(@PathVariable("id") int customerId){

        System.out.println("Hit ===> PlaceOrder");

        Object[] customerJson = restTemplate.getForObject("http://localhost:8080/micro/customers", Object[].class);

        System.out.println(customerJson.toString());

        return "false";
    }

}

POM.xml

    <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.Apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.Apache.org/POM/4.0.0 http://maven.Apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.micro.test</groupId>
    <artifactId>Test-MicroService</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>Test-MicroService</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <Java.version>1.8</Java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>
81
Khuzi

C'est exactement ce que dit l'erreur. Vous n'avez créé aucun bean RestTemplate, il ne peut donc pas en renvoyer automatiquement. Si vous avez besoin d'un RestTemplate vous devrez en fournir un. Par exemple, ajoutez ce qui suit à TestMicroServiceApplication.Java:

@Bean
public RestTemplate restTemplate() {
    return new RestTemplate();
}

Notez que dans les versions précédentes du démarreur de nuage Spring pour Eureka, un bean RestTemplate a été créé pour vous, mais ce n’est plus le cas.

117
g00glen00b

Selon les technologies que vous utilisez et les versions qui influenceront la manière dont vous définissez une RestTemplate dans votre classe @Configuration.

Spring> = 4 sans Spring Boot

Définissez simplement un @Bean:

@Bean
public RestTemplate restTemplate() {
    return new RestTemplate();
}

Spring Boot <= 1.3

Nul besoin d'en définir un, Spring Boot en définit automatiquement un pour vous.

Spring Boot> = 1,4

Spring Boot ne définit plus automatiquement un RestTemplate mais à la place un RestTemplateBuilder, ce qui vous permet de mieux contrôler le RestTemplate créé. Vous pouvez injecter la RestTemplateBuilder en tant qu'argument dans votre méthode @Bean pour créer une RestTemplate:

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
   // Do any additional configuration here
   return builder.build();
}

L'utiliser dans votre classe

@Autowired
private RestTemplate restTemplate;

référence

18
Sahil Chhabra

Si un TestRestTemplate est une option valide dans votre test unitaire, cette documentation peut être pertinente

http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#boot-features-rest-templates-test-utility

Réponse courte: si vous utilisez

@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)

alors @Autowired fonctionnera. Si vous utilisez

@SpringBootTest(webEnvironment=WebEnvironment.MOCK)

puis créez un TestRestTemplate comme celui-ci

private TestRestTemplate template = new TestRestTemplate();
7
Mark K.

Comme les instances RestTemplate doivent souvent être personnalisées avant d'être utilisées, Spring Boot ne fournit aucun bean RestTemplate auto-configuré.

RestTemplateBuilder offre le moyen approprié de configurer et d'instancier le bean de modèle de repos, par exemple pour une autorisation de base ou des intercepteurs.

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
    return builder
                .basicAuthorization("user", "name") // Optional Basic auth example
                .interceptors(new MyCustomInterceptor()) // Optional Custom interceptors, etc..
                .build();
}
1
Pierrick HYMBERT

Error signale directement que le bean RestTemplate n'est pas défini dans le contexte et qu'il ne peut pas charger les beans.

  1. Définir un bean pour RestTemplate puis l'utiliser
  2. Utiliser une nouvelle instance de RestTemplate

Si vous êtes sûr que le bean est défini pour RestTemplate, utilisez ce qui suit pour imprimer les beans disponibles dans le contexte chargé par l'application Spring Boot.

ApplicationContext ctx = SpringApplication.run(Application.class, args);
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
    System.out.println(beanName);
}

Si cela contient le haricot du nom/type donné, alors tout va bien. Sinon, définissez un nouveau haricot et utilisez-le.

1
VinayVeluri

S'il vous plaît assurez-vous deux choses:

1- Utilisez l'annotation @Bean avec la méthode.

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder){
    return builder.build();
}

2- La portée de cette méthode devrait être public pas privé.

Exemple complet -

@Service
public class MakeHttpsCallImpl implements MakeHttpsCall {

@Autowired
private RestTemplate restTemplate;

@Override
public String makeHttpsCall() {
    return restTemplate.getForObject("https://localhost:8085/onewayssl/v1/test",String.class);
}

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder){
    return builder.build();
}
}
0
vineet