Spring:没有带有预设内容类型“null”的 [class java.util.ArrayList] 转换器
即使似乎已经解决了明显的可能原因(缺少 Survey 类上的公共 getter、缺少依赖项中的 Jackson...),我仍然不断收到此错误
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class java.util.ArrayList] with preset Content-Type 'null'] with root cause
org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class java.util.ArrayList] with preset Content-Type 'null'
:控制器无法工作:
@RestController
@RequestMapping("/api")
public class SurveyController {
@Autowired
SurveyService surveyService;
@RequestMapping(value = "/surveys", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody List<Survey> getAllSurveys() {
List<Survey> surveys = surveyService.findAll();
return surveys; // <-- ERROR HERE
}
}
公共 getter 和 setter 已生成:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Survey {
private String sid;
private String surveyls_title;
@Nullable
private String startdate;
@Nullable
private String expires;
private String active;
}
该服务的工作原理预期返回调查列表
@Service
public class SurveyService implements SurveyServiceInterface{
@Autowired
WebClient webClient;
private final String SESSION_KEY = "***************";
public List<Survey> findAll() {
RPCRequest<Object> rpcRequest = RPCRequest.builder()
.method("list_surveys")
.id(1)
.params(new ArrayList<>(){{
add(SESSION_KEY);
}})
.build();
RPCResponse<Survey> rpcResponse = webClient.post()
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(rpcRequest))
.retrieve()
.bodyToMono(RPCResponse.class)
.single()
.block();
return rpcResponse.getResult();
}
}
@Configuration
@EnableWebFlux
public class WebFluxConfig implements WebFluxConfigurer{
@Bean
public WebClient getWebClient() {
HttpClient httpClient = HttpClient.create()
.tcpConfiguration(client ->
client.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000)
.doOnConnected(conn -> conn
.addHandlerLast(new ReadTimeoutHandler(10))
.addHandlerLast(new WriteTimeoutHandler(10))));
ClientHttpConnector connector = new ReactorClientHttpConnector(httpClient.wiretap(true));
return WebClient.builder()
.baseUrl("https://****.net/***.php/***/remotecontrol")
.clientConnector(connector)
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.exchangeStrategies(ExchangeStrategies.builder().codecs(this::acceptedCodecs).build())
.build();
}
private void acceptedCodecs(ClientCodecConfigurer clientCodecConfigurer) {
clientCodecConfigurer.customCodecs().register(new Jackson2JsonEncoder(new ObjectMapper(), MediaType.valueOf("text/javascript;charset=UTF-8")));
clientCodecConfigurer.customCodecs().register(new Jackson2JsonDecoder(new ObjectMapper(), MediaType.valueOf("text/javascript;charset=UTF-8")));
}
}
POM.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.6</version>
</parent>
<properties>
<java.version>17</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-webflux</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.1.210</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
依赖树显示存在 jackson-databind 和 jackson-core
[INFO] --- maven-dependency-plugin:3.1.2:tree (default-cli) @ SurveyAPI ---
[INFO] com.**********:SurveyAPI:jar:0.0.1-SNAPSHOT
[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:2.5.6:compile
[INFO] | +- org.springframework.boot:spring-boot-starter:jar:2.5.6:compile
[INFO] | | +- org.springframework.boot:spring-boot:jar:2.5.6:compile
[INFO] | | +- org.springframework.boot:spring-boot-autoconfigure:jar:2.5.6:compile
[INFO] | | +- org.springframework.boot:spring-boot-starter-logging:jar:2.5.6:compile
[INFO] | | | +- ch.qos.logback:logback-classic:jar:1.2.6:compile
[INFO] | | | | +- ch.qos.logback:logback-core:jar:1.2.6:compile
[INFO] | | | | \- org.slf4j:slf4j-api:jar:1.7.32:compile
[INFO] | | | +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.14.1:compile
[INFO] | | | | \- org.apache.logging.log4j:log4j-api:jar:2.14.1:compile
[INFO] | | | \- org.slf4j:jul-to-slf4j:jar:1.7.32:compile
[INFO] | | +- jakarta.annotation:jakarta.annotation-api:jar:1.3.5:compile
[INFO] | | +- org.springframework:spring-core:jar:5.3.12:compile
[INFO] | | | \- org.springframework:spring-jcl:jar:5.3.12:compile
[INFO] | | \- org.yaml:snakeyaml:jar:1.28:compile
[INFO] | +- org.springframework.boot:spring-boot-starter-json:jar:2.5.6:compile
[INFO] | | +- com.fasterxml.jackson.core:jackson-databind:jar:2.12.5:compile
[INFO] | | | +- com.fasterxml.jackson.core:jackson-annotations:jar:2.12.5:compile
[INFO] | | | \- com.fasterxml.jackson.core:jackson-core:jar:2.12.5:compile
[INFO] | | +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.12.5:compile
[INFO] | | +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.12.5:compile
[INFO] | | \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.12.5:compile
[INFO] | +- org.springframework.boot:spring-boot-starter-tomcat:jar:2.5.6:compile
[INFO] | | +- org.apache.tomcat.embed:tomcat-embed-core:jar:9.0.54:compile
[INFO] | | +- org.apache.tomcat.embed:tomcat-embed-el:jar:9.0.54:compile
[INFO] | | \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:9.0.54:compile
[INFO] | +- org.springframework:spring-web:jar:5.3.12:compile
[INFO] | | \- org.springframework:spring-beans:jar:5.3.12:compile
[INFO] | \- org.springframework:spring-webmvc:jar:5.3.12:compile
[INFO] | +- org.springframework:spring-aop:jar:5.3.12:compile
[INFO] | +- org.springframework:spring-context:jar:5.3.12:compile
[INFO] | \- org.springframework:spring-expression:jar:5.3.12:compile
[INFO] +- org.springframework.boot:spring-boot-starter-webflux:jar:2.5.6:compile
[INFO] | +- org.springframework.boot:spring-boot-starter-reactor-netty:jar:2.5.6:compile
[INFO] | | \- io.projectreactor.netty:reactor-netty-http:jar:1.0.12:compile
[INFO] | | +- io.netty:netty-codec-http:jar:4.1.69.Final:compile
[INFO] | | | +- io.netty:netty-common:jar:4.1.69.Final:compile
[INFO] | | | +- io.netty:netty-buffer:jar:4.1.69.Final:compile
[INFO] | | | +- io.netty:netty-transport:jar:4.1.69.Final:compile
[INFO] | | | +- io.netty:netty-codec:jar:4.1.69.Final:compile
[INFO] | | | \- io.netty:netty-handler:jar:4.1.69.Final:compile
[INFO] | | +- io.netty:netty-codec-http2:jar:4.1.69.Final:compile
[INFO] | | +- io.netty:netty-resolver-dns:jar:4.1.69.Final:compile
[INFO] | | | +- io.netty:netty-resolver:jar:4.1.69.Final:compile
[INFO] | | | \- io.netty:netty-codec-dns:jar:4.1.69.Final:compile
[INFO] | | +- io.netty:netty-resolver-dns-native-macos:jar:osx-x86_64:4.1.69.Final:compile
[INFO] | | | \- io.netty:netty-transport-native-unix-common:jar:4.1.69.Final:compile
[INFO] | | +- io.netty:netty-transport-native-epoll:jar:linux-x86_64:4.1.69.Final:compile
[INFO] | | \- io.projectreactor.netty:reactor-netty-core:jar:1.0.12:compile
[INFO] | | \- io.netty:netty-handler-proxy:jar:4.1.69.Final:compile
[INFO] | | \- io.netty:netty-codec-socks:jar:4.1.69.Final:compile
[INFO] | \- org.springframework:spring-webflux:jar:5.3.12:compile
[INFO] | \- io.projectreactor:reactor-core:jar:3.4.11:compile
[INFO] | \- org.reactivestreams:reactive-streams:jar:1.0.3:compile
[INFO] +- com.h2database:h2:jar:2.1.210:compile
[INFO] \- org.projectlombok:lombok:jar:1.18.22:provided
有人知道我做错了什么吗?谢谢
I keep getting this error even if the obvious possible causes seems to be taken care of (missing public getters on Survey class, missing jackson from dependency...)
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class java.util.ArrayList] with preset Content-Type 'null'] with root cause
org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class java.util.ArrayList] with preset Content-Type 'null'
Controller not working:
@RestController
@RequestMapping("/api")
public class SurveyController {
@Autowired
SurveyService surveyService;
@RequestMapping(value = "/surveys", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody List<Survey> getAllSurveys() {
List<Survey> surveys = surveyService.findAll();
return surveys; // <-- ERROR HERE
}
}
The public getters and setters are beign generated:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Survey {
private String sid;
private String surveyls_title;
@Nullable
private String startdate;
@Nullable
private String expires;
private String active;
}
The service works as expected returning the list of Surveys
@Service
public class SurveyService implements SurveyServiceInterface{
@Autowired
WebClient webClient;
private final String SESSION_KEY = "***************";
public List<Survey> findAll() {
RPCRequest<Object> rpcRequest = RPCRequest.builder()
.method("list_surveys")
.id(1)
.params(new ArrayList<>(){{
add(SESSION_KEY);
}})
.build();
RPCResponse<Survey> rpcResponse = webClient.post()
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(rpcRequest))
.retrieve()
.bodyToMono(RPCResponse.class)
.single()
.block();
return rpcResponse.getResult();
}
}
@Configuration
@EnableWebFlux
public class WebFluxConfig implements WebFluxConfigurer{
@Bean
public WebClient getWebClient() {
HttpClient httpClient = HttpClient.create()
.tcpConfiguration(client ->
client.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000)
.doOnConnected(conn -> conn
.addHandlerLast(new ReadTimeoutHandler(10))
.addHandlerLast(new WriteTimeoutHandler(10))));
ClientHttpConnector connector = new ReactorClientHttpConnector(httpClient.wiretap(true));
return WebClient.builder()
.baseUrl("https://****.net/***.php/***/remotecontrol")
.clientConnector(connector)
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.exchangeStrategies(ExchangeStrategies.builder().codecs(this::acceptedCodecs).build())
.build();
}
private void acceptedCodecs(ClientCodecConfigurer clientCodecConfigurer) {
clientCodecConfigurer.customCodecs().register(new Jackson2JsonEncoder(new ObjectMapper(), MediaType.valueOf("text/javascript;charset=UTF-8")));
clientCodecConfigurer.customCodecs().register(new Jackson2JsonDecoder(new ObjectMapper(), MediaType.valueOf("text/javascript;charset=UTF-8")));
}
}
POM.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.6</version>
</parent>
<properties>
<java.version>17</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-webflux</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.1.210</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Dependency tree shows that jackson-databind and jackson-core are present
[INFO] --- maven-dependency-plugin:3.1.2:tree (default-cli) @ SurveyAPI ---
[INFO] com.**********:SurveyAPI:jar:0.0.1-SNAPSHOT
[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:2.5.6:compile
[INFO] | +- org.springframework.boot:spring-boot-starter:jar:2.5.6:compile
[INFO] | | +- org.springframework.boot:spring-boot:jar:2.5.6:compile
[INFO] | | +- org.springframework.boot:spring-boot-autoconfigure:jar:2.5.6:compile
[INFO] | | +- org.springframework.boot:spring-boot-starter-logging:jar:2.5.6:compile
[INFO] | | | +- ch.qos.logback:logback-classic:jar:1.2.6:compile
[INFO] | | | | +- ch.qos.logback:logback-core:jar:1.2.6:compile
[INFO] | | | | \- org.slf4j:slf4j-api:jar:1.7.32:compile
[INFO] | | | +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.14.1:compile
[INFO] | | | | \- org.apache.logging.log4j:log4j-api:jar:2.14.1:compile
[INFO] | | | \- org.slf4j:jul-to-slf4j:jar:1.7.32:compile
[INFO] | | +- jakarta.annotation:jakarta.annotation-api:jar:1.3.5:compile
[INFO] | | +- org.springframework:spring-core:jar:5.3.12:compile
[INFO] | | | \- org.springframework:spring-jcl:jar:5.3.12:compile
[INFO] | | \- org.yaml:snakeyaml:jar:1.28:compile
[INFO] | +- org.springframework.boot:spring-boot-starter-json:jar:2.5.6:compile
[INFO] | | +- com.fasterxml.jackson.core:jackson-databind:jar:2.12.5:compile
[INFO] | | | +- com.fasterxml.jackson.core:jackson-annotations:jar:2.12.5:compile
[INFO] | | | \- com.fasterxml.jackson.core:jackson-core:jar:2.12.5:compile
[INFO] | | +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.12.5:compile
[INFO] | | +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.12.5:compile
[INFO] | | \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.12.5:compile
[INFO] | +- org.springframework.boot:spring-boot-starter-tomcat:jar:2.5.6:compile
[INFO] | | +- org.apache.tomcat.embed:tomcat-embed-core:jar:9.0.54:compile
[INFO] | | +- org.apache.tomcat.embed:tomcat-embed-el:jar:9.0.54:compile
[INFO] | | \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:9.0.54:compile
[INFO] | +- org.springframework:spring-web:jar:5.3.12:compile
[INFO] | | \- org.springframework:spring-beans:jar:5.3.12:compile
[INFO] | \- org.springframework:spring-webmvc:jar:5.3.12:compile
[INFO] | +- org.springframework:spring-aop:jar:5.3.12:compile
[INFO] | +- org.springframework:spring-context:jar:5.3.12:compile
[INFO] | \- org.springframework:spring-expression:jar:5.3.12:compile
[INFO] +- org.springframework.boot:spring-boot-starter-webflux:jar:2.5.6:compile
[INFO] | +- org.springframework.boot:spring-boot-starter-reactor-netty:jar:2.5.6:compile
[INFO] | | \- io.projectreactor.netty:reactor-netty-http:jar:1.0.12:compile
[INFO] | | +- io.netty:netty-codec-http:jar:4.1.69.Final:compile
[INFO] | | | +- io.netty:netty-common:jar:4.1.69.Final:compile
[INFO] | | | +- io.netty:netty-buffer:jar:4.1.69.Final:compile
[INFO] | | | +- io.netty:netty-transport:jar:4.1.69.Final:compile
[INFO] | | | +- io.netty:netty-codec:jar:4.1.69.Final:compile
[INFO] | | | \- io.netty:netty-handler:jar:4.1.69.Final:compile
[INFO] | | +- io.netty:netty-codec-http2:jar:4.1.69.Final:compile
[INFO] | | +- io.netty:netty-resolver-dns:jar:4.1.69.Final:compile
[INFO] | | | +- io.netty:netty-resolver:jar:4.1.69.Final:compile
[INFO] | | | \- io.netty:netty-codec-dns:jar:4.1.69.Final:compile
[INFO] | | +- io.netty:netty-resolver-dns-native-macos:jar:osx-x86_64:4.1.69.Final:compile
[INFO] | | | \- io.netty:netty-transport-native-unix-common:jar:4.1.69.Final:compile
[INFO] | | +- io.netty:netty-transport-native-epoll:jar:linux-x86_64:4.1.69.Final:compile
[INFO] | | \- io.projectreactor.netty:reactor-netty-core:jar:1.0.12:compile
[INFO] | | \- io.netty:netty-handler-proxy:jar:4.1.69.Final:compile
[INFO] | | \- io.netty:netty-codec-socks:jar:4.1.69.Final:compile
[INFO] | \- org.springframework:spring-webflux:jar:5.3.12:compile
[INFO] | \- io.projectreactor:reactor-core:jar:3.4.11:compile
[INFO] | \- org.reactivestreams:reactive-streams:jar:1.0.3:compile
[INFO] +- com.h2database:h2:jar:2.1.210:compile
[INFO] \- org.projectlombok:lombok:jar:1.18.22:provided
Does anybody know what I'm doing wrong? Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我自己发现了问题:我试图将 WebFlux 和非响应式 Spring 一起使用。我设法通过将注释应用
到主类来做到这一点,这解决了启动期间的异常:
但可能禁用了一些产生我所面临问题的 Jackson 组件。
通过返回
Flux
而不是List
将 SurveyController 转换为反应式控制器即可解决Found the problem myself: I was trying to use WebFlux and non-reactive Spring together. I managed to do so by applying the annotation
to the main class, which solved the exception during boot:
but probably disable some Jackson component generating the problem I was facing.
Solved by converting the SurveyController into a reactive one by returning
Flux<Survey>
instead ofList<Survey>