165

I am getting below exception while running spring boot application during start up:

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

I am autowiring RestTemplate in my TestController. I am using Maven for dependency managagement.

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>
Khuzi
  • 2,542
  • 3
  • 12
  • 24

9 Answers9

252

It's exactly what the error says. You didn't create any RestTemplate bean, so it can't autowire any. If you need a RestTemplate you'll have to provide one. For example, add the following to TestMicroServiceApplication.java:

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

Note, in earlier versions of the Spring cloud starter for Eureka, a RestTemplate bean was created for you, but this is no longer true.

Dmitry Rakovets
  • 358
  • 1
  • 3
  • 13
g00glen00b
  • 38,039
  • 13
  • 89
  • 120
  • Thanks a lot for your reply. This helped! – Khuzi Mar 22 '16 at 11:00
  • 41
    Upvoted the question and your answer cause It's not obvious that you have to manually create a `RestTemplate` when everything else is magically created and linked for you. Especially if one used spring-cloud before which provides an autoconfigured `RestTemplate`. ;-) – daniel.eichten Mar 22 '16 at 11:31
  • 2
    Honestly, that was the reason I put this issue here in forum. I was expecting RestTemplate to be linked for me. :-) This was working fine when I had included Eureka dependency in POM.xml. It was working fine without defining RestTemplate bean. One of the classes of Eureka might have defined this bean or so. – Khuzi Mar 23 '16 at 03:52
  • 7
    Just an update. From Spring Boot 1.4.0 `RestTemplateBuilder` can be used for managing `RestTemplate` instances. Example here https://spring.io/guides/gs/consuming-rest/ – Mensur Sep 27 '16 at 10:58
  • I cant yet upgrade to SB 1.4.0. I want to do this with 1.3.8.RELEASE but @g00glen00b solution didn't work for me. I am also using `spring-cloud-netflix` artifactid with version `1.1.5.RELEASE`. My RestTemplate is being called from an `@RestController` java class which uses `@Autowired` for the `RestTemplate`. Can someone please help ? – ZeroGraviti Oct 20 '16 at 20:02
  • @ZeroGraviti, can you create a new question? I think this problem is unrelated to this question/answer. – g00glen00b Oct 21 '16 at 12:42
  • This answer does not work for Spring Boot 1.4.x java.lang.IllegalStateException: Test classes cannot include @Bean methods – Avec Nov 30 '16 at 21:53
  • @Avec this question/answer is not about test classes though. – g00glen00b Dec 01 '16 at 17:58
  • Autowired* (just add method) – raffian Feb 23 '18 at 19:33
56

Depending on what technologies you're using and what versions will influence how you define a RestTemplate in your @Configuration class.

Spring >= 4 without Spring Boot

Simply define an @Bean:

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

Spring Boot <= 1.3

No need to define one, Spring Boot automatically defines one for you.

Spring Boot >= 1.4

Spring Boot no longer automatically defines a RestTemplate but instead defines a RestTemplateBuilder allowing you more control over the RestTemplate that gets created. You can inject the RestTemplateBuilder as an argument in your @Bean method to create a RestTemplate:

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

Using it in your class

@Autowired
private RestTemplate restTemplate;

Reference

Sahil Chhabra
  • 9,711
  • 4
  • 62
  • 62
11

If a TestRestTemplate is a valid option in your unit test, this documentation might be relevant

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

Short answer: if using

@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)

then @Autowired will work. If using

@SpringBootTest(webEnvironment=WebEnvironment.MOCK)

then create a TestRestTemplate like this

private TestRestTemplate template = new TestRestTemplate();
riccardo.cardin
  • 7,325
  • 3
  • 51
  • 93
Mark K.
  • 391
  • 3
  • 3
9
  • You must add @Bean public RestTemplate restTemplate(RestTemplateBuilder builder){ return builder.build(); }
2

Since RestTemplate instances often need to be customized before being used, Spring Boot does not provide any single auto-configured RestTemplate bean.

RestTemplateBuilder offers proper way to configure and instantiate the rest template bean, for example for basic auth or interceptors.

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
    return builder
            .basicAuthorization("user", "name") // Optional Basic auth example
            .interceptors(new MyCustomInterceptor()) // Optional Custom interceptors, etc..
            .build();
}
Dmitry Rakovets
  • 358
  • 1
  • 3
  • 13
2

you are trying to inject the restTemplate but you need to create configuration class . then there you need to create bean that return you new RestTemplate see the below example.

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


@Configuration
public class YourConfigClass {


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

}
Fazle Subhan
  • 171
  • 1
  • 5
1

Error points directly that RestTemplate bean is not defined in context and it cannot load the beans.

  1. Define a bean for RestTemplate and then use it
  2. Use a new instance of the RestTemplate

If you are sure that the bean is defined for the RestTemplate then use the following to print the beans that are available in the context loaded by spring boot application

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

If this contains the bean by the name/type given, then all good. Or else define a new bean and then use it.

Vinay Veluri
  • 6,317
  • 5
  • 30
  • 54
1

The simplest way I was able to achieve a similar feat to use the code below (reference), but I would suggest not to make API calls in controllers(SOLID principles). Also autowiring this way is better optimsed than the traditional way of doing it.

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";
    }
}
Padi kodwo
  • 364
  • 3
  • 5
  • do you think thar the getForObject() violate the SOLID principales ? Wich one ? – Hamdy Sep 17 '21 at 09:45
  • @Hamdy you violate the SOLID principle by putting your main logic in the controller ... controllers are meant to be entry points for your code not processors of the request. in spring you will usually use a service class for such functions. – Padi kodwo Apr 09 '22 at 11:58
0

Please make sure two things:

1- Use @Bean annotation with the method.

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

2- Scope of this method should be public not private.

Complete Example -

@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();
}
}
Harun Diluka Heshan
  • 1,079
  • 2
  • 18
  • 28
vineet
  • 19
  • 2