解决 “no suitable HttpMessageConverter found” 错误

huangapple go评论83阅读模式
英文:

Solving "no suitable HttpMessageConverter found" error

问题

以下是您提供的代码的翻译部分:

我有一个简单的应用程序试图消费Rest服务

@SpringBootApplication
public class ConsumingRestApplication
{

	private static final Logger log = LoggerFactory.getLogger(ConsumingRestApplication.class);

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

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

	@Bean
	public CommandLineRunner run(RestTemplate restTemplate) throws Exception
	{
		return args -> {
			try
			{
				restTemplate.getForObject("https://gturnquist-quoters.cfapps.io/api/random", Quote.class);
				
			} catch (RestClientException e)
			{
				e.printStackTrace();
			}
		};
	}
}

@JsonIgnoreProperties(ignoreUnknown = true)
public class Quote {

  private String type;
  private Value value;

  public Quote() {
  }

  public String getType() {
    return type;
  }

  public void setType(String type) {
    this.type = type;
  }

  public Value getValue() {
    return value;
  }

  public void setValue(Value value) {
    this.value = value;
  }

  @Override
  public String toString() {
    return "Quote{" +
        "type='" + type + '\'' +
        ", value=" + value +
        '}';
  }
}

遇到的错误

org.springframework.web.client.UnknownContentTypeException: 无法提取响应找不到适合的HttpMessageConverter用于响应类型 [class com.example.consumingrest.Quote] 和内容类型 [application/json;charset=UTF-8]

完整的异常跟踪

2020-10-19 12:39:04.984  INFO 8328 --- [  restartedMain] c.e.c.ConsumingRestApplication           : 正在启动 ConsumingRestApplication进程ID 8328位于 C:\gdrive\java_test\consumingrest\build\classes\java\main由 g 在 C:\gdrive\java_test\consumingrest 中启动
2020-10-19 12:39:04.987  INFO 8328 --- [  restartedMain] c.e.c.ConsumingRestApplication           : 未设置活动配置文件回退到默认配置文件default
2020-10-19 12:39:05.070  INFO 8328 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools 属性默认值处于活动状态spring.devtools.add-properties设置为false以禁用
2020-10-19 12:39:05.070  INFO 8328 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : 要获取更多与 Web 相关的日志记录请考虑将logging.level.web属性设置为DEBUG
2020-10-19 12:39:06.843  INFO 8328 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : 使用端口号初始化了 Tomcat8080http
...以下省略
org.springframework.web.client.UnknownContentTypeException: 无法提取响应找不到适合的HttpMessageConverter用于响应类型 [class com.example.consumingrest.Quote] 和内容类型 [application/json;charset=UTF-8]
	at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:126)
	at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:741)
	at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:674)
	at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:315)
	at com.example.consumingrest.ConsumingRestApplication.lambda$run$0(ConsumingRestApplication.java:37)
	...以下省略

解决此问题的起始点是什么?我应该采取什么逻辑来找到问题?

英文:

I have simple application that is trying consume Rest service:

@SpringBootApplication
public class ConsumingRestApplication
{
private static final Logger log = LoggerFactory.getLogger(ConsumingRestApplication.class);
public static void main(String[] args)
{
SpringApplication.run(ConsumingRestApplication.class, args);
}
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder)
{
return builder.build();
}
@Bean
public CommandLineRunner run(RestTemplate restTemplate) throws Exception
{
return args -> {
try
{
restTemplate.getForObject("https://gturnquist-quoters.cfapps.io/api/random", Quote.class);
} catch (RestClientException e)
{
e.printStackTrace();
}
};
}
}

Quote class:

