Alan otomatik olarak bağlanamadı: Spring önyükleme uygulamasında RestTemplate


115

Başlatma sırasında yay önyükleme uygulamasını çalıştırırken istisnanın altına düşüyorum:

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)}

TestController'ımda RestTemplate'i otomatik kabloluyorum. Bağımlılık yönetimi için Maven kullanıyorum.

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>

1
Sorunuza olumlu oy vermek, çünkü her şey sihirli bir şekilde birbirine bağlı olduğunda a'nın sizin RestTemplateiçin otomatik olarak oluşturulmadığı açık değildir.
daniel.eichten

Olumlu oy verildi - Spring Boot'un kendi sayfasındaki eğitici, RestTemplate Bean oluşturma hakkında hiçbir şey söylemiyor !!
Matt

Yanıtlar:


177

Hatanın söylediği tam olarak bu. Herhangi bir RestTemplatefasulye yaratmadınız , bu yüzden hiçbirini otomatik olarak kablolayamaz. Bir ihtiyacınız RestTemplatevarsa, bir tane sağlamanız gerekir. Örneğin, TestMicroServiceApplication.java'ya aşağıdakileri ekleyin :

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

Unutmayın, Eureka için Spring bulut başlatıcısının önceki sürümlerinde, RestTemplatesizin için bir fasulye yaratıldı, ancak bu artık geçerli değil.


Cevabınız için çok teşekkürler. Bu yardımcı oldu!
Khuzi

20
Soruyu ve cevabınızı desteklediniz çünkü Diğer RestTemplateher şey sizin için sihirli bir şekilde oluşturulduğunda ve bağlantılı olduğunda manuel olarak bir tane oluşturmanız gerektiği açık değil . Özellikle, daha önce otomatik yapılandırılmış bir sağlayan yay-bulutu kullanılıyorsa RestTemplate. ;-)
daniel.eichten

2
Dürüst olmak gerekirse, bu konuyu buraya foruma koymamın nedeni buydu. RestTemplate'in benim için bağlanmasını bekliyordum. :-) Eureka bağımlılığını POM.xml'ye dahil ettiğimde bu iyi çalışıyordu. RestTemplate fasulyesini tanımlamadan iyi çalışıyordu. Eureka sınıflarından biri bu fasulyeyi tanımlamış olabilir.
Khuzi

4
Sadece bir güncelleme. Spring Boot 1.4.0'dan bulut sunucuları RestTemplateBuilderyönetmek için kullanılabilir RestTemplate. Buradaki örnek spring.io/guides/gs/consuming-rest
Mensur

Henüz SB 1.4.0'a yükseltemiyorum. Bunu 1.3.8.RELEASE ile yapmak istiyorum ama @ g00glen00b çözümü benim için çalışmadı. Ben de spring-cloud-netflixartifactid sürümü ile kullanıyorum 1.1.5.RELEASE. Benim RestTemplate bir gelen çağrılan @RestControllerkullandığı java sınıfının @Autowirediçin RestTemplate. Birisi lütfen yardım edebilir mi ?
ZeroGraviti

35

Bağlı olarak kullanıyorsanız ve bir tanımlamak nasıl neyi versiyonları etkileyecektir hangi teknolojilerin RestTemplatesizin de @Configurationsınıfta.

Spring> = 4, Spring Boot olmadan

Basitçe bir @Bean:

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

Yaylı Önyükleme <= 1.3

Bir tane tanımlamanıza gerek yok, Spring Boot sizin için otomatik olarak birini tanımlar.

Yaylı Önyükleme> = 1.4

Spring Boot artık otomatik olarak a tanımlamaz, RestTemplatebunun yerine RestTemplateBuilderoluşturulan RestTemplate üzerinde daha fazla kontrole izin vermenizi sağlar. Bir oluşturmak RestTemplateBuilderiçin @Beanyönteminize argüman olarak enjekte edebilirsiniz RestTemplate:

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

Sınıfınızda kullanmak

@Autowired
private RestTemplate restTemplate;

Referans


8

TestRestTemplate, birim testinizde geçerli bir seçenekse, bu belge ilgili olabilir

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

Kısa cevap: kullanılıyorsa

@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)

o @Autowiredzaman çalışacak. Kullanılıyorsa

@SpringBootTest(webEnvironment=WebEnvironment.MOCK)

sonra bunun gibi bir TestRestTemplate oluşturun

private TestRestTemplate template = new TestRestTemplate();

1

Hata doğrudan RestTemplatefasulyenin bağlamda tanımlanmadığını ve fasulyeleri yükleyemediğini gösterir.

  1. RestTemplate için bir fasulye tanımlayın ve ardından kullanın
  2. RestTemplate'in yeni bir örneğini kullanın

Çekirdeğin RestTemplate için tanımlandığından eminseniz, yay önyükleme uygulaması tarafından yüklenen bağlamda bulunan çekirdekleri yazdırmak için aşağıdakileri kullanın

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

Bu, verilen ad / türe göre fasulyeyi içeriyorsa, o zaman her şey iyidir. Ya da yeni bir fasulye tanımlayın ve sonra onu kullanın.


1

RestTemplate örneklerinin genellikle kullanılmadan önce özelleştirilmesi gerektiğinden, Spring Boot tek bir otomatik yapılandırılmış RestTemplate çekirdeği sağlamaz.

RestTemplateBuilder , örneğin temel kimlik doğrulama veya engelleyiciler için dinlenme şablonu çekirdeğini yapılandırmak ve başlatmak için uygun bir yol sunar.

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


0

Lütfen iki şeyden emin olun:

1- @BeanYöntemle açıklama kullanın .

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

2- bu yöntemin kapsamı olmalıdır halka değil özel .

Tam Örnek -

@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

Aşağıdaki kodu kullanmak için benzer bir başarı elde etmenin en basit yolu ( referans ), ancak denetleyicilerde API çağrıları yapmamayı öneririm ( SOLID ilkeleri ). Ayrıca bu şekilde otomatik kablolama, geleneksel yöntemden daha iyi optimize edilmiştir.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
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 {

    private final RestTemplate restTemplate;


    @Autowired
    public TestController(RestTemplateBuilder builder) {
        this.restTemplate = builder.build();
    }

    @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";
    }
}

0

restTemplate'i enjekte etmeye çalışıyorsunuz ancak konfigürasyon sınıfı oluşturmanız gerekiyor. orada size yeni RestTemplate döndüren fasulye oluşturmanız gerekir, aşağıdaki örneğe bakın.

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


@Configuration
public class YourConfigClass {


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

}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.