Quarkus 找不到内容类型多部分/表单数据休息客户端的编写器
Posted
技术标签:
【中文标题】Quarkus 找不到内容类型多部分/表单数据休息客户端的编写器【英文标题】:Quarkus could not find writer for content-type multipart/form-data rest client 【发布时间】:2020-10-12 21:32:28 【问题描述】:我正在使用 Quarkus 为我的 rest 微服务实现一个 API 网关。 我想将请求转发到另一个(Quarkus)rest-api。 我正在尝试使用多格式数据转发 POST 请求。 我期望得到 201,但我得到 500 内部服务器错误。 RESTEASY 抛出以下错误:
RESTEASY002020: Unhandled asynchronous exception, sending back 500: javax.ws.rs.ProcessingException: RESTEASY004655: Unable to invoke request: javax.ws.rs.ProcessingException: RESTEASY003215: could not find writer for content-type multipart/form-data type: org.acme.rest.client.multipart.MultipartBody
我尝试将我的 Quarkus 版本从 1.4.2 升级到 1.5.2,因为我看到了以下问题: https://github.com/quarkusio/quarkus/issues/8223
还尝试过 Intellij 无效缓存/重启,重新导入 maven
代码
多部分:
package org.acme.rest.client.multipart;
import org.jboss.resteasy.annotations.providers.multipart.PartType;
import javax.ws.rs.FormParam;
import javax.ws.rs.core.MediaType;
public class MultipartBody
@FormParam("sample_id")
@PartType(MediaType.TEXT_PLAIN)
public Long sampleId;
@FormParam("username")
@PartType(MediaType.TEXT_PLAIN)
public String username;
@FormParam("content")
@PartType(MediaType.TEXT_PLAIN)
public String content;
界面:
package org.acme.rest.client;
import io.smallrye.mutiny.Uni;
import org.acme.rest.client.multipart.MultipartBody;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import org.jboss.resteasy.annotations.providers.multipart.MultipartForm;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@RegisterRestClient
@Consumes(MediaType.MULTIPART_FORM_DATA)
public interface SocialService
@POST
Uni<Response> create(@MultipartForm MultipartBody data);
资源:
package org.acme.rest.client;
import io.smallrye.mutiny.Uni;
import org.acme.rest.client.multipart.MultipartBody;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.jboss.resteasy.annotations.providers.multipart.MultipartForm;
import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@Path("/comments")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public class SocialResource
@Inject
@RestClient
SocialService socialService;
@POST
public Uni<Response> create(@MultipartForm MultipartBody data)
return socialService.create(data);
测试:
package org.acme.rest.client;
import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
@QuarkusTest
public class SocialResourceTest
@Test
public void create()
given().contentType("multipart/form-data")
.multiPart("sample_id", "1")
.multiPart("username", "testuser")
.multiPart("content", "test message")
.when()
.post("/comments")
.then()
.statusCode(201);
【问题讨论】:
【参考方案1】:一切看起来都很好,但也许你缺少这个依赖
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-multipart-provider</artifactId>
</dependency>
该信息可在此 quarkus guide 获得
【讨论】:
依赖也在POM中。【参考方案2】:我遇到了同样的问题(找不到内容类型多部分/表单数据的编写器)。我通过让 MultiPartBody 扩展 MultipartFormDataOutput
解决了这个问题。
在你的情况下,这将是:
...
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput;
...
public class MultipartBody extends MultipartFormDataOutput
...
我通过查看 Quarkus / Resteasy 如何在内部解析输出编写器找到了这个解决方案。这是在org.jboss.resteasy.core.providerfactory.ResteasyProviderFactoryImpl
的resolveMessageBodyWriter()
方法中完成的。相关作者是org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataWriter
。在那里,isWriteable()
方法检查 MultipartFormDataOutput
是否是您的类 (MultipartBody
) 的超类。
但是,我不知道为什么不扩展 Quarkus 示例中的 MultipartFormDataOutput
就可以工作。
我的 Quarkus 版本是 1.8.2.Final,我使用 io.quarkus.quarkus-resteasy-multipart
maven 依赖项,而不是 org.jboss.resteasy.resteasy-multipart-provider
。
【讨论】:
【参考方案3】:要解决 Resteasy 和 quarkus 的这个问题,我必须将 MultipartFormDataWriter 添加到 resteasy 客户端注册表,这是我的新代码: 任何问题点击连接到我的推特@AIDeveloper
MultipartFormDataOutput output = new MultipartFormDataOutput();
output.addFormData("file", fileInputStream, MediaType.APPLICATION_OCTET_STREAM_TYPE);
output.addFormData("status", "status1", MediaType.TEXT_PLAIN_TYPE);
Response uploadResponse = newClient()
.target(uploadUri)
.register(MultipartFormDataWriter.class)
.request()
.post(Entity.entity(output
, MediaType.MULTIPART_FORM_DATA_TYPE));
【讨论】:
【参考方案4】:带有消息RESTEASY003215: could not find writer for content
的ProcessingException 表示没有为请求类型绑定序列化程序。这通常意味着您缺少该类型所需的其余客户端依赖项。
你的情况可能是今天(从 Quarkus 2.5.0 开始)
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-multipart</artifactId>
</dependency>
同样的错误的另一种可能性是您尝试使用响应式 API 实现 REST 客户端,但缺少 reactive 客户端 API 绑定。您可以在您的项目中同时拥有响应式和常规休息客户端。
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-client-reactive-jackson</artifactId>
</dependency>
这可能看起来不相关,因为在这种情况下它会带来 Json 编写器,但是您将获得的异常和错误消息完全相同。
【讨论】:
以上是关于Quarkus 找不到内容类型多部分/表单数据休息客户端的编写器的主要内容,如果未能解决你的问题,请参考以下文章
PrimeFaces 4.0/JSF 2.2.x 中的文件上传不适用于 AJAX - javax.servlet.ServletException:请求内容类型不是多部分/表单数据