Ergun
Ergun

Reputation: 57

Posting MultipartFormData with the WSClient using java

I am currently trying to post a file to a end point using the WSClient, with the following code

public Result uploadBankingFile(){
    logger.info("Uploading file to cold fusion");
    MultipartFormData<File> body = request().body().asMultipartFormData();
    MultipartFormData.FilePart<File> bankingFile = body.getFile("bankingFile");

    if (bankingFile != null) {
       String fileName = bankingFile.getFilename();
       String contentType = bankingFile.getContentType();

       //field needs to be called import
        Source<ByteString, ?> file = FileIO.fromFile(bankingFile.getFile());
        MultipartFormData.FilePart<Source<ByteString, ?>> fp = new MultipartFormData.FilePart<>("import", fileName, "text/plain", file);
        MultipartFormData.DataPart dp = new MultipartFormData.DataPart("key", "value");

        Future<WSResponse> post = ws.url(coldFusionPath + coldFusionUploadPath).post(Source.from(Arrays.asList(fp,dp)));


        return new JsonResult("ok");
    } else {
        flash("error", "Missing file");
        return badRequest();
    }

}

I am using the framework version 2.5.15 and with java 8. The issue I am getting is

/ImportBankingData.java:58: no suitable method found for post(akka.stream.javadsl.Source<play.mvc.Http.MultipartFormData.Part<akka.stream.javadsl.Source<akka.util.ByteString,?>>,akka.NotUsed>)
[error]     method play.api.libs.ws.WSRequest.<T>post(T,play.api.http.Writeable<T>) is not applicable
[error]       (cannot infer type-variable(s) T
[error]         (actual and formal argument lists differ in length))
[error]     method play.api.libs.ws.WSRequest.post(java.io.File) is not applicable
[error]       (argument mismatch; no instance(s) of type variable(s) O,T exist so that akka.stream.javadsl.Source<O,akka.NotUsed> conforms to java.io.File)
[error]     method play.api.libs.ws.WSRequest.post(akka.stream.scaladsl.Source<play.api.mvc.MultipartFormData.Part<akka.stream.scaladsl.Source<akka.util.ByteString,?>>,?>) is not applicable
[error]       (argument mismatch; no instance(s) of type variable(s) O,T exist so that akka.stream.javadsl.Source<O,akka.NotUsed> conforms to akka.stream.scaladsl.Source<play.api.mvc.MultipartFormData.Part<akka.stream.scaladsl.Source<akka.util.ByteString,?>>,?>)
[error] ws.url(coldFusionPath + coldFusionUploadPath).post
[error] (compile:compileIncremental) javac returned nonzero exit code
[info] Compiling 1 Java source to /Users/ergun/Documents/projects/brightbook/web/target/scala-2.11/classes...
[error] /Users/ergun/Documents/projects/brightbook/web/app/co/brightbook/web/controllers/ImportBankingData.java:58: no suitable method found for post(akka.stream.javadsl.Source<play.mvc.Http.MultipartFormData.Part<akka.stream.javadsl.Source<akka.util.ByteString,?>>,akka.NotUsed>)
[error]     method play.api.libs.ws.WSRequest.<T>post(T,play.api.http.Writeable<T>) is not applicable
[error]       (cannot infer type-variable(s) T
[error]         (actual and formal argument lists differ in length))
[error]     method play.api.libs.ws.WSRequest.post(java.io.File) is not applicable
[error]       (argument mismatch; no instance(s) of type variable(s) O,T exist so that akka.stream.javadsl.Source<O,akka.NotUsed> conforms to java.io.File)
[error]     method play.api.libs.ws.WSRequest.post(akka.stream.scaladsl.Source<play.api.mvc.MultipartFormData.Part<akka.stream.scaladsl.Source<akka.util.ByteString,?>>,?>) is not applicable
[error]       (argument mismatch; no instance(s) of type variable(s) O,T exist so that akka.stream.javadsl.Source<O,akka.NotUsed> conforms to akka.stream.scaladsl.Source<play.api.mvc.MultipartFormData.Part<akka.stream.scaladsl.Source<akka.util.ByteString,?>>,?>)
[error] ws.url(coldFusionPath + coldFusionUploadPath).post
[error] (compile:compileIncremental) javac returned nonzero exit code
[error] application - 

I am not sure how to resolve this issue. If anyone could point me in the right direction that would be much appreciated. Thanks

Upvotes: 1

Views: 1040

Answers (2)

Viswa Teja Kuncham
Viswa Teja Kuncham

Reputation: 199

I tried below approach in latest play version and it worked for me. I created a method getMultipartBody which returns the object in format required for wsClient post call taking multiPartData from current request as input.

public CompletionStage<Result> thirdPartyAttachment(){
    Http.MultipartFormData multipartFormData = request().body().asMultipartFormData();
    Source<? super Http.MultipartFormData.Part<Source<ByteString, ?>>, ?> multipartBody = getMultipartBody(multipartFormData.asFormUrlEncoded(),multipartFormData.getFiles());

    String url = "url_to_call";
    return wsClient.url(url)
            .post(multipartBody)
            .thenApplyAsync(response -> {
                new JsonResult("ok");
            })
            .exceptionally(e -> {
                return Results.internalServerError(prepareError());
            });
}

private Source<? super Http.MultipartFormData.Part<Source<ByteString, ?>>, ?> getMultipartBody(Map<String, String[]> dataSet, List<Http.MultipartFormData.FilePart<File>> filePartsList) {
        List<Http.MultipartFormData.Part> partList = new ArrayList<>();
        if (dataSet != null) {
            for (String field : dataSet.keySet()) {
                Http.MultipartFormData.DataPart dataPart = new Http.MultipartFormData.DataPart(field, dataSet.get(field)[0]);
                partList.add(dataPart);
            }
        }
        if (filePartsList != null) {
            for(Http.MultipartFormData.FilePart<File> filePart:filePartsList){
                Source<ByteString, ?> file = FileIO.fromFile(filePart.getFile());
                Http.MultipartFormData.FilePart<Source<ByteString, ?>> fp = new Http.MultipartFormData.FilePart<>(filePart.getKey(), filePart.getFilename(), filePart.getContentType(), file);
                partList.add(fp);
            }
        }
        return Source.from(Collections.unmodifiableList(partList));
    }

Upvotes: 2

Martin GOYOT
Martin GOYOT

Reputation: 286

I'm not sure, but looking at the stack trace I think you might have imported the wrong WSClient, the one from Scala instead of the one from Java.

In general, everything with api like here in play.api.libs.ws.WSRequest.<T>post is Scala stuff. Change your import, it might solve your issue.

Upvotes: 1

Related Questions