0

My Springboot project that builds using gradle has an upload feature that lets the user choose a file from their PC and upload it the server for later use. The backend is fully functioning as I could test it with Postman, so the error must be generated somewhere in the frontend. I added the multipart dependencies in the build.gradle, but I'm not sure what else to do.

    implementation 'org.glassfish.jersey.media:jersey-media-multipart:2.34'

This is the error message:

Caused by: org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=multipart/form-data, type=class org.springframework.mock.web.MockMultipartFile, genericType=class org.springframework.mock.web.MockMultipartFile.
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:224)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:139)
    at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1116)
    at org.glassfish.jersey.client.ClientRequest.doWriteEntity(ClientRequest.java:461)
    at org.glassfish.jersey.client.ClientRequest.writeEntity(ClientRequest.java:443)
    at org.glassfish.jersey.client.internal.HttpUrlConnector._apply(HttpUrlConnector.java:369)
Caused by: org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=multipart/form-data, type=class org.springframework.mock.web.MockMultipartFile, genericType=class org.springframework.mock.web.MockMultipartFile.

    at org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:267)
    at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:297)
    at org.glassfish.jersey.client.JerseyInvocation.lambda$invoke$2(JerseyInvocation.java:687)
    at org.glassfish.jersey.client.JerseyInvocation.call(JerseyInvocation.java:697)
    at org.glassfish.jersey.client.JerseyInvocation.lambda$runInScope$3(JerseyInvocation.java:691)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:292)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:274)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:205)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:390)
    at org.glassfish.jersey.client.JerseyInvocation.runInScope(JerseyInvocation.java:691)
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:686)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:461)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.post(JerseyInvocation.java:357)
    at client.utils.ServerUtils.filePostRequest(ServerUtils.java:273)
    at client.utils.ServerUtils.saveFile(ServerUtils.java:278)
    at client.scenes.MediaPlayerCtrl.save(MediaPlayerCtrl.java:121)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    ... 57 more

This is the client part that's making the call to the server:

public void saveFile(File file) throws IOException {
        MultipartFile file1=convert(file);
        filePostRequest("secure/" + store.accessStore().getUsername() + "/file/add",
                Entity.entity(file1, "multipart/form-data"), new GenericType<>(){});
    }
public static MultipartFile convert(File file) throws IOException {
        String filename = file.getName();
        FileInputStream inputStream = new FileInputStream(file);
        return new MockMultipartFile(filename, inputStream);
    }
private <T> void filePostRequest(String path, Entity send, GenericType<T> retType) {
        ClientBuilder.newClient(new ClientConfig())
                .target(getServer()).path(path)
                .request("multipart/form-data")
                .post(send, retType);
    }

And this is the Controller on the server side:

@SpringBootApplication
@RestController
@RequestMapping(value = {"/secure/{username}/{password}/file", "/secure/{username}/file"})
public class FileController {
    @Autowired
    private StorageService service;
    @PostMapping("/add")
    public ResponseEntity<?> uploadFile(@RequestParam("file") MultipartFile file) throws IOException {
        String uploadFile = service.uploadFile(file);
        return ResponseEntity.status(HttpStatus.OK)
                .body(uploadFile);
    }

Edit: I tried adding the following class to the tests as indicated in this thread, but I'm encountering a "Cannot access jakarta.ws.rs.core.Configurable" in-IDE error (I mean it's underlined with red and it says this when hovered over) from the conf.register() method.

package server.api;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.test.JerseyTest;

public class FileControllerTest extends JerseyTest {
    @Override
    protected void configureClient(ClientConfig conf) {
        conf.register(MultiPartFeature.class);
    }
}
  • MockMultipartFile suggests you are getting this exception in the test. can you provide your test code? – Yury Apr 07 '23 at 08:01
  • @Yury I'm not using the MockMultipartFile in the tests. As u can see in the convert() method, I'm using it to convert the File object I'm providing to the saveFile() method to a MultipartFile that can be sent to the server. I couldn't figure out a better way to make the conversion. – Micu Bogdan Apr 07 '23 at 17:05

0 Answers0