Page 1 of 2 12 LastLast
Results 1 to 10 of 16

Thread: Setting up media types dynamically

  1. #1
    Join Date
    May 2011
    Location
    Chennai,India
    Posts
    38

    Default Setting up media types dynamically

    Hi,
    The below is my scenario. I have been working on this for a quite a some time now without any luck
    I want to render the documents on the browser. I have done it before for pdf ( by configuring byte array message converter).But this is bit different. I won't be knowing the type of the document until i get it downloaded from the server. So either i have to set the media type dynamically or i should configure a collection of media types before hand. Here is what i have tried,
    Code:
    <int-http:inbound-gateway request-channel="Channel"
    		name="/Retrieve" supported-methods="GET" message-converters="byteArrayMessageConverter"/>
    
    	<int:channel id="Channel" />
    
    	<int:service-activator input-channel="Channel"
    		expression="@Service.fetchDocument(payload)" />
    and i have configured byte array message converter as follows,
    Code:
    <bean id="byteArrayMessageConverter"
    
    		class="org.springframework.http.converter.ByteArrayHttpMessageConverter">
    
    		<property name="supportedMediaTypes">
    			<list>
    				
    				<bean class="org.springframework.http.MediaType">
    					<constructor-arg value="application" />
    					<constructor-arg value="pdf" />
    				</bean>
    				<bean class="org.springframework.http.MediaType">
    					<constructor-arg value="text" />
    					<constructor-arg value="plain" />
    				</bean>
    				<bean class="org.springframework.http.MediaType">
    					<constructor-arg value="text" />
    					<constructor-arg value="csv" />
    				</bean>
    				<bean class="org.springframework.http.MediaType">
    					<constructor-arg value="text" />
    					<constructor-arg value="xml" />
    				</bean>
    				<bean class="org.springframework.http.MediaType">
    					<constructor-arg value="application" />
    					<constructor-arg value="msword" />
    				</bean>
    				<bean class="org.springframework.http.MediaType">
    					<constructor-arg value="application" />
    					<constructor-arg value="vnd.ms-excel" />
    				</bean>
                                     </list>
    		</property>
    	</bean>
    But the above doesn't work as expected. Am i messed up anything?
    Any pointers on this?

    Thanks in Advance,
    Paary

  2. #2
    Join Date
    Jan 2009
    Location
    Ukraine, Kharkov
    Posts
    742

    Default

    Hello, Paary

    Can you explain what problem are you getting?
    set the media type dynamically
    You should set MessageHeader content-type manualy before you send reply into <http:inbound-gateway>
    It will be transalted into Response's HttpHeader before writing content into response.

    Hope it helps...

    Artem Bilan

  3. #3
    Join Date
    Mar 2011
    Posts
    12

    Default

    Artem,
    Paary and me work on the same team. To answer your question.

    This is the method signature corresponding to the ServiceActivator class which holds the business logic to get the document stream.

    public byte[] fetchDocument(LinkedMultiValueMap payload) throws Exception {

    My ServiceActivator expects the byte array and if the message-converters on the http-inbound gateway maps to a byteArrayMessageConverter that holds only one value (lets say application\pdf) and the byte array returns the same stream then all is fine.

    Now, we know we have mutiple MIME types to deal with. So we compiled them on the byteArrayMessageConverter ( as shown in the configuration Paary shared).

    How would SI know which MIME type to associate with the message-converters @ runtime? I think we need to return from the ServiceActivator an Object that can hold the byte stream as well as the MIME type indicator. Where we are struggling is which object to use and when we return the data 1) how to associate the byte stream with the anonymous reply channel that SI will configure under the hood and 2) how to map the MIME type to the appropriate byteArrayMessageConverter value from the list configured.

  4. #4
    Join Date
    Jan 2008
    Location
    Mohnton, PA USA (that's near Philadelphia)
    Posts
    2,148

    Default

    You may want to look at this sample which demonstrates exactly what you need https://github.com/SpringSource/spri...multipart-http

  5. #5
    Join Date
    Mar 2010
    Location
    Gtr Philadelphia, PA
    Posts
    2,153

    Default

    There are a couple of things you can do.

    1. If you want your service to remain as a POJO, do as you suggest and return an object containing the byte[] and MediaType; then use a header-enricher and transformer to set up the reply....

    Code:
    <int:chain input-channel="fromSA">
        <int:header-enricher header="contentType" expression="payload.contentType"/>
        <int:transformer expression="payload.byteArray"/>
    </int:chain>
    2. Return a Message<byte[]> from your service method and use
    Code:
         return MessageBuilder.withPayload(bytes).setHeader("contentType", ...).build();
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

  6. #6
    Join Date
    Jan 2009
    Location
    Ukraine, Kharkov
    Posts
    742

    Default

    Well, I understand your task.

    So, let me make step back.
    1. HttpRequestHandlingEndpointSupport already has ByteArrayHttpMessageConverter
    2.
    Code:
    HttpMessageConverter#canWrite(Class<?> clazz, MediaType mediaType) 
    HttpMessageConverter#write(T t, MediaType contentType, HttpOutputMessage outputMessage)
    These methods are used for determine appropriate Converter and put into HttpHeaders some content-type with writing payload into response outputStream.
    3. For example. If you can determine content-type of your document in the fetchDocument just return Map<String, Object>
    One key contains your byte[], another - is determined content-type.
    4. And now it is simple:
    HTML Code:
    <chain input-channel="Channel">
        <service-activator  ref="Service" method="fetchDocument"/>
        <header-enricher> 
            <header name="content-type" expression="payload[contentType]"/>
        </header-enricher>
        <transformer expression="payload[document]"/>
    <chain>
    Otherwise 'content-type' will be determined by request's 'accept-type' header.

  7. #7
    Join Date
    Jan 2009
    Location
    Ukraine, Kharkov
    Posts
    742

    Default

    return MessageBuilder.withPayload(bytes).setHeader("conte ntType", ...).build();
    Don't do this in the <service-activator>: you are losing REPLY_CHANNEL Header for the return into gateway.
    Gary, sorry ;-)

  8. #8
    Join Date
    Jan 2008
    Location
    Mohnton, PA USA (that's near Philadelphia)
    Posts
    2,148

    Default

    Artem that is incorrect.
    Code:
    return MessageBuilder.withPayload(bytes).setHeader("conte ntType", ...).build();
    is safe, since original headers (including REPLY_CHANNEL) wil still be copied in AbstractReplyProducingMessageHandler.createReplyMe ssage(..) method

  9. #9
    Join Date
    Jan 2009
    Location
    Ukraine, Kharkov
    Posts
    742

    Default

    is safe, since original headers (including REPLY_CHANNEL) wil still be copied
    E-h-h... It is.
    Haste makes waste.

    my contention is about <transformer>

  10. #10
    Join Date
    May 2011
    Location
    Chennai,India
    Posts
    38

    Default vendor specific documents not displayed properly

    Thanks Oleg, Gary and Artem for your valuable inputs
    Artem,
    I tried the approach as pointed out by you.
    I'm able to render pdfs, images etc on the browser with out any issues. But when comes to vendor specific (like WORD, EXCEL), we are not getting the document on the browser as expected.
    Say, if it is a word document, i get many special characters along with text in the browser.
    if its an excel, once i hit the end point, it tries to open it as a zipped file

    Any pointers on this?

    Thanks,
    Paary

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •