Announcement Announcement Module
Collapse
No announcement yet.
Help with Poller (Polling a File) Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Help with Poller (Polling a File)

    Hi Friends,

    I am completely new to Spring Integration. Following is my requirement :

    I have to poll a given location (say a directory in interval of 5 sec.) for a file (with a given pattern - defined by regex.). IF the file is found that I have to perform certain operation(s) on the file (say log a message "File found", save the file to another location, etc.) and if the file is NOT found then the program needs to log a message say - "Polling interval 5 sec ... File not found". The program also needs to poll for 9 hrs. and after that it should STOP polling i.e. program should QUIT.

    Currently: My program is polling the directory as expected and its also logging to the file mentioning "File Found ...". I have couple of queries which are troubling me:

    1) My program is keeping on polling which is fine. But what I require is that the program should say poll for 9 hr. and then it should stop polling OR to be more precise the program should exit and not poll forever.

    I have checked the various attributes of Poller in Spring Integration Reference Manual.

    Code:
    <int:poller cron=""                                 
                default="false"                         
                error-channel=""                        
                fixed-delay=""                          
                fixed-rate=""                           
                id=""                                   
                max-messages-per-poll=""                
                receive-timeout=""                      
                ref=""                                  
                task-executor=""                        
                time-unit="MILLISECONDS"                
                trigger="">                             
                <int:advice-chain />                    
                <int:transactional />                   
    </int:poller>
    I am NOT getting which attribute to use for stopping the poller after 9 hrs. Could you please help me out and show me a practical example/code snippet for the same ?

    2) If a new file is NOT found on each poll then I want that I should log say "Polling interval is 5 sec (polling interval time)... File not found". How could this be done ??

    3) If I have a error in polling (for e.g. polled directory is not present or some kind of network error or whatever) and its not able to poll the directory so how do I log the error. I understand that we have an error-channel for the same. But what's happening is that on startup if the directory that the inbound-channel-adapter referes to is not present physically then the directory is created (I DO NOT want this ... I want to log an error saying - "Directory polled does not exist"). How could this be done ? I have the following configuration for my error channel:

    Code:
    <int:service-activator input-channel="fileTrackerErrorChannel"
             ref="errorTracker" method="processError" />
    
       <bean id="errorTracker" class="com.jefferies.fileutility.ErrorTracker" />
    In my ErrorTracker class I have a method by the name of processerror as described below:

    Code:
    public void processError(){       
        logger.trace("Folder is not present ... Program is exiting !!! ");
    }
    Please do kindly let me know if any information if required form my end. Please do help me with your esteemed suggestions.

    Thanks and Regards,
    Sid.


  • #2
    1. To achieve the requirements for "Polling interval is 5 sec (polling interval time)... File not found" you can write custom MethodInterceptor:
    Code:
       public class FilePollerMethodInterceptor implements MethodInterceptor {
    
               public Object invoke(MethodInvocation invocation) throws Throwable {
                     Object result = invocation.proceed();
                     if (!((Bollean)result)) {
                          logger.warn("Polling interval is 5 sec (polling interval time)... File not found");
                     }
                     return result;
              }
       }
    And inject it to the <poller>'s <advice-chain>

    2. To stop your app after 9 hours it's easy, too:
    Code:
      public static void main(String[] args) throws Exception {
            final ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext("YOUR_CTX.xml");
            new ThreadPoolTaskScheduler().schedule(new Runnable() {
                @Override
                public void run() {
                    ctx.close();
                }
            }, new Date(System.currentTimeMillis() + 9 * 60 * 60 * 1000));
           
        }
    3. auto-create-directory="false" and if your directory doesn't exist, your application won't start:
    Assert.isTrue(this.directory.exists(),
    "Source directory [" + directory + "] does not exist.");
    Assert.isTrue(this.directory.isDirectory(),
    "Source path [" + this.directory + "] does not point to a directory.");
    Assert.isTrue(this.directory.canRead(),
    "Source directory [" + this.directory + "] is not readable.");

    Comment


    • #3
      Originally posted by Artem Bilan View Post
      1. To achieve the requirements for "Polling interval is 5 sec (polling interval time)... File not found" you can write custom MethodInterceptor:
      Code:
      public class FilePollerMethodInterceptor implements MethodInterceptor {
      
      public Object invoke(MethodInvocation invocation) throws Throwable {
      Object result = invocation.proceed();
      if (!((Bollean)result)) {
      logger.warn("Polling interval is 5 sec (polling interval time)... File not found");
      }
      return result;
      }
      }
      And inject it to the <poller>'s <advice-chain>
      Artem Thanks a lot for your reply. I would like to mention that If the file is found then I am logging the details of the particular file. I am able to do this successfully (My log messages are being printed on the console as well as the file). Following is the configuration for the same in my spring configuration xml file:

      Code:
      <int:service-activator input-channel="incomingFiles"
              output-channel="outgoingFiles" ref="fileTracker" method="processFile" />
              
          <bean id="fileTracker" class="com.jefferies.fileutility.FileTracker" />
      In my FileTracker class I have a method by the name of processFile as described below:

      Code:
      public void processFile(File file){
              
          logger.trace("Absoute File Path:: "+file.getAbsolutePath()+" | "+"File Name :: "+file.getName()+" | "+"File Length :: "+file.length());
          
      }
      Now together with this as mentioned in my post I want to log the message (Polling interval is 5 sec (polling interval time)... File not found) even if the poller is not able to find the file in every subsequent polling. Can't I perform this activity with service-activator ? Do I need to use Spring's AOP feature and inject it to the poller's <advice-chain>. Also I am unable to understand the code of custom MethodInterceptor. Please do help me in understanding the same.

      [QUOTE=Artem Bilan;n749580]
      2. To stop your app after 9 hours it's easy, too:
      Code:
      public static void main(String[] args) throws Exception {
      final ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext("YOUR_CTX.xml");
      new ThreadPoolTaskScheduler().schedule(new Runnable() {
      @Override
      public void run() {
      ctx.close();
      }
      }, new Date(System.currentTimeMillis() + 9 * 60 * 60 * 1000));
      
      }
      [QUOTE]

      I understood the code above. It just says that the ThreadPoolTaskScheduler() would run the run method (which in turn would close the ApplicationContext) after a span of 9hrs. Can't we do the same using XML configuration say

      Code:
      <task:scheduler id="scheduler" pool-size="10" />
      I am more comfortable using Spring's XML configuration so would like to do that way.


      Originally posted by Artem Bilan View Post
      3. auto-create-directory="false" and if your directory doesn't exist, your application won't start:
      Is auto-create-directory an attribute of <in-file:inbound -channel-adapter> or <int-file:outbound-channel-adapter> ? when I used it in <in-file:inbound -channel-adapter> and deleted the polled directory then when I started the program it gave and exception saying "Source directory does not exist" as a stacktrace on the console. Can I use an error-channel in this case and redirect the exception to a log file and gracefully exit the program ? rather than printing the stacktrace on the console ? I tried using an error channel my configuration goes like this:

      Code:
      <int:service-activator input-channel="fileTrackerErrorChannel"
               ref="errorTracker" method="processError" />
      
          <bean id="errorTracker" class="com.jefferies.fileutility.ErrorTracker" />
      The ErrorTracker class has the following method:

      Code:
      public void processError(){
              logger.trace("Folder is not present ... Program is exiting !!! ");       
          }
      But this seems to be not working? What's wrong here ? How can I make the error-channel configuration to work ?

      Please do help with your suggestion

      Thanks and Regards,
      Sid.

      Comment


      • #4
        1.
        I would like to mention that If the file is found then I am logging the details of the particular file
        No questions: you do it correctly. And that's why I said nothing on the matter: there is no other choice to to log an info about some "entity", unless withing the process for that entity.
        To understand AOP and its MethodInterceptor you should read docs on the matter: http://docs.spring.io/spring/docs/4....tmlsingle/#aop

        2.
        Can't we do the same using XML configuration say
        Yes, you can do it there. however you should be more specific: you are going to stop entire application or just that file poller.

        3.
        Can I use an error-channel in this case and redirect the exception to a log file and gracefully exit the program ?
        No, you can't. Because the adapter checks directory existence on start up and its absence is a critical error for file adapter.
        However you can do some trick:
        a) Mark <int-file:inbound-channel-adapter> with auto-startup="false".
        b)
        HTML Code:
        <event:inbound-channel-adapter channel="contextStartedEventChannelChannel"
                                           event-types="org.springframework.context.event.ContextRefreshedEvent"
                                           payload-expression="new java.io.File('PATH_TO_YOUR_DIR').exists()"/>
        
        <int:router input-channel="contextStartedEventChannelChannel" expression="payload">
                <int:mapping value="true" channel="trueChannel" />
                <int:mapping value="false" channel="falseChannel" />
        </int:router>
        
        <int:outbound-channel-adapter id="trueChannel" expression="@fileChannelAdapter.start()"/>
        
        <int:outbound-channel-adapter id="falseChannel" ref="errorTracker" method="processError" />
        Hope I'm clear
        Last edited by Artem Bilan; May 27th, 2014, 05:44 AM.

        Comment


        • #5
          Originally posted by Artem Bilan View Post
          1.
          [QOUTE]
          I would like to mention that If the file is found then I am logging the details of the particular file
          [/QOUTE]

          No questions: you do it correctly. And that's why I said nothing on the matter: there is no other choice to to log an info about some "entity", unless withing the process for that entity.
          To understand AOP and its MethodInterceptor you should read docs on the matter: http://docs.spring.io/spring/docs/4....tmlsingle/#aop



          2.
          [QOUTE]
          Can't we do the same using XML configuration say
          [/QOUTE]
          Yes, you can do it there. however you should be more specific: you are going to stop entire application or just that file poller.



          3.

          No, you can't. Because the adapter checks directory existence on start up and its absence is a critical error for file adapter.
          However you can do some trick:
          a) Mark <int-file:inbound-channel-adapter> with auto-startup="false".
          b)
          HTML Code:
          <event:inbound-channel-adapter channel="contextStartedEventChannelChannel"
          event-types="org.springframework.context.event.ContextRefreshedEvent"
          payload-expression="new java.io.File('PATH_TO_YOUR_DIR').exists()"/>
          
          <int:router input-channel="contextStartedEventChannelChannel" expression="payload">
          <int:mapping value="true" channel="trueChannel" />
          <int:mapping value="false" channel="falseChannel" />
          </int:router>
          
          <int:outbound-channel-adapter id="trueChannel" expression="@fileChannelAdapter.start()"/>
          
          <int:outbound-channel-adapter id="falseChannel" ref="errorTracker" method="processError" />


          Hope I'm clear
          1) Artem, Sorry for troubling you I have some more queries. I would like to keep it simple. So I decided to use service-activator

          <int:service-activator input-channel="incomingFiles" output-channel="outgoingFiles" ref="fileTracker" method="processFile" /> <bean id="fileTracker" class="com.jefferies.fileutility.FileTracker" />
          public void processFile(File file){ logger.trace("Absoute File Path:: "+file.getAbsolutePath()+" | "+"File Name :: "+file.getName()+" | "+"File Length :: "+file.length()); } Now the issue is just that if the file is there on polling then it logs the above message which is perfectly fine BUT when polling happens and there is no new file to be polled then I just want to log a message which just says logger.trace("Polling time 5 sec ... File not found.."). Can I couple this with the processFile method somehow ? Am I moving in the right direction or my implementation of service-activator is wrong technically ? Do I need to use "MethodInterceptors" ??? Is there no other option .... SORRY for my ignorance still learning ...

          2) I would like to stop the poller which would invariably mean stopping the entire application in my case. Please do let me know how to do it using XML configuration.

          3) I understood this. But won't we be using auto-create-directory="false" as an attribute on inbound-channel-adapter here ?

          Thanks a TON for all your help

          Last edited by sidspring; May 27th, 2014, 04:53 AM.

          Comment


          • #6
            1. No, you can't use ServiceActivator to determine that there is no anything to process. The Polling Adapter can invoke process, if there is something having a value, otherwise it just goes to the next poliing cycle.From source code:
            Code:
            private boolean doPoll() {
                    Message<?> message = this.receiveMessage();
                    boolean result;
                    if (message == null) {
                        result = false;
                    }
                    else {
                        this.handleMessage(message);
                        result = true;
                    }
                    return result;
                }
            That's all. Your ServiceActivator is initiated from that this.handleMessage(message);.
            We can, of course, provide some ApplicationEvent publication, but I'm not sure that it makes sence, since we can do the same with custom Polling Advice.

            2. To stop just the poller you can do this:
            HTML Code:
            <task:scheduled-tasks scheduler="scheduler">    
                  <task:scheduled ref="fileChannelAdapter" method="stop" fixed-delay="#{9 * 60 * 60 * 1000}"/>
            </task:scheduled-tasks>
            3. No, we can't. As I said: it is wrong state for application, hance adapter can't start and from there the entire application can't do it. From code of FileReadingMessageSource:
            Code:
            Assert.isTrue(this.directory.exists(), "Source directory [" + directory + "] does not exist.");
            This sentence throws IllegalArgumentException on the bean initialization phase. The inconsistent state of any bean identify the entire application as invalid one.
            That's why I've shown you the trick how to achieve your requirements

            Comment


            • #7
              Originally posted by Artem Bilan View Post
              1. No, you can't use ServiceActivator to determine that there is no anything to process. The Polling Adapter can invoke process, if there is something having a value, otherwise it just goes to the next poliing cycle.From source code:
              Code:
              private boolean doPoll() {
              Message<?> message = this.receiveMessage();
              boolean result;
              if (message == null) {
              result = false;
              }
              else {
              this.handleMessage(message);
              result = true;
              }
              return result;
              }
              That's all. Your ServiceActivator is initiated from that this.handleMessage(message);.
              We can, of course, provide some ApplicationEvent publication, but I'm not sure that it makes sence, since we can do the same with custom Polling Advice.

              2. To stop just the poller you can do this:
              HTML Code:
              <task:scheduled-tasks scheduler="scheduler">
              <task:scheduled ref="fileChannelAdapter" method="stop" fixed-delay="#{9 * 60 * 60 * 1000}"/>
              </task:scheduled-tasks>
              3. No, we can't. As I said: it is wrong state for application, hance adapter can't start and from there the entire application can't do it. From code of FileReadingMessageSource:
              Code:
              Assert.isTrue(this.directory.exists(), "Source directory [" + directory + "] does not exist.");
              This sentence throws IllegalArgumentException on the bean initialization phase. The inconsistent state of any bean identify the entire application as invalid one.
              That's why I've shown you the trick how to achieve your requirements
              1. For issue 1, my Method Interceptor is working perfectly fine. But when I mention auto-startup="false" in <int-file:inbound-channel-adapter> then the poller doesn't poll the file (although the poller is started). why so ? I need to keep the attribute auto-startup="false". What could be done in this case ???

              2. I just wrote the code in my spring configuration xml file

              HTML Code:
              <task:scheduled-tasks scheduler="scheduler">
              <task:scheduled ref="fileChannelAdapter" method="stop" fixed-delay="#{9 * 60 * 60 * 1000}"/>
              </task:scheduled-tasks>
              but it gave the following exception.

              Code:
              Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.scheduling.support.ScheduledMethodRunnable#0': Cannot resolve reference to bean 'fileChannelAdapter' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'fileChannelAdapter' is defined
                  at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
                  at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:107)
                  at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:627)
                  at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:148)
                  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1114)
                  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1017)
                  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
                  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
                  at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
                  at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
                  at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
                  at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
                  at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
                  at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
                  at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
                  at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
                  at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
                  at com.jefferies.fileutility.App.main(App.java:31)
              Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'fileChannelAdapter' is defined
                  at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:638)
                  at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1159)
                  at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:282)
                  at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
                  at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:320)
                  ... 17 more
              I understand that there is no bean by the name of 'fileChannelAdapter' BUT please try and help me understand how should I define the bean 'fileChannelAdapter' as ???

              3. I wrote the code exactly as below:
              a) Mark <int-file:inbound-channel-adapter> with auto-startup="false".
              b) HTML Code:
              Code:
                
               <event:inbound-channel-adapter channel="contextStartedEventChannelChannel"                                    event-types="org.springframework.context.event.ContextRefreshedEvent"                                    payload-expression="new java.io.File(file:${myapp.incomingFile.path}).exists()"/>  <int:router input-channel="contextStartedEventChannelChannel" expression="payload">         <int:mapping value="true" channel="trueChannel" />         <int:mapping value="false" channel="falseChannel" /> </int:router>  <int:outbound-channel-adapter id="trueChannel" expression="@fileChannelAdapter.start()"/>  <int:outbound-channel-adapter id="falseChannel" ref="errorTracker" method="processError" />
              'PATH_TO_YOUR_DIR' == file:${myapp.incomingFile.path} Its value is taken from the properties file. But it gave me the following exception:

              Code:
              Exception in thread "main" org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'org.springframework.integration.event.inbound.App licationEventListeningMessageProducer#0': Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateExcep tion; nested PropertyAccessExceptions (1) are: PropertyAccessException 1: org.springframework.beans.MethodInvocationExceptio n: Property 'payloadExpression' threw exception; nested exception is org.springframework.expression.spel.SpelParseExcep tion: EL1065E:(pos 24): unexpected escape character. at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.applyPropertyValues(Abs tractAutowireCapableBeanFactory.java:1493) at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.populateBean(AbstractAu towireCapableBeanFactory.java:1197) at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.doCreateBean(AbstractAu towireCapableBeanFactory.java:537) at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.createBean(AbstractAuto wireCapableBeanFactory.java:475) at org.springframework.beans.factory.support.Abstract BeanFactory$1.getObject(AbstractBeanFactory.java:3 04) at org.springframework.beans.factory.support.DefaultS ingletonBeanRegistry.getSingleton(DefaultSingleton BeanRegistry.java:228) at org.springframework.beans.factory.support.Abstract BeanFactory.doGetBean(AbstractBeanFactory.java:300 ) at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:195) at org.springframework.beans.factory.support.DefaultL istableBeanFactory.preInstantiateSingletons(Defaul tListableBeanFactory.java:700) at org.springframework.context.support.AbstractApplic ationContext.finishBeanFactoryInitialization(Abstr actApplicationContext.java:760) at org.springframework.context.support.AbstractApplic ationContext.refresh(AbstractApplicationContext.ja va:482) at org.springframework.context.support.ClassPathXmlAp plicationContext.<init>(ClassPathXmlApplicationCon text.java:139) at org.springframework.context.support.ClassPathXmlAp plicationContext.<init>(ClassPathXmlApplicationCon text.java:83) at com.jefferies.fileutility.App.main(App.java:31) Caused by: org.springframework.beans.PropertyBatchUpdateExcep tion; nested PropertyAccessExceptions (1) are: PropertyAccessException 1: org.springframework.beans.MethodInvocationExceptio n: Property 'payloadExpression' threw exception; nested exception is org.springframework.expression.spel.SpelParseExcep tion: EL1065E:(pos 24): unexpected escape character. at org.springframework.beans.AbstractPropertyAccessor .setPropertyValues(AbstractPropertyAccessor.java:1 08) at org.springframework.beans.AbstractPropertyAccessor .setPropertyValues(AbstractPropertyAccessor.java:6 2) at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.applyPropertyValues(Abs tractAutowireCapableBeanFactory.java:1489) ... 13 more
              What I am doing wrong here ??? Following is my spring configuration XML file:

              Code:
              <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-file="http://www.springframework.org/schema/integration/file"
                  xmlns:int-event="http://www.springframework.org/schema/integration/event"
                  xmlns:int-task="http://www.springframework.org/schema/task"
                  xsi:schemaLocation="http://www.springframework.org/schema/beans
                  http://www.springframework.org/schema/beans/spring-beans.xsd
                  http://www.springframework.org/schema/integration
                  http://www.springframework.org/schema/integration/spring-integration.xsd
                  http://www.springframework.org/schema/integration/file
                  http://www.springframework.org/schema/integration/file/spring-integration-file.xsd
                  http://www.springframework.org/schema/integration/event
                  http://www.springframework.org/schema/integration/event/spring-integration-event-4.0.xsd
                  http://www.springframework.org/schema/task
                  http://www.springframework.org/schema/task/spring-task.xsd" >
              
                  <int-file:inbound-channel-adapter id="incomingFiles"
                      directory="file:${myapp.incomingFile.path}" prevent-duplicates="true"
                      filename-regex="${ETD.filenameRegex}" auto-startup="false">
              
                      <int:poller id="poller" fixed-rate="5000" >
                          <int:advice-chain>
                              <ref bean="springAdvise" />
                          </int:advice-chain>
                      </int:poller>
                      
                      <int-file:nio-locker />
              
                  </int-file:inbound-channel-adapter>
              
                  <int:service-activator input-channel="incomingFiles"
                          ref="fileTracker" method="processFile" />
              
                  <int:service-activator input-channel="incomingFiles"
                      ref="errorTracker" method="processError" />
              
                  <bean id="fileTracker" class="com.jefferies.fileutility.FileTracker" />
              
                  <bean id="errorTracker" class="com.jefferies.fileutility.ErrorTracker" />
                  
                  <bean id="springAdvise" class="com.jefferies.fileutility.FilePollerMethodInterceptor" />
              
                  <int-event:inbound-channel-adapter
                  channel="contextStartedEventChannelChannel" event-types="org.springframework.context.event.ContextRefreshedEvent"
                  payload-expression="new java.io.File(file:${myapp.incomingFile.path}).exists()" />
              
                  <int:router input-channel="contextStartedEventChannelChannel"
                      expression="payload">
                      <int:mapping value="true" channel="trueChannel" />
                      <int:mapping value="false" channel="falseChannel" />
                  </int:router>
              
                  <int:outbound-channel-adapter id="trueChannel"
                      expression="@fileChannelAdapter.start()" />
              
                  <int:outbound-channel-adapter id="falseChannel"
                      ref="errorTracker" method="processError" />
                  
                  <int-task:scheduled-tasks scheduler="scheduler">    
                        <int-task:scheduled ref="fileChannelAdapter" method="stop" fixed-delay="#{9 * 60 * 60 * 1000}"/>
                  </int-task:scheduled-tasks>
              
              
              </beans>
              Please do let me know if any more information is required.
              Last edited by sidspring; May 27th, 2014, 03:06 PM.

              Comment


              • #8
                1.
                But when I mention auto-startup="false" in <int-file:inbound-channel-adapter> then the poller doesn't poll the file (although the poller is started). why so ? I need to keep the attribute auto-startup="false". What could be done in this case ???
                You should understand what SmartLifecycle means. In this case auto-startup="false" means "do not poll files at all". Of course, you should start it after to do the stuff.

                2.
                [QOUTE]
                No bean named 'fileChannelAdapter' is defined
                [/QOUTE]
                Of course, you should mark <int-file:inbound-channel-adapter> with id="fileChannelAdapter". I was thinking it is clear... In your case it is incomingFiles
                3.
                [QOUTE]
                Property 'payloadExpression' threw exception; nested exception is org.springframework.expression.spel.SpelParseExcep tion: unexpected escape character.
                [/QOUTE]
                Right. You need to know more about SpEL and property-placeholder:
                HTML Code:
                payload-expression="new java.io.File(${myapp.incomingFile.path}).exists()"
                Here it is a runtime expression, so you can't use Resourse (file: indicator), however it supports property-placeholder before invocation

                Everything other looks good

                Comment


                • #9
                  Hi Artem,


                  My main concern is what would I write in the start and stop method.

                  Code:
                  <int:router input-channel="contextStartedEventChannelChannel" expression="payload">
                            <int:mapping value="true" channel="trueChannel" />
                           <int:mapping value="false" channel="falseChannel" />
                  </int:router>
                  
                  <int:outbound-channel-adapter id="trueChannel" expression="@fileChannelAdapter.start()" />
                  <int:outbound-channel-adapter id="falseChannel" ref="errorTracker" method="processError" />
                  
                  <int-task:scheduled-tasks scheduler="scheduler">
                         <int-task:scheduled ref="fileChannelAdapter" method="stop" fixed-delay="#{9 * 60 * 60 * 1000}"/>
                  </int-task:scheduled-tasks>
                  I understand that the fileChannelAdapter would be a bean which would have start and stop method BUT what do I write in the start and stop method ???.

                  The start method needs to start the poller and the stop method would need to stop the poller. How could this be done ???

                  Please kindly help.

                  Comment


                  • Artem Bilan
                    Artem Bilan commented
                    Editing a comment
                    Looks like we cross-post each other .

                    start/stop are operations of SmartLifecycle and (SourcePollingChannelAdapter) implements it. So, you have to do nothis: just provide correct id

                • #10
                  Originally posted by Artem Bilan View Post
                  1.

                  You should understand what SmartLifecycle means. In this case auto-startup="false" means "do not poll files at all". Of course, you should start it after to do the stuff.

                  2.
                  [QOUTE]
                  No bean named 'fileChannelAdapter' is defined
                  [/QOUTE]
                  Of course, you should mark <int-file:inbound-channel-adapter> with id="fileChannelAdapter". I was thinking it is clear... In your case it is incomingFiles
                  3.
                  [QOUTE]
                  Property 'payloadExpression' threw exception; nested exception is org.springframework.expression.spel.SpelParseExcep tion: unexpected escape character.
                  [/QOUTE]
                  Right. You need to know more about SpEL and property-placeholder:
                  HTML Code:
                  payload-expression="new java.io.File(${myapp.incomingFile.path}).exists()"
                  Here it is a runtime expression, so you can't use Resourse (file: indicator), however it supports property-placeholder before invocation

                  Everything other looks good

                  Thanks a lot Artem for your continued help and support. Really appreciate it. Please bear with me. I have some more exceptions

                  1. This issue is clear.

                  2. I changed my spring configuration file as per below:

                  Code:
                  <int-file:inbound-channel-adapter id="incomingFiles"
                          directory="file:${myapp.incomingFile.path}" prevent-duplicates="true"
                          filename-regex="${ETD.filenameRegex}" auto-startup="true">
                  
                          <int:poller id="poller" fixed-rate="5000" >
                              <int:advice-chain>
                                  <ref bean="springAdvise" />
                              </int:advice-chain>
                          </int:poller>
                          
                          <int-file:nio-locker />
                  
                      </int-file:inbound-channel-adapter>
                  Code:
                  <int-task:scheduled-tasks scheduler="scheduler">    
                        <int-task:scheduled ref="incomingFiles" method="stop" fixed-delay="#{5 * 1000}"/>
                      </int-task:scheduled-tasks>
                  Now we have the same id i.e. 'incomingFiles' in both. but I get the following exception after running this code:

                  Code:
                  Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.scheduling.support.ScheduledMethodRunnable#0': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.scheduling.support.ScheduledMethodRunnable]: Constructor threw exception; nested exception is java.lang.NoSuchMethodException: org.springframework.integration.channel.DirectChannel.stop()
                      at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:289)
                      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1114)
                      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1017)
                      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
                      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
                      at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
                      at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
                      at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
                      at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
                      at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
                      at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
                      at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
                      at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
                      at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
                      at com.jefferies.fileutility.App.main(App.java:31)
                  Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.scheduling.support.ScheduledMethodRunnable]: Constructor threw exception; nested exception is java.lang.NoSuchMethodException: org.springframework.integration.channel.DirectChannel.stop()
                      at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:164)
                      at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:125)
                      at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:281)
                      ... 14 more
                  Caused by: java.lang.NoSuchMethodException: org.springframework.integration.channel.DirectChannel.stop()
                      at java.lang.Class.getMethod(Unknown Source)
                      at org.springframework.scheduling.support.ScheduledMethodRunnable.<init>(ScheduledMethodRunnable.java:48)
                      at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
                      at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
                      at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
                      at java.lang.reflect.Constructor.newInstance(Unknown Source)
                      at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:148)
                      ... 16 more
                  3. I changed my spring configuration file as per below:

                  Code:
                  <int-event:inbound-channel-adapter
                      channel="contextStartedEventChannelChannel" event-types="org.springframework.context.event.ContextRefreshedEvent"
                      payload-expression="new java.io.File(${myapp.incomingFile.path}).exists()" />
                  
                      <int:router input-channel="contextStartedEventChannelChannel"
                          expression="payload">
                          <int:mapping value="true" channel="trueChannel" />
                          <int:mapping value="false" channel="falseChannel" />
                      </int:router>
                  
                      <int:outbound-channel-adapter id="trueChannel"
                          expression="@incomingFiles.start()" />
                  
                      <int:outbound-channel-adapter id="falseChannel"
                          ref="errorTracker" method="processError" />

                  I am now not using Resourse (file: indicator), I am only using property-placeholder before invocation. I changed my payload-expression from

                  Code:
                  payload-expression="new java.io.File(file:${myapp.incomingFile.path}).exists()"
                  to

                  Code:
                  payload-expression="new java.io.File(${myapp.incomingFile.path}).exists()"
                  still I am getting the same exception:
                  EL1065Epos 19): unexpected escape character.
                  Exception in thread "main" org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'org.springframework.integration.event.inbound.App licationEventListeningMessageProducer#0': Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateExcep tion; nested PropertyAccessExceptions (1) are:
                  PropertyAccessException 1: org.springframework.beans.MethodInvocationExceptio n: Property 'payloadExpression' threw exception; nested exception is org.springframework.expression.spel.SpelParseExcep tion: EL1065Epos 19): unexpected escape character.
                  at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.applyPropertyValues(Abs tractAutowireCapableBeanFactory.java:1493)
                  at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.populateBean(AbstractAu towireCapableBeanFactory.java:1197)
                  at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.doCreateBean(AbstractAu towireCapableBeanFactory.java:537)
                  at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.createBean(AbstractAuto wireCapableBeanFactory.java:475)
                  at org.springframework.beans.factory.support.Abstract BeanFactory$1.getObject(AbstractBeanFactory.java:3 04)
                  at org.springframework.beans.factory.support.DefaultS ingletonBeanRegistry.getSingleton(DefaultSingleton BeanRegistry.java:228)
                  at org.springframework.beans.factory.support.Abstract BeanFactory.doGetBean(AbstractBeanFactory.java:300 )
                  at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:195)
                  at org.springframework.beans.factory.support.DefaultL istableBeanFactory.preInstantiateSingletons(Defaul tListableBeanFactory.java:700)
                  at org.springframework.context.support.AbstractApplic ationContext.finishBeanFactoryInitialization(Abstr actApplicationContext.java:760)
                  at org.springframework.context.support.AbstractApplic ationContext.refresh(AbstractApplicationContext.ja va:482)
                  at org.springframework.context.support.ClassPathXmlAp plicationContext.<init>(ClassPathXmlApplicationCon text.java:139)
                  at org.springframework.context.support.ClassPathXmlAp plicationContext.<init>(ClassPathXmlApplicationCon text.java:83)
                  at com.jefferies.fileutility.App.main(App.java:31)
                  Caused by: org.springframework.beans.PropertyBatchUpdateExcep tion; nested PropertyAccessExceptions (1) are:
                  PropertyAccessException 1: org.springframework.beans.MethodInvocationExceptio n: Property 'payloadExpression' threw exception; nested exception is org.springframework.expression.spel.SpelParseExcep tion: EL1065Epos 19): unexpected escape character.
                  at org.springframework.beans.AbstractPropertyAccessor .setPropertyValues(AbstractPropertyAccessor.java:1 08)
                  at org.springframework.beans.AbstractPropertyAccessor .setPropertyValues(AbstractPropertyAccessor.java:6 2)
                  at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.applyPropertyValues(Abs tractAutowireCapableBeanFactory.java:1489)
                  ... 13 more
                  Please kindly bear with me and help me out of the exception

                  Comment


                  • #11
                    java.lang.NoSuchMethodException: org.springframework.integration.channel.DirectChan nel.stop()
                    Oh! Sorry I haven't noticed that you don't use channel attribute on &lt;int-file:inbound-channel-adapter&gt; in this case, the auto-created message channel is gotten the "incomingFiles" id, but addapter is gotten this one - "incomingFiles.adapter". So you should change to this:
                    HTML Code:
                    <int-task:scheduled ref="incomingFiles.adapter" method="stop" fixed-delay="#{5 * 1000}"/>
                    ...
                    <int:outbound-channel-adapter id="trueChannel" expression="@'incomingFiles.adapter'.start()" />
                    unexpected escape character.
                    Try this:
                    HTML Code:
                    payload-expression="new java.io.File('${myapp.incomingFile.path}').exists()"
                    The property-placeholder works on start up phase and resolves to some value, but for expression, which will be evaluated at runtime it should be a literal, otherwise expression context tries to resolve it as a value. In your case it can't parse expression because it contains file separators.

                    Comment


                    • #12
                      Originally posted by Artem Bilan View Post
                      Oh! Sorry I haven't noticed that you don't use channel attribute on &lt;int-file:inbound-channel-adapter&gt; in this case, the auto-created message channel is gotten the "incomingFiles" id, but addapter is gotten this one - "incomingFiles.adapter". So you should change to this:
                      HTML Code:
                      <int-task:scheduled ref="incomingFiles.adapter" method="stop" fixed-delay="#{5 * 1000}"/>
                      ...
                      <int:outbound-channel-adapter id="trueChannel" expression="@'incomingFiles.adapter'.start()" />
                      Try this:
                      HTML Code:
                      payload-expression="new java.io.File('${myapp.incomingFile.path}').exists()"
                      The property-placeholder works on start up phase and resolves to some value, but for expression, which will be evaluated at runtime it should be a literal, otherwise expression context tries to resolve it as a value. In your case it can't parse expression because it contains file separators.
                      Thanks Artem. I did the required changes.

                      Now my code looks like

                      Code:
                      <int-task:scheduler id="scheduler" pool-size="10"/>    
                          
                      <int-task:scheduled-tasks scheduler="scheduler">    
                          <int-task:scheduled ref="incomingFiles.adapter" method="stop" fixed-delay="#{10 * 1000}"/>
                      </int-task:scheduled-tasks>
                      But now what I observe is that when I start my program then on startup I immediately get the message in the console as:

                      Code:
                      INFO: Starting beans in phase 0
                      May 28, 2014 10:27:55 AM org.springframework.integration.endpoint.AbstractEndpoint start
                      INFO: started incomingFiles.adapter
                      May 28, 2014 10:27:55 AM org.springframework.integration.endpoint.EventDrivenConsumer logComponentSubscriptionEvent
                      INFO: Adding {service-activator} as a subscriber to the 'incomingFiles' channel
                      May 28, 2014 10:27:55 AM org.springframework.integration.channel.AbstractSubscribableChannel adjustCounterIfNecessary
                      INFO: Channel 'org[email protected]f4d5bc9.incomingFiles' has 1 subscriber(s).
                      May 28, 2014 10:27:55 AM org.springframework.integration.endpoint.AbstractEndpoint start
                      INFO: started org.springframework.integration.config.ConsumerEndpointFactoryBean#0
                      May 28, 2014 10:27:55 AM org.springframework.integration.endpoint.EventDrivenConsumer logComponentSubscriptionEvent
                      INFO: Adding {router} as a subscriber to the 'contextStartedEventChannelChannel' channel
                      May 28, 2014 10:27:55 AM org.springframework.integration.channel.AbstractSubscribableChannel adjustCounterIfNecessary
                      INFO: Channel 'org.springframework.context.support.ClassPathXmlApplicationContext[email protected]' has 1 subscriber(s).
                      May 28, 2014 10:27:55 AM org.springframework.integration.endpoint.AbstractEndpoint start
                      INFO: started org.springframework.integration.config.ConsumerEndpointFactoryBean#1
                      May 28, 2014 10:27:55 AM org.springframework.integration.endpoint.EventDrivenConsumer logComponentSubscriptionEvent
                      INFO: Adding {outbound-channel-adapter:trueChannel.adapter} as a subscriber to the 'trueChannel' channel
                      May 28, 2014 10:27:55 AM org.springframework.integration.channel.AbstractSubscribableChannel adjustCounterIfNecessary
                      INFO: Channel 'org[email protected]f4d5bc9.trueChannel' has 1 subscriber(s).
                      May 28, 2014 10:27:55 AM org.springframework.integration.endpoint.AbstractEndpoint start
                      INFO: started trueChannel.adapter
                      May 28, 2014 10:27:55 AM org.springframework.integration.endpoint.EventDrivenConsumer logComponentSubscriptionEvent
                      INFO: Adding {outbound-channel-adapter:falseChannel.adapter} as a subscriber to the 'falseChannel' channel
                      May 28, 2014 10:27:55 AM org.springframework.integration.channel.AbstractSubscribableChannel adjustCounterIfNecessary
                      INFO: Channel 'org[email protected]f4d5bc9.falseChannel' has 1 subscriber(s).
                      May 28, 2014 10:27:55 AM org.springframework.integration.endpoint.AbstractEndpoint start
                      INFO: started falseChannel.adapter
                      May 28, 2014 10:27:55 AM org.springframework.integration.endpoint.EventDrivenConsumer logComponentSubscriptionEvent
                      INFO: Adding {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel
                      May 28, 2014 10:27:55 AM org.springframework.integration.channel.AbstractSubscribableChannel adjustCounterIfNecessary
                      INFO: Channel 'org[email protected]f4d5bc9.errorChannel' has 1 subscriber(s).
                      May 28, 2014 10:27:55 AM org.springframework.integration.endpoint.AbstractEndpoint start
                      INFO: started _org.springframework.integration.errorLogger
                      May 28, 2014 10:27:55 AM org.springframework.integration.file.FileReadingMessageSource receive
                      INFO: Created message: [[Payload File content=C:\TEMP\incomingFile\ETD.CONFIRM.60326.140519.T0613170][Headers={id=b003893a-e013-57c8-0c96-55db627ec643, timestamp=1401287275402}]]
                      May 28, 2014 10:27:55 AM org.springframework.integration.endpoint.AbstractEndpoint stop
                      INFO: stopped incomingFiles.adapter
                      Sometime in the start of the starttup logs we get

                      May 28, 2014 10:27:55 AM org.springframework.integration.endpoint.AbstractE ndpoint start
                      INFO: started incomingFiles.adapter
                      Ans sometime at the end we get :

                      May 28, 2014 10:27:55 AM org.springframework.integration.endpoint.AbstractE ndpoint stop
                      INFO: stopped incomingFiles.adapter
                      Why the incomingFiles.adapter has been stopped immediately while our fixed-delay="#{10 * 1000}" is 10 sec. Time is exactly same and there is absolutely no delay. So ideally the poller should stop after 10 sec. and not immediately. Also there are 4 files in the directory and its picking up only one.

                      Please do suggest what's wrong.

                      3) I also changed my code as :

                      Code:
                      <int-event:inbound-channel-adapter
                          channel="contextStartedEventChannelChannel" event-types="org.springframework.context.event.ContextRefreshedEvent"
                          payload-expression="new java.io.File('${myapp.incomingFile.path}').exists()" />
                      
                          <int:router input-channel="contextStartedEventChannelChannel"
                              expression="payload">
                              <int:mapping value="true" channel="trueChannel" />
                              <int:mapping value="false" channel="falseChannel" />
                          </int:router>
                      
                          <int:outbound-channel-adapter id="trueChannel"
                              expression="@'incomingFiles.adapter'.start()" />
                      
                          <int:outbound-channel-adapter id="falseChannel"
                              ref="errorTracker" method="processError" />
                      Code:
                      <int-file:inbound-channel-adapter id="incomingFiles"
                              directory="file:${myapp.incomingFile.path}" prevent-duplicates="true"
                              filename-regex="${ETD.filenameRegex}"  auto-create-directory="false"
                              auto-startup="false">
                      i) But now what's happening is that when I delete the polled directory purposefully then as expected we are getting an exception but its coming as a stacktrace on the console and its not going on an error channel.

                      ii) Currently we are only taking care of one error scenario i.e. if the polled directory is not present. I would also want to implement other error scenarios such as network down, etc. , etc. and would like to just show a message on the logger (i.e. pass on the error channel) and gracefully exit the program.

                      Please do suggest what's wrong.

                      Thanks a lot as always for your continued support.

                      Comment


                      • #13
                        But now what I observe is that when I start my program then on startup I immediately get the message in the console as:
                        How does it work, if you increase the delay, e.g. for the 1 min ?

                        For other two questions, please, start new forum posts. And would be better, if you do it already on http://stackexchange.com, as far as we are going to migrate there soon.

                        Comment


                        • #14
                          Originally posted by Artem Bilan View Post
                          How does it work, if you increase the delay, e.g. for the 1 min ?

                          For other two questions, please, start new forum posts. And would be better, if you do it already on http://stackexchange.com, as far as we are going to migrate there soon.
                          I increased the delay for 1 min. fixed-delay="#{60 * 1000}" then also I get the same result as given above.

                          For the other 2 questions as mentioned by you I am starting new forum posts on stackexchange.com

                          Please do reply to me there at stackexchange.com

                          Thanks a lot as always for your continued support.

                          Comment


                          • #15
                            Well, I see. The
                            HTML Code:
                            <int-task:scheduled ref="incomingFiles.adapter" method="stop" fixed-delay="#{10 * 1000}"/>
                            produces PeriodicTrigger which result (nextExecutionTime) depends on triggerContext.lastScheduledExecutionTime() and if it null (your case) it invokes underlying method immidiatelly.
                            Let's try this!
                            HTML Code:
                            <task:scheduled ref="incomingFiles.adapter" method="stop" fixed-delay="#{10 * 1000}" initial-delay="#{10 * 1000}"/>
                            I mean the same value for the initial-delay to postpone the first stop task for the desired time

                            Comment

                            Working...
                            X