【问题标题】:Quarkus could not find writer for content-type multipart/form-data rest clientQuarkus 找不到内容类型多部分/表单数据休息客户端的编写器
【发布时间】: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);
    }
}

【问题讨论】:

    标签: rest multipartform-data resteasy quarkus quarkus-rest-client


    【解决方案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 编写器,但是您将获得的异常和错误消息完全相同。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-04-24
          • 2014-08-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多