@JsonIgnoreProperties(ignoreUnknown = true)
public class Quote {
private String type;
private Value value;
public Quote() {
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Value getValue() {
return value;
}
public void setValue(Value value) {
this.value = value;
}
@Override
public String toString() {
return "Quote{" +
"type='" + type + '\'' +
", value=" + value +
'}';
}
}

Got error :

org.springframework.web.client.UnknownContentTypeException: Could not extract response: no suitable HttpMessageConverter found for response type [class com.example.consumingrest.Quote] and content type [application/json;charset=UTF-8]

Whole exception trace:

2020-10-19 12:39:04.984  INFO 8328 --- [  restartedMain] c.e.c.ConsumingRestApplication           : Starting ConsumingRestApplication on GM with PID 8328 (C:\gdrive\java_test\consumingrest\build\classes\java\main started by g in C:\gdrive\java_test\consumingrest)
2020-10-19 12:39:04.987  INFO 8328 --- [  restartedMain] c.e.c.ConsumingRestApplication           : No active profile set, falling back to default profiles: default
2020-10-19 12:39:05.070  INFO 8328 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2020-10-19 12:39:05.070  INFO 8328 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2020-10-19 12:39:06.843  INFO 8328 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2020-10-19 12:39:06.856  INFO 8328 --- [  restartedMain] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2020-10-19 12:39:06.857  INFO 8328 --- [  restartedMain] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.38]
2020-10-19 12:39:06.957  INFO 8328 --- [  restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2020-10-19 12:39:06.957  INFO 8328 --- [  restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1887 ms
2020-10-19 12:39:07.204  INFO 8328 --- [  restartedMain] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-10-19 12:39:07.395  INFO 8328 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2020-10-19 12:39:07.603  INFO 8328 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2020-10-19 12:39:07.617  INFO 8328 --- [  restartedMain] c.e.c.ConsumingRestApplication           : Started ConsumingRestApplication in 3.076 seconds (JVM running for 3.545)
2020-10-19 12:39:07.786  WARN 8328 --- [  restartedMain] .c.j.MappingJackson2HttpMessageConverter : Failed to evaluate Jackson deserialization for type [[simple type, class com.example.consumingrest.Quote]]: com.fasterxml.jackson.databind.JsonMappingException: Cannot deserialize Class org.springframework.beans.factory.annotation.Value (of type annotation) as a Bean
2020-10-19 12:39:07.786  WARN 8328 --- [  restartedMain] .c.j.MappingJackson2HttpMessageConverter : Failed to evaluate Jackson deserialization for type [[simple type, class com.example.consumingrest.Quote]]: com.fasterxml.jackson.databind.JsonMappingException: Cannot deserialize Class org.springframework.beans.factory.annotation.Value (of type annotation) as a Bean
2020-10-19 12:39:08.541  WARN 8328 --- [  restartedMain] .c.j.MappingJackson2HttpMessageConverter : Failed to evaluate Jackson deserialization for type [[simple type, class com.example.consumingrest.Quote]]: com.fasterxml.jackson.databind.JsonMappingException: Cannot deserialize Class org.springframework.beans.factory.annotation.Value (of type annotation) as a Bean
2020-10-19 12:39:08.542  WARN 8328 --- [  restartedMain] .c.j.MappingJackson2HttpMessageConverter : Failed to evaluate Jackson deserialization for type [[simple type, class com.example.consumingrest.Quote]]: com.fasterxml.jackson.databind.JsonMappingException: Cannot deserialize Class org.springframework.beans.factory.annotation.Value (of type annotation) as a Bean
2020-10-19 12:39:08.544  WARN 8328 --- [  restartedMain] .c.j.MappingJackson2HttpMessageConverter : Failed to evaluate Jackson deserialization for type [[simple type, class com.example.consumingrest.Quote]]: com.fasterxml.jackson.databind.JsonMappingException: Cannot deserialize Class org.springframework.beans.factory.annotation.Value (of type annotation) as a Bean
2020-10-19 12:39:08.545  WARN 8328 --- [  restartedMain] .c.j.MappingJackson2HttpMessageConverter : Failed to evaluate Jackson deserialization for type [[simple type, class com.example.consumingrest.Quote]]: com.fasterxml.jackson.databind.JsonMappingException: Cannot deserialize Class org.springframework.beans.factory.annotation.Value (of type annotation) as a Bean
org.springframework.web.client.UnknownContentTypeException: Could not extract response: no suitable HttpMessageConverter found for response type [class com.example.consumingrest.Quote] and content type [application/json;charset=UTF-8]
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:126)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:741)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:674)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:315)
at com.example.consumingrest.ConsumingRestApplication.lambda$run$0(ConsumingRestApplication.java:37)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:795)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:779)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:322)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
at com.example.consumingrest.ConsumingRestApplication.main(ConsumingRestApplication.java:21)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)

What is starting point o solving this problem? What logic I should go to find problem?

答案1

得分: 1

我认为您可能遗漏了 Value 对象,或者可能导入错误。除此之外,如果字段是私有的,在直接在响应中返回该对象时,您需要为这些字段添加 getter 方法。以下是我是如何做的:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class DemoApplication {

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

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

    @RestController
    public static class Test {

        @Autowired
        private RestTemplate restTemplate;

        @GetMapping
        public Quote test() {
            return restTemplate.getForObject("https://gturnquist-quoters.cfapps.io/api/random", Quote.class);
        }
    }

    public static class Quote {
        private String type;
        private Value value;
        public String getType() {
            return type;
        }
        public Value getValue() {
            return value;
        }
    }

    public static class Value {
        private Long id;
        private String quote;
        public Long getId() {
            return id;
        }
        public String getQuote() {
            return quote;
        }
    }
}
英文:

I believe you are missing Value object or must be a wrong import. Along with that you need to add getter methods for the field if they are private, when you are returning that object directly in the response, here is how i have done it:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class DemoApplication {

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

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

    @RestController
    public static class Test {

        @Autowired
        private RestTemplate restTemplate;

        @GetMapping
        public Quote test() {
            return restTemplate.getForObject("https://gturnquist-quoters.cfapps.io/api/random", Quote.class);
        }
    }

    public static class Quote {
        private String type;
        private Value value;
        public String getType() {
            return type;
        }
        public Value getValue() {
            return value;
        }
    }

    public static class Value {
        private Long id;
        private String quote;
        public Long getId() {
            return id;
        }
        public String getQuote() {
            return quote;
        }
    }
}

huangapple
  • 本文由 发表于 2020年10月19日 17:54:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/64425017.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定