Spring boot cloud config client not picking up cloud config with error message: no suitable HttpMessageConverter found?

Viewed 2381

I'm trying to connect my Spring Boot app "config-test" to the Springframework‘s Cloud config server. Instead of picking up the application's configuration it answers with an error and aborts the application (because of the fail-fast option):

Could not extract response: no suitable HttpMessageConverter found for response type [class org.springframework.cloud.config.environment.Environment] and content type [text/html;charset=UTF-8]

Connecting to the config server it says:

 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.0.RELEASE)

2021-02-21 17:41:32.950  INFO 1891 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://localhost:8081
2021-02-21 17:41:33.230 ERROR 1891 --- [           main] o.s.boot.SpringApplication               : Application run failed

java.lang.IllegalStateException: Could not locate PropertySource and the fail fast property is set, failing
    at org.springframework.cloud.config.client.ConfigServicePropertySourceLocator.locate(ConfigServicePropertySourceLocator.java:148) ~[spring-cloud-config-client-2.2.2.RELEASE.jar:2.2.2.RELEASE]
    at org.springframework.cloud.bootstrap.config.PropertySourceLocator.locateCollection(PropertySourceLocator.java:52) ~[spring-cloud-context-2.2.2.RELEASE.jar:2.2.2.RELEASE]
    at org.springframework.cloud.config.client.ConfigServicePropertySourceLocator.locateCollection(ConfigServicePropertySourceLocator.java:163) ~[spring-cloud-config-client-2.2.2.RELEASE.jar:2.2.2.RELEASE]
    at org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration.initialize(PropertySourceBootstrapConfiguration.java:97) ~[spring-cloud-context-2.2.2.RELEASE.jar:2.2.2.RELEASE]
    at org.springframework.boot.SpringApplication.applyInitializers(SpringApplication.java:626) [spring-boot-2.3.0.RELEASE.jar:2.3.0.RELEASE]
    at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:370) [spring-boot-2.3.0.RELEASE.jar:2.3.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) [spring-boot-2.3.0.RELEASE.jar:2.3.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) [spring-boot-2.3.0.RELEASE.jar:2.3.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.3.0.RELEASE.jar:2.3.0.RELEASE]
    at com.lhsystems.cdb.logging_test.DynamicConfigLogLevelApplication.main(DynamicConfigLogLevelApplication.java:24) [classes/:na]
Caused by: org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class org.springframework.cloud.config.environment.Environment] and content type [text/html;charset=UTF-8]
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:123) ~[spring-web-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:998) ~[spring-web-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:981) ~[spring-web-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:741) ~[spring-web-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:674) ~[spring-web-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:583) ~[spring-web-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.cloud.config.client.ConfigServicePropertySourceLocator.getRemoteEnvironment(ConfigServicePropertySourceLocator.java:264) ~[spring-cloud-config-client-2.2.2.RELEASE.jar:2.2.2.RELEASE]
    at org.springframework.cloud.config.client.ConfigServicePropertySourceLocator.locate(ConfigServicePropertySourceLocator.java:107) ~[spring-cloud-config-client-2.2.2.RELEASE.jar:2.2.2.RELEASE]
    ... 9 common frames omitted

2021-02-21 17:41:33.234  WARN 1891 --- [           main] o.s.boot.SpringApplication               : Unable to close ApplicationContext

I have defined the URI of the cloud config server in the 'bootstrap.yml' properties file. The bootstrap.yml is:

spring:
  cloud:
    config:
      name: config-test
      uri: http://localhost:8081
      fail-fast: true

logging:
  level:
    com.harry.potter.logging_test: trace

I have a "application.properties" file to enable the /refresh feature of the configuration client during runtime:

management.endpoints.web.exposure.include=*

My project's pom.xml is:

<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>
<parent>
    <groupId>com.harry.potter</groupId>
    <artifactId>cloud-aware-microservices</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</parent>

<artifactId>cloud-aware-microservices-config-test</artifactId>

<properties>
    <java.version>1.8</java.version>
    <spring-cloud.version>Hoxton.SR4</spring-cloud.version>
</properties>

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

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

My project's parent pom.xml is:

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

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

<groupId>com.harry.potter</groupId>
<artifactId>cloud-aware-microservices</artifactId>
<version>0.0.1-SNAPSHOT</version>

<packaging>pom</packaging>

<name>cloud-aware-microservices</name>
<description>Cloud Aware Microservice Configuration System</description>

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

<modules>
    <module>cloud-aware-microservices-config</module>
    <module>cloud-aware-microservices-config-test</module>
</modules>

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

The config server works as expected giving back the configuration contents of a local file being organized as GIT repository when activated with a request to do so (with curl).

What am I doing wrong?

2 Answers

The problem here is that the config client requests the config server without credentials (or with wrong credentials).

In this case Spring's ConfigServicePropertySourceLocator throws the above exception with a rather misleading message:

Could not extract response: no suitable HttpMessageConverter found for response type [class org.springframework.cloud.config.environment.Environment] and content type [text/html;charset=UTF-8]

About credentials and the cloud config server, the Baeldung tutorial "Quick Intro to Spring Cloud" says:

We also need to set a username and a password for the Basic-Authentication in our application.properties to avoid an auto-generated password on every application restart.

These credentials are required each time the config client inquires the server for the configuration. I have added the credentials to the 'bootstrap.yml' properties file:

spring:
  cloud:
    config:
      name: config-test
      uri: http://localhost:8081
      username: harry
      password: potter
      fail-fast: true

logging:
  level:
    com.harry.potter.logging_test: trace

That did the trick.

I faced a similar issue when while following this tutorial Quick Intro to Spring Cloud Configuration even though the credentials for the server was correct. I later realized the spring security default settings was causing the error this is because the config server had full securty turned on. I solved it by disabling Cross-Site Request Forgery in the default spring security using the spring configuration:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception{
        httpSecurity.csrf().disable();
    }
}
Related