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.ResteasyProviderFactoryImplresolveMessageBodyWriter() 方法中完成的。相关作者是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 找不到内容类型多部分/表单数据休息客户端的编写器的主要内容,如果未能解决你的问题,请参考以下文章

使用 PHP 手动解析原始多部分/表单数据数据

关于多部分/表单数据?

PrimeFaces 4.0/JSF 2.2.x 中的文件上传不适用于 AJAX - javax.servlet.ServletException:请求内容类型不是多部分/表单数据

使用休息服务时表单无法将参数传递给requestparam

如何从多部分/表单数据响应中提取数据?

php 注册表单 为啥在显示注册成功后却在数据库里找不到呢 给20分!!