Results 1 to 9 of 9

Thread: Service activaor behaving erratically

  1. #1
    Join Date
    Jan 2013
    Posts
    7

    Default Service activaor behaving erratically

    Hi Guys,

    I am trying to copy files from the landing directory to a destination directory via inbound/outbound channel adapters. In the process I am using two service activators, one for the movement between inbound and outbound channel and the second one for delegating from the outbound channel to a seperate class that is meant inform about the completion of the copy and trigger further processing on the file.
    The problem is that the second activator is picking up files that has not moved from source to destination and triggering further processing thus resulting in exception.

    Not sure if I am doing anything wrong in the wiring, any help would be highly appreciated

    configuration file:
    Code:
    <?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:integration="http://www.springframework.org/schema/integration"
    	   xmlns:file="http://www.springframework.org/schema/integration/file"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans
    						http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    						http://www.springframework.org/schema/integration/file
    						http://www.springframework.org/schema/integration/file/spring-integration-file-2.2.xsd 
    						http://www.springframework.org/schema/integration
    						http://www.springframework.org/schema/integration/spring-integration-2.2.xsd">
    	
    	
    	<file:inbound-channel-adapter id="filesIn" directory="file:C:/test/tmpInbound" scanner="myscanner">
    		<integration:poller id="poller" fixed-delay="1000" />
    	</file:inbound-channel-adapter>	
    	
    	
    	<integration:service-activator input-channel="filesIn" output-channel="filesOut" ref="handler" />	
    	 <file:outbound-channel-adapter id="filesOut" directory="file:C:/test/DR" delete-source-files="false"	filename-generator="writer"/>	
    	<integration:service-activator input-channel="filesOut" ref="complete"/>	
    	
    	 
    	<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />
    	<bean id="myscanner" class="org.springframework.integration.file.RecursiveLeafOnlyDirectoryScanner" />
    	<bean id="handler" class="com.watcher.Handler" />
    	<bean id="writer" class="com.watcher.Writer" />
    	<bean id="complete" class="com.watcher.Complete" />
    </beans>
    The output:
    Code:
    ************start***************
    generateFileName(C:\test\tmpInbound\Bitmap Image0.bmp)
    {timestamp=1358314500737, id=575d8e7d-a959-4b8a-b5b6-19689588319c}
    Bitmap Image0.bmp
    Original ---> C:\test\tmpInbound\Bitmap Image0.bmp
    Final --> \Bitmap Image0.bmp0.13921170863669796
    *************done***************
    
    Jan 16, 2013 12:35:01 AM org.springframework.integration.file.FileReadingMessageSource receive
    INFO: Created message: [[Payload=C:\test\tmpInbound\Bitmap Image1.bmp][Headers={timestamp=1358314501783, id=6f807524-33a1-4ed5-8e86-907c9a63f6e2}]]
    [COMPLETE] C:\test\tmpInbound\Bitmap Image1.bmp
    Jan 16, 2013 12:35:02 AM org.springframework.integration.file.FileReadingMessageSource receive
    INFO: Created message: [[Payload=C:\test\tmpInbound\Bitmap Image2.bmp][Headers={timestamp=1358314502799, id=33a7932c-0d2a-444f-bf5a-a85f0bfac6f7}]]
    
    ************start***************
    generateFileName(C:\test\tmpInbound\Bitmap Image2.bmp)
    {timestamp=1358314502799, id=8a2695bf-0b86-4cfa-9d22-f97e110258c0}
    Bitmap Image2.bmp
    Original ---> C:\test\tmpInbound\Bitmap Image2.bmp
    Final --> \Bitmap Image2.bmp0.19998457677029258
    *************done***************
    As you can see in the result above Bitmap Image1.bmp is being picked up by the second activator eventhough the file has not been moved and also the activator is not all being called for the remaining two files that have been moved.

    Thanks in advance
    Anirban

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

    Default

    You have two subscribers to channel 'filesOut' (outbound channel adapter and second service activator). By default, the framework will round-robin messages to these subscribers.
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

  3. #3
    Join Date
    Mar 2010
    Location
    Gtr Philadelphia, PA
    Posts
    2,142

    Default

    If you want the message to go to both the outbound adapter and the service-activator, define filesOut as a <publish-subscribe-channel/>.

    The subscribers will be called in turn (the service activator after the adapter) but to be safe, you should add order="1" to the adapter and order="2" to the service activator.
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

  4. #4
    Join Date
    Jan 2013
    Posts
    7

    Default

    Thank you so much Gary for the solution , the flow is now working smoothly... and I have also removed the duplicate post, the review post screen made me think something had gone wrong , so I reposted it.

    However one quick question on the file copy part.
    In the process of moving a file from the landing to the destination directory, is there anyway I can force a wait on the inbound-channel-adapter for the duration that a large file is landing in the input directory ?

    Thanks
    Anirban

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

    Default

    That is a common problem for this kind if application, regardless of whether you are using Spring Integration. A common approach (used by the outbound adapter) is to write the file with a temporary name (e.g. foo.txt.writing) and rename to (e.g. to foo.txt) when the copy is complete.

    If you can't control the sender, you could write a custom FileListFilter that only exposes the file if the size hasn't changed for so many seconds/minutes, but the rename technique is better.
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

  6. #6
    Join Date
    Jan 2013
    Posts
    7

    Default

    Thank you Gary, I am allready trying to ensure a temp file policy to negate this issue.

    Incidentally there seems to be another issue with setting custom header values on teh message payload. I have set in some user-defined values from within the transformer component. But when this message payload reached the next inline pub-sub channel, the header is getting reset to the old value and the custom paratemer vanishes.

    The snippet below shows the two payload details. Do I need to set-in any additional parameter to ensure persistence of the custom vaule xml=2122311111 ?
    Code:
    [Payload=C:\test\tmpInbound\Bitmap Image1.bmp][Headers={timestamp=1358439618627, xml=2122311111, id=e46e4914-cdbf-4e93-b027-256bd6f6c119}]
    
    [Payload=C:\test\tmpInbound\Bitmap Image1.bmp][Headers={timestamp=1358439618627, id=a45a81b4-a7f6-468c-930e-290e52439ea2}]
    Custom value have been set via

    Code:
    Message<Object> message1 = MessageBuilder.withPayload(messageTmp.getPayload()).setHeader("xml", new String("2122311111")).copyHeadersIfAbsent(messageTmp.getHeaders()).build();
    Last edited by anirbanzeus; Jan 17th, 2013 at 10:25 AM. Reason: Updated

  7. #7
    Join Date
    Mar 2010
    Location
    Gtr Philadelphia, PA
    Posts
    2,142

    Default

    Headers cannot be dropped by a channel.

    Please show your configuration, and any transformers you are using. Note that if your transformer is a POJO (that just transforms the payload), the framework will take care of propagating headers for you. However, if the signature of your <transformer /> returns a Message object for example...

    Code:
     public Message<?> transform(Message<?> message)
    then you are responsible for propagating headers (see MessageBuilder.copyHeaders()). The assumption is (with a transformer) that if you are dealing with Message objects, you have the responsibility. This is unique to transformers.

    We generally recommend using POJOs when possible; users should avoid exposing the messaging infrastructure to their code.
    Last edited by Gary Russell; Jan 17th, 2013 at 10:35 AM.
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

  8. #8
    Join Date
    Jan 2013
    Posts
    7

    Default

    here are teh configuration details that i am leveraging

    Code:
    <?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:integration="http://www.springframework.org/schema/integration"
    	   xmlns:file="http://www.springframework.org/schema/integration/file"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans
    						http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    						http://www.springframework.org/schema/integration/file
    						http://www.springframework.org/schema/integration/file/spring-integration-file-2.2.xsd 
    						http://www.springframework.org/schema/integration
    						http://www.springframework.org/schema/integration/spring-integration-2.2.xsd">
    	
    	
    	<file:inbound-channel-adapter id="filesIn" directory="file:C:/test/tmpInbound" scanner="myscanner">
    		<integration:poller id="poller" fixed-delay="1000" />
    	</file:inbound-channel-adapter>	
    	
    	<integration:header-enricher input-channel="filesIn" output-channel="filesRouter" method="addNewHeader" ref="transform"/>
    	
    	<integration:publish-subscribe-channel id="filesRouter" />
    	
    	<file:outbound-channel-adapter id="filesOut" channel="filesRouter" directory="file:C:/test/DR" delete-source-files="false" filename-generator="writer" order="1"/>
    	
    	<integration:service-activator input-channel="filesRouter" ref="complete" order="2"/>
    	<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />
    	<bean id="myscanner" class="org.springframework.integration.file.RecursiveLeafOnlyDirectoryScanner" />
    	<bean id="handler" class="com.watcher.Handler" />
    	<bean id="writer" class="com.watcher.Writer" />
    	<bean id="complete" class="com.watcher.Complete" />
    	<bean id="transform" class="com.watcher.TestTransformer" />
    </beans>
    Within the transformer its a mere addition of the custom attribute with following method signature

    Code:
    public Message<?> addNewHeader(Message<?> messageTmp) {}

  9. #9
    Join Date
    Mar 2010
    Location
    Gtr Philadelphia, PA
    Posts
    2,142

    Default

    FYI, if all you are doing in addNewHeader is adding a header, you don't need any code at all, just add a <header/> element to your <header-enricher/>.

    Please provide a debug log snippet showing the message flow, including the dropped header.
    Last edited by Gary Russell; Jan 17th, 2013 at 11:01 AM.
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

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
  •