3

I have files stored in MongoDB which can be uploaded/downloaded/deleted via a Rest service. I'd like to download files from MongoDB via Spring Integration (+Boot+Embedded Jetty) but I can't figure out how to set the Content-Disposition header properly because the downloaded file has the correct payload but the filename is wrong (it's receiveGateway without any extension):

xml config

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:int="http://www.springframework.org/schema/integration"
       xmlns:int-http="http://www.springframework.org/schema/integration/http"
       xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http.xsd">

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- one of the properties available; the maximum file size in bytes -->
    <property name="maxUploadSize" value="100000"/>
</bean>

<bean id="byteArrayHttpMessageConverter"
      class="org.springframework.http.converter.ByteArrayHttpMessageConverter">
</bean>

<int:channel id="http.frontend.rx"/>
<int:channel id="http.frontend.tx"/>
<int:channel id="http.backend.mysql.api.rx"/>
<int:channel id="http.backend.mysql.api.tx"/>
<int:channel id="http.backend.mongodb.api.rx"/>
<int:channel id="http.backend.mongodb.api.tx"/>
<!-- -->
<int-http:inbound-gateway
    id="frontEndToFlow"
    request-channel="http.frontend.rx"
    reply-channel="http.frontend.tx"
    path="/receiveGateway"
    mapped-request-headers="*"
    mapped-response-headers="Content-Disposition,Content-Length,Content-Type,Server,Application-Context,Content-Transfer-Encoding"
    message-converters="byteArrayHttpMessageConverter"
    supported-methods="GET,POST,PUT,DELETE"/>
<int-http:outbound-gateway
    id="FlowToBackEnd"
    request-channel="http.backend.mysql.api.tx"
    reply-channel="http.backend.mysql.api.rx"
    url="http://localhost:7070/api/{path}"
    http-method-expression="headers.http_requestMethod"
    expected-response-type="java.lang.String"
    charset="UTF-8">
    <int-http:uri-variable name="path" expression="'users/[email protected]/'"/>
</int-http:outbound-gateway>
<int-http:outbound-gateway
    id="springFlowToHttpBackEndMongoDB"
    request-channel="http.backend.mongodb.api.tx"
    reply-channel="http.backend.mongodb.api.rx"
    url="http://localhost:5050/api/{path}"
    http-method-expression="headers.http_requestMethod"
    message-converters="byteArrayHttpMessageConverter"
    mapped-request-headers="*"
    mapped-response-headers="Content-Disposition,Content-Length,Content-Type,Server,X-Application-Context,Content-Transfer-Encoding"
    expected-response-type="byte[]"
    charset="UTF-8">
    <int-http:uri-variable name="path" expression="'download/53cffb7c6c29a4f718627905'"/>
</int-http:outbound-gateway>
<int:service-activator
    id="inboundServiceActivator"
    input-channel="http.frontend.rx"
    output-channel="http.backend.mongodb.api.tx"
    ref="messageReaderService"
    method="printContent">
</int:service-activator>
<int:service-activator
    id="outboundServiceActivator"
    input-channel="http.backend.mongodb.api.rx"
    output-channel="http.frontend.tx"
    ref="messageReaderService"
    method="printContent">
</int:service-activator>

http request/response headers

Remote Address:::1:8080
Request URL:http://localhost:8080/receiveGateway
Request Method:GET
Status Code:200 OK
Request Headersview source
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8,ro;q=0.6,nb;q=0.4
Connection:keep-alive
Cookie:m=1933:86400%7C1800|2377:small|2491:chart|3247:t|34e2:|47ba:t|1d98:t|2a03:t|745a:t|77cb:t|5cf4:t|ca3:t|54e1:t|4e71:small|e69:chart|45b9:86400%7C1800|4a01:t|4c1b:t|3eff:t; JSESSIONID=8ACC161B9338DC122564C8BAB81EF25D
DNT:1
Host:localhost:8080
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36
Response Headersview source
Content-Length:33331
Content-Type:application/octet-stream
Server:Jetty(8.1.15.v20140411)
X-Content-Disposition:attachment; filename="aqmAR47_460s.jpg"

Application.java

@Configuration
@ComponentScan
@EnableAutoConfiguration
@ImportResource("classpath:httpgateway.xml")
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

MessageReaderService.java - used it to see headers ... which are correct ...

@Component
public class MessageReaderService {

    public Message printContent(Message message){
        System.out.println(message.getHeaders().toString());
        return message;
    }

}

System.out.println console output

    {errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@2f53f6f3, http_requestMethod=GET, Cookie=m=1933:86400%7C1800|2377:small|2491:chart|3247:t|34e2:|47ba:t|1d98:t|2a03:t|745a:t|77cb:t|5cf4:t|ca3:t|54e1:t|4e71:small|e69:chart|45b9:86400%7C1800|4a01:t|4c1b:t|3eff:t; JSESSIONID=8ACC161B9338DC122564C8BAB81EF25D, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@2f53f6f3, Host=localhost:8080, User-Agent=Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36, http_requestUrl=http://localhost:8080/receiveGateway, Connection=keep-alive, Accept-Language=en-US,en;q=0.8,ro;q=0.6,nb;q=0.4, Accept-Encoding=gzip,deflate,sdch, DNT=1, Accept=[text/html, application/xhtml+xml, application/xml;q=0.9, image/webp, */*;q=0.8], id=a5c4630e-f064-7245-8c8d-9e6706c361af, timestamp=1406907105217}
2014-08-01 18:31:45.218  WARN 8364 --- [qtp699466412-13] o.s.i.h.support.DefaultHttpHeaderMapper  : Header 'X-errorChannel' with value 'org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@2f53f6f3' will not be set since it is not a String and no Converter is available. Consider registering a Converter with ConversionService (e.g., <int:converter>)
2014-08-01 18:31:45.218  WARN 8364 --- [qtp699466412-13] o.s.i.h.support.DefaultHttpHeaderMapper  : Header 'X-replyChannel' with value 'org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@2f53f6f3' will not be set since it is not a String and no Converter is available. Consider registering a Converter with ConversionService (e.g., <int:converter>)
2014-08-01 18:31:45.218  WARN 8364 --- [qtp699466412-13] o.s.i.h.support.DefaultHttpHeaderMapper  : Header 'X-id' with value 'a5c4630e-f064-7245-8c8d-9e6706c361af' will not be set since it is not a String and no Converter is available. Consider registering a Converter with ConversionService (e.g., <int:converter>)
2014-08-01 18:31:45.219  WARN 8364 --- [qtp699466412-13] o.s.i.h.support.DefaultHttpHeaderMapper  : Header 'X-timestamp' with value '1406907105217' will not be set since it is not a String and no Converter is available. Consider registering a Converter with ConversionService (e.g., <int:converter>)
{errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@2f53f6f3, http_requestMethod=GET, Cookie=m=1933:86400%7C1800|2377:small|2491:chart|3247:t|34e2:|47ba:t|1d98:t|2a03:t|745a:t|77cb:t|5cf4:t|ca3:t|54e1:t|4e71:small|e69:chart|45b9:86400%7C1800|4a01:t|4c1b:t|3eff:t; JSESSIONID=8ACC161B9338DC122564C8BAB81EF25D, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@2f53f6f3, Host=localhost:8080, Content-Length=33331, User-Agent=Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36, http_requestUrl=http://localhost:8080/receiveGateway, Connection=keep-alive, Server=Jetty(8.1.15.v20140411), Accept-Language=en-US,en;q=0.8,ro;q=0.6,nb;q=0.4, Content-Disposition=attachment; filename="aqmAR47_460s.jpg", http_statusCode=200, Accept-Encoding=gzip,deflate,sdch, DNT=1, Content-Type=application/octet-stream, X-Application-Context=application:5050, Accept=[text/html, application/xhtml+xml, application/xml;q=0.9, image/webp, */*;q=0.8], id=4c1f52c8-b5f7-067c-2d60-826242d9d2db, timestamp=1406907105236}
{errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@6105c7d8, http_requestMethod=GET, Cookie=m=1933:86400%7C1800|2377:small|2491:chart|3247:t|34e2:|47ba:t|1d98:t|2a03:t|745a:t|77cb:t|5cf4:t|ca3:t|54e1:t|4e71:small|e69:chart|45b9:86400%7C1800|4a01:t|4c1b:t|3eff:t; JSESSIONID=8ACC161B9338DC122564C8BAB81EF25D, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@6105c7d8, Host=localhost:8080, User-Agent=Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36, http_requestUrl=http://localhost:8080/receiveGateway, Connection=keep-alive, Accept-Language=en-US,en;q=0.8,ro;q=0.6,nb;q=0.4, Accept-Encoding=gzip,deflate,sdch, DNT=1, Accept=[text/html, application/xhtml+xml, application/xml;q=0.9, image/webp, */*;q=0.8], id=21994eda-55aa-c798-53bc-c406e53e878d, timestamp=1406907106040}
2014-08-01 18:31:46.041  WARN 8364 --- [qtp699466412-14] o.s.i.h.support.DefaultHttpHeaderMapper  : Header 'X-errorChannel' with value 'org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@6105c7d8' will not be set since it is not a String and no Converter is available. Consider registering a Converter with ConversionService (e.g., <int:converter>)
2014-08-01 18:31:46.042  WARN 8364 --- [qtp699466412-14] o.s.i.h.support.DefaultHttpHeaderMapper  : Header 'X-replyChannel' with value 'org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@6105c7d8' will not be set since it is not a String and no Converter is available. Consider registering a Converter with ConversionService (e.g., <int:converter>)
2014-08-01 18:31:46.043  WARN 8364 --- [qtp699466412-14] o.s.i.h.support.DefaultHttpHeaderMapper  : Header 'X-id' with value '21994eda-55aa-c798-53bc-c406e53e878d' will not be set since it is not a String and no Converter is available. Consider registering a Converter with ConversionService (e.g., <int:converter>)
2014-08-01 18:31:46.043  WARN 8364 --- [qtp699466412-14] o.s.i.h.support.DefaultHttpHeaderMapper  : Header 'X-timestamp' with value '1406907106040' will not be set since it is not a String and no Converter is available. Consider registering a Converter with ConversionService (e.g., <int:converter>)
{errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@6105c7d8, http_requestMethod=GET, Cookie=m=1933:86400%7C1800|2377:small|2491:chart|3247:t|34e2:|47ba:t|1d98:t|2a03:t|745a:t|77cb:t|5cf4:t|ca3:t|54e1:t|4e71:small|e69:chart|45b9:86400%7C1800|4a01:t|4c1b:t|3eff:t; JSESSIONID=8ACC161B9338DC122564C8BAB81EF25D, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@6105c7d8, Host=localhost:8080, Content-Length=33331, User-Agent=Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36, http_requestUrl=http://localhost:8080/receiveGateway, Connection=keep-alive, Server=Jetty(8.1.15.v20140411), Accept-Language=en-US,en;q=0.8,ro;q=0.6,nb;q=0.4, Content-Disposition=attachment; filename="aqmAR47_460s.jpg", http_statusCode=200, Accept-Encoding=gzip,deflate,sdch, DNT=1, Content-Type=application/octet-stream, X-Application-Context=application:5050, Accept=[text/html, application/xhtml+xml, application/xml;q=0.9, image/webp, */*;q=0.8], id=a048606a-f03f-89d8-e981-bb661bc7e955, timestamp=1406907106058}
2
  • Show, please, how you build Content-Disposition header. and what you get in logs with System.out.println(message.getHeaders().toString()); Commented Aug 1, 2014 at 11:03
  • Hi Artem, I've edited my question with the requested details, I tried to set mapped-reply-headers ... the first line usually refers to the request message in the service activator, and the second line refers to the reply message , decided to map every header with '*' just to make sure I don't lose data somewhere Commented Aug 1, 2014 at 15:35

1 Answer 1

2

Good. I see now.

First of all: please, raise, an improvement JIRA issue (https://jira.spring.io/browse/INT): Content-Disposition is really a standard HTTP header and have to map it by default.

Right now you can overcome it with injected DefaultHttpHeaderMapper instead of those mapped-request-headers and mapped-response-headers. In addition you have to configure setUserDefinedHeaderPrefix as null.

It is X- by default, so we should change it to populate Content-Disposition.

Thank you for pointing it out!

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, I've posted INT-3488 as suggested, hope it's ok. I'll test the DefaultHttpHeaderMapper tomorrow and let you know.
solution was indeed to inject defaulthttpheadermapper and define setUserDefinedHeaderPrefix value = "" , big thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.