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