rest-client multipart not working without MultipartForm

See original GitHub issue

Describe the bug I have following “multipart/form-data” method defined in my application:

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.TEXT_PLAIN)
String sendMultipartData(@FormParam("file") @PartType(MediaType.APPLICATION_OCTET_STREAM) InputStream file, @FormParam("fileName") @PartType(MediaType.TEXT_PLAIN) String fileName);

However, this request is send as “application/x-www-form-urlencoded”. If I change this method to use “@MultipartForm MultipartBody data”, “multipart/form-data” is used as expected.

Expected behavior The request should not be sent with a content type that was not even declared. In this case, an error message from the client side might help.

Also, I was epecting that this use-case was also supported, since I correctly declared the mediatype. The rest-client should just build the MultipartForm object itself.

Actual behavior Currently, “application/x-www-form-urlencoded” is used instead of the defined “multipart/form-data”

2020-09-23 12:33:24,750 ERROR [io.qua.ver.htt.run.QuarkusErrorHandler] (executor-thread-1) HTTP Request to /client/multipart2 failed, error id: 8572358f-fdd7-46b3-b8be-9d31363fc93c-1: org.jboss.resteasy.spi.UnhandledException: javax.ws.rs.ProcessingException: RESTEASY004655: Unable to invoke request: javax.ws.r
s.ProcessingException: RESTEASY003215: could not find writer for content-type application/x-www-form-urlencoded type: javax.ws.rs.core.Form
        at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:106)
        at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:372)
        at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:216)
        at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:515)
        at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:259)
        at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:160)
        at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
        at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:163)
        at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:245)
        at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:73)
        at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:131)
        at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.access$000(VertxRequestHandler.java:37)
        at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler$1.run(VertxRequestHandler.java:94)
        at io.quarkus.runtime.CleanableExecutor$CleaningRunnable.run(CleanableExecutor.java:231)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
        at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2046)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1578)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1452)
        at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
        at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
        at java.base/java.lang.Thread.run(Thread.java:834)
        at org.jboss.threads.JBossThread.run(JBossThread.java:479)
Caused by: javax.ws.rs.ProcessingException: RESTEASY004655: Unable to invoke request: javax.ws.rs.ProcessingException: RESTEASY003215: could not find writer for content-type application/x-www-form-urlencoded type: javax.ws.rs.core.Form
        at org.jboss.resteasy.client.jaxrs.engines.ManualClosingApacheHttpClient43Engine.invoke(ManualClosingApacheHttpClient43Engine.java:287)
        at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:488)
        at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invokeSync(ClientInvoker.java:149)
        at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:112)
        at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:76)
        at com.sun.proxy.$Proxy50.sendMultipartData(Unknown Source)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.jboss.resteasy.microprofile.client.ProxyInvocationHandler.invoke(ProxyInvocationHandler.java:144)
        at com.sun.proxy.$Proxy53.sendMultipartData(Unknown Source)
        at org.acme.rest.client.multipart.MultipartClientResource.sendFile2(MultipartClientResource.java:41)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:167)
        at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:130)
        at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:638)
        at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:504)
        at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:454)
        at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
        at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:456)
        at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:417)
        at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:391)
        at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:68)
        at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:488)
        ... 20 more
Caused by: javax.ws.rs.ProcessingException: RESTEASY003215: could not find writer for content-type application/x-www-form-urlencoded type: javax.ws.rs.core.Form
        at org.jboss.resteasy.core.interception.jaxrs.ClientWriterInterceptorContext.throwWriterNotFoundException(ClientWriterInterceptorContext.java:50)
        at org.jboss.resteasy.core.interception.jaxrs.AbstractWriterInterceptorContext.getWriter(AbstractWriterInterceptorContext.java:302)
        at org.jboss.resteasy.core.interception.jaxrs.AbstractWriterInterceptorContext.syncProceed(AbstractWriterInterceptorContext.java:240)
        at org.jboss.resteasy.core.interception.jaxrs.AbstractWriterInterceptorContext.proceed(AbstractWriterInterceptorContext.java:224)
        at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.writeRequestBody(ClientInvocation.java:440)
        at org.jboss.resteasy.client.jaxrs.engines.ManualClosingApacheHttpClient43Engine.writeRequestBodyToOutputStream(ManualClosingApacheHttpClient43Engine.java:589)
        at org.jboss.resteasy.client.jaxrs.engines.ManualClosingApacheHttpClient43Engine.buildEntity(ManualClosingApacheHttpClient43Engine.java:548)
        at org.jboss.resteasy.client.jaxrs.engines.ManualClosingApacheHttpClient43Engine.loadHttpMethod(ManualClosingApacheHttpClient43Engine.java:455)
        at org.jboss.resteasy.client.jaxrs.engines.ManualClosingApacheHttpClient43Engine.invoke(ManualClosingApacheHttpClient43Engine.java:265)
        ... 47 more

To Reproduce

Link to a small reproducer (preferably a Maven project if the issue is not Gradle-specific).

Or attach an archive containing the reproducer to the issue. rest-client-multipart-quickstart.zip

Steps to reproduce the behavior:

  1. Download the reproducer
  2. mvn quarkus:dev
  3. Go to http://localhost:8080/client/multipart -> no error, the file is uploaded as multipart/form-data
  4. Go to http://localhost:8080/client/multipart2 -> error, the file is uploaded as application/x-www-form-urlencoded

Configuration

org.acme.rest.client.multipart.MultipartService/mp-rest/url=http://localhost:8080

Environment (please complete the following information):

  • Output of uname -a or ver:
  • Output of java -version:
  • GraalVM version (if different from Java):
  • Quarkus version or git rev:
  • Build tool (ie. output of mvnw --version or gradlew --version):

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:1
  • Comments:11 (7 by maintainers)

github_iconTop GitHub Comments

6reactions
ggrebertcommented, May 11, 2021

Hi @38leinaD , you can fix your problem with the following property:

quarkus.resteasy-json.json-default=false
1reaction
knutwannhedencommented, Nov 8, 2021

I am also trying to call a service that expects application/x-www-form-urlencoded using an MP REST client. I get the same exception as above when annotating my input parameter(s) using either @FormParam or @MultipartForm. Is this supposed to work in Quarkus? Are there some test cases you can point me at so that I can compare with my code? Thanks!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Quarkus could not find writer for content-type multipart/form ...
To fix this issue with Resteasy and quarkus, I had to add the MultipartFormDataWriter to resteasy client registry, this is my new code...
Read more >
Using the REST Client with Multipart - Quarkus
This guide explains how to use the RESTEasy REST Client with Multipart in order to interact with REST APIs requiring multipart/form-data content-type with ......
Read more >
Multipart Form Post in C# - Brian Grinstead
There is big problem with implementation. The FileParameter object hold Bytes array of file content. If the FormUpload will be used to upload...
Read more >
Body editor - ARC Documentation - Advanced REST Client
If you won't fix the problem the server will probably read the message incorrectly or ... Advanced REST Client has a dedicated multipart...
Read more >
Can't get Form Multi-part POST to work - MuleSoft Help Center
I'm having a trouble with a Form Multi-part POST. I get a response if I call it directly in Advanced Rest Client (ARC),...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found