Announcement Announcement Module
Collapse
No announcement yet.
Integration batch help Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Integration batch help

    Hi All,

    I'm writing a simple application that uses both spring-integration and spring-batch. The app polls a directory, moves the found file into a 'processing' directory and then launches the batch job using the file. On completion of the job, the file is moved into the 'processed' directory.

    My integration context looks like this:

    Code:
    	<int-file:inbound-channel-adapter
    		directory="${file.input.directory}"
    		channel="filesIn" filename-pattern="${file.filename.pattern}">
    		<int:poller cron="${file.poller.cron}"
    			max-messages-per-poll="1" />
    	</int-file:inbound-channel-adapter>
    
    	<int:channel id="filesIn" />
    
    	<int-file:outbound-gateway id="moveFileToProcessing"
    		request-channel="filesIn" reply-channel="processing"
    		directory="${file.processing.directory}"
    		delete-source-files="true" />
    
    	<int:channel id="processing">
    		<int:dispatcher load-balancer="none" />
    	</int:channel>
    
    	<int:chain input-channel="processing" order="1">
    		<int:service-activator ref="fileToJobLaunchRequestAdapter"
    			method="adapt" />
    		<int:service-activator ref="jobLaunchingMessageHandler"
    			method="launch" />
    	</int:chain>
    
    	<int-file:outbound-channel-adapter
    		order="2" directory="${file.processed.directory}"
    		channel="processing" delete-source-files="true" />
    fileToJobLaunchRequestAdapter snippet:

    Code:
        @ServiceActivator
        public JobLaunchRequest adapt(File file) throws NoSuchJobException {
    
            JobParameters jobParameters = new JobParametersBuilder().addString("INPUT_FILE_PATH_KEY",
                    file.getAbsolutePath()).toJobParameters();
    
            return new JobLaunchRequest("job", jobParameters);
        }
    jobLaunchingMessageHandler snippet:

    Code:
        @Autowired
        private JobLauncher jobLauncher;
    
        @Autowired
        private JobRegistry jobRegistry;
    
        @ServiceActivator
        public JobExecution launch(JobLaunchRequest request) throws NoSuchJobException,
                JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException,
                JobParametersInvalidException {
    
            Job job = jobRegistry.getJob(request.getJobName());
            JobParameters jobParameters = request.getJobParameters();
    
            return jobLauncher.run(job, jobParameters);
    }
    spring.integration.version : 2.1.3.RELEASE
    spring.batch.version : 2.1.9.RELEASE

    All seems to work ok in the nominal case. However, if a runtime exception occurs in the batch job i'm unable to handle it with the current configuration. Can someone suggest how i might do this?

    Any help appreciated.
    Last edited by maddenj.ie; Oct 30th, 2012, 01:34 PM.

  • #2
    Add an error-channel to the inbound adapter; when the exception occurs, a message will be sent with a MessagingException as the payload; it has two properties failedMessage and cause (the exception).

    You can then handle the exception as you wish.

    When 2.2. comes out (soon!), you will be able to add an advice to the job launching service activator as discussed in this blog (http://blog.springsource.org/2012/10...etry-and-more/) and its associated sample.

    Comment


    • #3
      Thanks for the help.

      I tried the following

      Code:
      <int-file:inbound-channel-adapter
      	directory="${file.input.directory}"
      	channel="rawFilesIn" filename-pattern="${file.filename.pattern}">
      	<int:poller cron="${file.poller.cron}" 
      		max-messages-per-poll="1" error-channel="errorChannel"/>	
      </int-file:inbound-channel-adapter>
      
      <int-stream:stderr-channel-adapter channel="errorChannel" append-newline="true"/>
      
      <int:service-activator input-channel="errorChannel"
      	ref="defaultErrorHandlingServiceActivator">
      </int:service-activator>
      I'm still not seeing any messages on the errorChannel when a runtime exception is thrown.

      The attachment contains the output from my app on start up and when a file is dropped into polled directory.

      JobLaunchingMessageHandler throws the runtime exception that I can't seem to catch.

      I'd appreciate any help you could give me on setting up the error channel correctly.

      Comment


      • #4
        It doesn't look like an exception was thrown; otherwise, with your configuration, you wouldn't see the FileWritingMessageHandler being invoked (order="2")

        10-31 18:40:55,094 [task-scheduler-4] DEBUG org.springframework.integration.file.FileWritingMe ssageHandler...received message:...

        That said, there is something odd happening because your chain has no output-channel, so there is nowhere to send the JobExecution returned by the launch method.

        Is your configuration still the same as in your original post above? Can you log the JobExecution before returning it and/or catch/rethrow the exception to ensure you are actually seeing an exception?

        Comment


        • #5
          Yes, the configuration is still the same from my original post except for the errorChannel config. I've added a try/catch & rethrow and confirmed the exception is being thrown. To be a bit more specific, I've deleted the batch specific tables from my database and the exception thrown by the job launcher is the one I'm trying to catch.

          Currently I'm not using the jobExecution, I just want to move the file after the job has been run.

          Perhaps there are better ways of doing this?

          Again, your help on this is much appreciated.

          Comment


          • #6
            Oh; I see; I didn't notice this before, but you have a direct channel with load-balancer = none.

            The default behavior with this arrangement is if the first sub fails, we try the next one. You can set failover="false" but I don't think that's what you want.

            You should change 'processing' to a <publish-subscribe-channel/>. By default, the second subscriber won't be called if the first throws an exception.

            Also, when your launcher is successful, you need an output-channel on your <chain/> to receive the JobExecution object.

            Comment


            • #7
              As you suggested, I have changed the 'processing' channel to a <publish-subscribe-channel/>. As I would like to move the file into the 'processed' directory even if the first subscriber throws an exception, I set 'ignore-failures="true"' . This gives me the desired behaviour but perhaps using the errorChannel might be better.

              Thanks for the help.

              Comment

              Working...
              X