199

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 management.

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>
3
  • 8
    Upvoting your question cause it is not obvious that when everything is magically linked a RestTemplate is not automatically created for you. Commented Mar 22, 2016 at 11:30
  • Upvoted - the tutorial on Spring Boot's own page says nothing about creating a RestTemplate Bean!! Commented Apr 14, 2016 at 15:16
  • 1
    Similar: stackoverflow.com/q/28024942/86967 Commented Jun 4, 2018 at 20:06

9 Answers 9

311

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

Since Spring boot 1.4, there's also a convenient builder that you can autowire and use to create a RestTemplate bean. The benefit is that you can use the builder pattern to register interceptors, customizers, ... .

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

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

Sign up to request clarification or add additional context in comments.

8 Comments

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. ;-)
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.
Just an update. From Spring Boot 1.4.0 RestTemplateBuilder can be used for managing RestTemplate instances. Example here spring.io/guides/gs/consuming-rest
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, can you create a new question? I think this problem is unrelated to this question/answer.
|
13

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();

This will help to avoid creation of a RestTemplate that wouldn't be used outside tests.

Comments

12

You must add

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

Comments

8

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

}

Comments

5

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

Comments

2

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

Comments

2

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

2 Comments

do you think thar the getForObject() violate the SOLID principales ? Wich one ?
@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.
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.

Comments

-1

This error usually happens when Spring Boot cannot find or create the RestTemplateBuilder bean automatically. if you are in reactive web, you have to define a new one manually. The most common causes and fixes are as follows:


Missing Spring Boot Web dependency

RestTemplateBuilder is auto-configured only when you have Spring Web or Spring WebFlux dependencies. Check your pom.xml or build.gradle for these:

Maven

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

If you are using WebFlux, then add:

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

Add a RestTemplate Bean

If you want to use RestTemplate, define it as a bean using the RestTemplateBuilder:

import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {

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

Using RestTemplateBuilder directly

If Spring Boot still doesn't find the RestTemplateBuilder, manually declare it:

@Bean
public RestTemplateBuilder restTemplateBuilder() {
    return new RestTemplateBuilder();
}

But normally, you shouldn't need this if spring-boot-starter-web is present.


Verify Spring Boot version

  • RestTemplateBuilder is available in Spring Boot 1.4+.
  • If you’re on older Spring Boot, consider upgrading.

For Spring WebFlux projects

If you are using Spring WebFlux, prefer WebClient over RestTemplate, as RestTemplate is blocking and WebFlux is reactive:

@Bean
public WebClient.Builder webClientBuilder() {
    return WebClient.builder();
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.