0
votes
  • Service A receives a file
  • Service A performs business logic.
  • Service B exposed an HTTP inbound to receive the file and post it to S3.
  • Service A calling Service B using http outbound gateway.

I am getting an error, unable to find suitable message converter when service A calls Service B using http outbound gateway.

<int:header-enricher input-channel="addHeader" output-channel="s3publishWithHeader">`


<int:header name="Content-Type" value="multipart/form-data" overwrite="true"/> </int:header-enricher>`

<util:list id="converters">
   <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
   <bean class="org.springframework.http.converter.FormHttpMessageConverter"/>
</util:list>`



<http:outbound-gateway request-channel="s3publishWithHeader"
                         http-method="POST" url="http://localhost:8090/com/api/upload"
                          extract-request-payload="true" message-converters="converters"
   ></http:outbound-gateway>

Version of Spring Integration: 4.3.12

2

2 Answers

2
votes

When using a Resource multipart it seems crucial that this resource has a file name, otherwise I found that the receiving server complains that the part is not present.

The MultiValueMap which will become the multipart request body can contain HttpEntity parts where you can specify the parts more precisely, e.g. you can specify a file name.

Assuming you have two parts, request and file, and file is an InputStreamResource (which never has a file name), you must define the filename by means of the Content-Disposition header. Use the resulting map as outgoing message payload, like so:

MultiValueMap payload = new LinkedMultiValueMap();

// some json part named "request"
HttpHeaders requestPartHeaders = new HttpHeaders();
requestPartHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<ConversionRequest> requestEntity = 
    new HttpEntity<>(requestBean, requestPartHeaders);

// InputStreamResource part named "file"
HttpHeaders fileRequestHeaders = new HttpHeaders();

fileRequestHeaders.setContentDisposition(ContentDisposition.builder("form-data")
        .name("file") // name of the part in the map
        .filename("my-file-name.pdf") // <-- mandatory file name
        .build());

fileRequestHeaders.setContentType(MediaType.parseMediaType(fileMimeType));
HttpEntity<InputStreamResource> fileEntity = 
    new HttpEntity<>(new InputStreamResource(fileOriginalStream),
        fileRequestHeaders);

payload.add("request", requestEntity);
payload.add("file", fileEntity);
1
votes

You don't need to specify that Content-Type header and you don't need to configure custom converters.

Only what you need is a payload as Map<String, Object>:

else if (content instanceof Map) {
        // We need to check separately for MULTIPART as well as URLENCODED simply because
        // MultiValueMap<Object, Object> is actually valid content for serialization
        if (this.isFormData((Map<Object, ?>) content)) {
            if (this.isMultipart((Map<String, ?>) content)) {
                contentType = MediaType.MULTIPART_FORM_DATA;
            }
            else {
                contentType = MediaType.APPLICATION_FORM_URLENCODED;
            }
        }
}

Nonetheless you have to show the StackTrace for error because I think there is something with response parsing.