Hich
Hich

Reputation: 51

Quarkus could not find writer for content-type multipart/form-data rest client

I'm implementing an API-gateway for my rest microservice using Quarkus. I want to forward requests to another (Quarkus) rest-api. I'm trying to forward a POST request with multiform data. I'm expecting to get a 201 but I'm getting a 500 internal server error. RESTEASY throws the following error:

 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

I've tried upgrading my Quarkus version from 1.4.2 to 1.5.2 because I saw the following issue: https://github.com/quarkusio/quarkus/issues/8223

Also tried Intellij invalidate cache/restart, re-import maven

Code

MultiPartBody:

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;
}

Interface:

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);    

}

Resource:

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);
    }

}

Test:

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);
    }
}

Upvotes: 5

Views: 6590

Answers (4)

Benoit
Benoit

Reputation: 3588

The ProcessingException with message RESTEASY003215: could not find writer for content indicates no serializer was bound for the request type. This usually means you're missing the rest client dependency needed for the type.

In your case that might be today (as of Quarkus 2.5.0)

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-resteasy-multipart</artifactId>
</dependency>

Another possibility for this very same error is you're trying to implement a REST client with the reactive API and missing the reactive client API bindings. You can have both reactive and regular rest-client at the same time in your project.

    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-rest-client-reactive-jackson</artifactId>
    </dependency>

It might seems unrelated because it brings the Json writers in that case, but the exception and error message you'll get is exactly the same.

Upvotes: 0

Zakariae BEN ALLAL
Zakariae BEN ALLAL

Reputation: 92

To fix this issue with Resteasy and quarkus, I had to add the MultipartFormDataWriter to resteasy client registry, this is my new code : Any question click connect to my twitter @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));


Upvotes: 4

kvnb93
kvnb93

Reputation: 1

I've had the same issue (could not find writer for content-type multipart/form-data). I solved it by making the MultiPartBody extend MultipartFormDataOutput.

In your case this would be:

...
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput;
...
public class MultipartBody extends MultipartFormDataOutput {
    ...
}

I found this solution by looking at how Quarkus / Resteasy internally resolves the output writers. This is done in the resolveMessageBodyWriter() method of org.jboss.resteasy.core.providerfactory.ResteasyProviderFactoryImpl. The relevant writer is org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataWriter. There, the isWriteable() method checks if MultipartFormDataOutput is a superclass of your class (MultipartBody).

However, I don't know why it works without extending MultipartFormDataOutput in the Quarkus examples.

My Quarkus version is 1.8.2.Final and I use the io.quarkus.quarkus-resteasy-multipart maven dependency, not org.jboss.resteasy.resteasy-multipart-provider.

Upvotes: 0

Gerardo Arroyo
Gerardo Arroyo

Reputation: 151

Everything looks fine, but maybe you are missing this dependency

<dependency>
   <groupId>org.jboss.resteasy</groupId>
   <artifactId>resteasy-multipart-provider</artifactId>
</dependency>

That info is available at this quarkus guide

Upvotes: 0

Related Questions