title: Spring Batch: Configuring service-activator
body: <p>I'm trying to add a service-activator in my Spring Batch .XML configuration file which sets requires-reply=false in my transformer method: FileMessageToJobRequestTransformer.</p>
  
  <p>Here's the XML:</p>
  
  <pre><code>&lt;int:transformer id="fileMessageToJobRequestTransformer"
                       input-channel="inboundFileChannel"
                       output-channel="outboundJobRequestChannel"
                       method="transform" &gt;
          &lt;bean class="com.distributedfinance.mbi.bai.transformer.FileMessageToJobRequestTransformer"&gt;
              &lt;property name="job" ref="baiParseJob"/&gt;
              &lt;property name="fileParameterName" value="input.file.url"/&gt;
          &lt;/bean&gt;
          &lt;int:poller fixed-rate="1000"/&gt;
      &lt;/int:transformer&gt;
  
      &lt;int:service-activator requires-reply="false" input-channel="inboundFileChannel" output-channel="outboundJobRequestChannel" ref="fileMessageToJobRequestTransformer"&gt; &lt;/int:service-activator&gt;
  </code></pre>
  
  <p>Here's the stack trace:</p>
  
  <pre><code>org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.integration.config.ConsumerEndpointFactoryBean#3': Cannot resolve reference to bean 'org.springframework.integration.config.ServiceActivatorFactoryBean#1' while setting bean property 'handler'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.integration.config.ServiceActivatorFactoryBean#1': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentException: Found ambiguous parameter type [class java.lang.Long] for method match: [public void org.springframework.integration.endpoint.AbstractPollingEndpoint.setTrigger(org.springframework.scheduling.Trigger), public void org.springframework.integration.endpoint.AbstractPollingEndpoint.setErrorHandler(org.springframework.util.ErrorHandler), public void org.springframework.integration.context.IntegrationObjectSupport.setComponentName(java.lang.String), public void org.springframework.integration.context.IntegrationObjectSupport.setApplicationContext(org.springframework.context.ApplicationContext) throws org.springframework.beans.BeansException, public void org.springframework.integration.endpoint.AbstractEndpoint.setAutoStartup(boolean), public void org.springframework.integration.endpoint.AbstractPollingEndpoint.setMaxMessagesPerPoll(long), public void org.springframework.integration.endpoint.AbstractEndpoint.setTaskScheduler(org.springframework.scheduling.TaskScheduler), public void org.springframework.integration.endpoint.AbstractEndpoint.setPhase(int), public void org.springframework.integration.context.IntegrationObjectSupport.getComponentType(), public void org.springframework.integration.endpoint.AbstractPollingEndpoint.setTransactionSynchronizationFactory(org.springframework.integration.transaction.TransactionSynchronizationFactory), public final void org.springframework.integration.context.IntegrationObjectSupport.setBeanFactory(org.springframework.beans.factory.BeanFactory)]
          at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:175)
          at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:103)
          at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1584)
          at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:253)
          at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
          at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
          ... 23 more
      Caused by: java.lang.IllegalArgumentException: Found ambiguous parameter type [class java.lang.Long] for method match: [public void org.springframework.integration.endpoint.AbstractPollingEndpoint.setTrigger(org.springframework.scheduling.Trigger), public void org.springframework.integration.endpoint.AbstractPollingEndpoint.setErrorHandler(org.springframework.util.ErrorHandler), public void org.springframework.integration.context.IntegrationObjectSupport.setComponentName(java.lang.String), public void org.springframework.integration.context.IntegrationObjectSupport.setApplicationContext(org.springframework.context.ApplicationContext) throws org.springframework.beans.BeansException, public void org.springframework.integration.endpoint.AbstractEndpoint.setAutoStartup(boolean), public void org.springframework.integration.endpoint.AbstractPollingEndpoint.setMaxMessagesPerPoll(long), public void org.springframework.integration.endpoint.AbstractEndpoint.setTaskScheduler(org.springframework.scheduling.TaskScheduler), public void org.springframework.integration.endpoint.AbstractEndpoint.setPhase(int), public void org.springframework.integration.endpoint.AbstractPollingEndpoint.setBeanClassLoader(java.lang.ClassLoader), public void org.springframework.integration.endpoint.AbstractPollingEndpoint.setAdviceChain(java.util.List), public void org.springframework.integration.context.IntegrationObjectSupport.setChannelResolver(org.springframework.messaging.core.DestinationResolver), public final void org.springframework.integration.endpoint.AbstractEndpoint.stop(java.lang.Runnable), public void org.springframework.integration.endpoint.AbstractPollingEndpoint.setTaskExecutor(java.util.concurrent.Executor), public void org.springframework.integration.context.IntegrationObjectSupport.setMessageBuilderFactory(org.springframework.integration.support.MessageBuilderFactory), public java.lang.String org.springframework.integration.context.IntegrationObjectSupport.getComponentType(), public void org.springframework.integration.endpoint.AbstractPollingEndpoint.setTransactionSynchronizationFactory(org.springframework.integration.transaction.TransactionSynchronizationFactory), public final void org.springframework.integration.context.IntegrationObjectSupport.setBeanFactory(org.springframework.beans.factory.BeanFactory)]
          at org.springframework.util.Assert.isNull(Assert.java:92)
          at org.springframework.integration.util.MessagingMethodInvokerHelper.findHandlerMethodsForTarget(MessagingMethodInvokerHelper.java:446)
          at org.springframework.integration.util.MessagingMethodInvokerHelper.&lt;init&gt;(MessagingMethodInvokerHelper.java:192)
          at org.springframework.integration.util.MessagingMethodInvokerHelper.&lt;init&gt;(MessagingMethodInvokerHelper.java:136)
          at org.springframework.integration.util.MessagingMethodInvokerHelper.&lt;init&gt;(MessagingMethodInvokerHelper.java:131)
          at org.springframework.integration.handler.MethodInvokingMessageProcessor.&lt;init&gt;(MethodInvokingMessageProcessor.java:57)
          at org.springframework.integration.handler.ServiceActivatingHandler.&lt;init&gt;(ServiceActivatingHandler.java:37)
          at org.springframework.integration.config.ServiceActivatorFactoryBean.createMethodInvokingHandler(ServiceActivatorFactoryBean.java:57)
          at org.springframework.integration.config.AbstractStandardMessageHandlerFactoryBean.createHandler(AbstractStandardMessageHandlerFactoryBean.java:97)
          at org.springframework.integration.config.AbstractSimpleMessageHandlerFactoryBean.createHandlerInternal(AbstractSimpleMessageHandlerFactoryBean.java:116)
          at org.springframework.integration.config.AbstractSimpleMessageHandlerFactoryBean.getObject(AbstractSimpleMessageHandlerFactoryBean.java:104)
          at org.springframework.integration.config.AbstractSimpleMessageHandlerFactoryBean.getObject(AbstractSimpleMessageHandlerFactoryBean.java:46)
          at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:168)
          ... 28 more
  
      Process finished with exit code 1
  </code></pre>
  
  <p>UPDATE:</p>
  
  <pre><code>@Transformer
      public JobLaunchRequest transform(Message&lt;File&gt; message) {
  
          LOGGER.debug("File message: {}", message);
          String jobName = message.getPayload().getAbsolutePath().toString();
  
          if (jobName.contains(".gitignore"))
                  return null;
  
          JobParametersBuilder jobParametersBuilder = new JobParametersBuilder();
  
          jobParametersBuilder.addString(fileParameterName,
                  "file://" + message.getPayload().getAbsolutePath());
  
  
          LOGGER.debug("Job params: {}", jobParametersBuilder.toJobParameters());
  
          Integer  pathDelimiterOffset = jobName.lastIndexOf('/');
          if (pathDelimiterOffset != -1) {
              String fileName = jobName.substring(pathDelimiterOffset+1);
              String archiveDirectoryName =  "bai/archive/";
              String archivePathName =  archiveDirectoryName.concat(fileName);
              File f = new File(archivePathName);
  
              // If the file exists in the bai/archive directory - assume it has already been processed - SKIP IT!  This is not a as reliable as querying Spring Batch tablle batch_execution_params... which will be done next.
              if (f.exists() &amp;&amp; !f.isDirectory())
                  return null;
          }
  
          try {
              return new JobLaunchRequest(job, jobParametersBuilder.toJobParameters());
          }
          catch (Exception e) {
              if (e instanceof JobInstanceAlreadyCompleteException) {
                  LOGGER.debug("Exception Handler: JobInstanceAlreadyCompleteException - Job params: {}", jobParametersBuilder.toJobParameters());
              }
          }
          return null;
      }
  </code></pre>
  
  <p>SftpBaiParserJobBridge-context.xml:</p>
  
  <pre><code>  &lt;?xml version="1.0" encoding="UTF-8"?&gt;
      &lt;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:batch-int="http://www.springframework.org/schema/batch-integration"
             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/batch-integration
                  http://www.springframework.org/schema/batch-integration/spring-batch-integration.xsd"&gt;
  
          &lt;!-- The bridge between SFTP spring integration to BAI parse spring batch job --&gt;
  
          &lt;int:channel id="outboundJobRequestChannel"/&gt;
          &lt;int:channel id="jobLaunchReplyChannel"&gt;
              &lt;int:queue/&gt;
              &lt;int:interceptors&gt;
                  &lt;int:wire-tap channel="logger"/&gt;
              &lt;/int:interceptors&gt;
          &lt;/int:channel&gt;
  
          &lt;!-- When getting a new BAI file, transform into spring batch job request --&gt;
          &lt;int:transformer id="fileMessageToJobRequestTransformer"
                           input-channel="inboundFileChannel"
                           output-channel="outboundJobRequestChannel"
                                 method="transform" &gt;
              &lt;bean class="com.distributedfinance.mbi.bai.transformer.FileMessageToJobRequestTransformer"&gt;
                  &lt;property name="job" ref="baiParseJob"/&gt;
                  &lt;property name="fileParameterName" value="input.file.url"/&gt;
              &lt;/bean&gt;
              &lt;int:poller fixed-rate="60000" max-messages-per-poll="100"/&gt;
          &lt;/int:transformer&gt;
  
          &lt;!-- Gateway to launch the BAI parse spring batch job --&gt;
          &lt;batch-int:job-launching-gateway request-channel="outboundJobRequestChannel"
                                           reply-channel="jobLaunchReplyChannel"&gt;
          &lt;/batch-int:job-launching-gateway&gt;
  
          &lt;int:logging-channel-adapter id="logger" level="WARN"
                                       logger-name="com.distributedfinance.mbi.bai.job"/&gt;
      &lt;/beans&gt;
  </code></pre>
  
  <p>SftpInboundReceive-context.xml:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;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-sftp="http://www.springframework.org/schema/integration/sftp"
      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/sftp
              http://www.springframework.org/schema/integration/sftp/spring-integration-sftp.xsd"&gt;
  
      &lt;!-- Create an inbound channel adapter to receive the BAI files via SFTP --&gt;
  
      &lt;import resource="SftpSession-context.xml"/&gt;
  
      &lt;int:channel id="inboundFileChannel"&gt;
          &lt;int:queue/&gt;
      &lt;/int:channel&gt;
  
      &lt;int-sftp:inbound-channel-adapter id="sftpInboundAdapter"
              auto-startup="true"
              channel="inboundFileChannel"
              session-factory="sftpSessionFactory"
              local-directory="${bai.sftp.local-dir}"
              remote-directory="${bai.sftp.remote-dir}"
              auto-create-local-directory="true"
              preserve-timestamp="true"
              delete-remote-files="${bai.sftp.delete}"&gt;
          &lt;int:poller cron="${bai.sftp.cron}" max-messages-per-poll="10"/&gt;
      &lt;/int-sftp:inbound-channel-adapter&gt;
  
  
  &lt;/beans&gt;
  </code></pre>
  
  <p>BaiParserJob.xml:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:batch="http://www.springframework.org/schema/batch"
         xmlns:util="http://www.springframework.org/schema/util"
         xsi:schemaLocation="
          http://www.springframework.org/schema/beans
              http://www.springframework.org/schema/beans/spring-beans.xsd
          http://www.springframework.org/schema/batch
              http://www.springframework.org/schema/batch/spring-batch.xsd
          http://www.springframework.org/schema/util
              http://www.springframework.org/schema/spring-util.xsd"&gt;
  
      &lt;bean name="jobParametersIncrementer" class="org.springframework.batch.core.launch.support.RunIdIncrementer"/&gt;
  
      &lt;!-- BATCH-2351 workaround --&gt;
      &lt;bean id="stepScope" class="org.springframework.batch.core.scope.StepScope"&gt;
          &lt;property name="autoProxy" value="true"/&gt;
      &lt;/bean&gt;
  
      &lt;batch:job id="baiParseJob" incrementer="jobParametersIncrementer"&gt;
          &lt;batch:step id="baiParseStep" next="baiArchive"&gt;
              &lt;batch:tasklet transaction-manager="transactionManager"&gt;
                  &lt;batch:chunk reader="baiItemReader"
                               processor="baiItemProcessor"
                               writer="baiItemWriter"
                               commit-interval="1"/&gt;
              &lt;/batch:tasklet&gt;
          &lt;/batch:step&gt;
          &lt;batch:step id="baiArchive"&gt;
              &lt;batch:tasklet ref="fileArchivingTasklet"/&gt;
          &lt;/batch:step&gt;
      &lt;/batch:job&gt;
  
      &lt;bean id="baiItemReader" class="com.distributedfinance.mbi.bai.reader.MultiLineBaiItemReader"
              scope="step"&gt;
          &lt;property name="delegate" ref="flatFileItemReader"/&gt;
          &lt;property name="baiFileFieldSetMapper"&gt;
              &lt;bean class="com.distributedfinance.mbi.bai.mapper.BaiFileFieldSetMapper"/&gt;
          &lt;/property&gt;
          &lt;property name="baiGroupFieldSetMapper"&gt;
              &lt;bean class="com.distributedfinance.mbi.bai.mapper.BaiGroupFieldSetMapper"/&gt;
          &lt;/property&gt;
          &lt;property name="baiAccountFieldSetMapper"&gt;
              &lt;bean class="com.distributedfinance.mbi.bai.mapper.BaiAccountFieldSetMapper"&gt;
                  &lt;property name="parser"&gt;
                      &lt;bean class="com.distributedfinance.mbi.bai.mapper.BaiTypeParser"/&gt;
                  &lt;/property&gt;
              &lt;/bean&gt;
          &lt;/property&gt;
          &lt;property name="baiTransactionFieldSetMapper"&gt;
              &lt;bean class="com.distributedfinance.mbi.bai.mapper.BaiTransactionFieldSetMapper"/&gt;
          &lt;/property&gt;
      &lt;/bean&gt;
  
      &lt;bean id="flatFileItemReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step"&gt;
          &lt;property name="resource" value="#{jobParameters['input.file.url']}"/&gt;
          &lt;property name="lineMapper"&gt;
              &lt;bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper"&gt;
                  &lt;property name="lineTokenizer"&gt;
                      &lt;bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer"/&gt;
                  &lt;/property&gt;
                  &lt;property name="fieldSetMapper"&gt;
                      &lt;bean class="org.springframework.batch.item.file.mapping.PassThroughFieldSetMapper"/&gt;
                  &lt;/property&gt;
              &lt;/bean&gt;
          &lt;/property&gt;
      &lt;/bean&gt;
  
      &lt;bean id="baiItemProcessor" class="com.distributedfinance.mbi.bai.processor.BaiItemProcessor"&gt;
          &lt;constructor-arg index="0" ref="accountLookup"/&gt;
          &lt;constructor-arg index="1"&gt;
              &lt;bean class="java.text.SimpleDateFormat"&gt;
                  &lt;constructor-arg value="yyMMddHHmmss"/&gt;
              &lt;/bean&gt;
          &lt;/constructor-arg&gt;
      &lt;/bean&gt;
  
      &lt;bean id="baiItemWriter" class="com.distributedfinance.mbi.bai.writer.BaiItemWriter"/&gt;
  
      &lt;bean id="accountLookup" class="com.distributedfinance.mbi.bai.lookup.AccountLookup"/&gt;
  
      &lt;bean id="fileArchivingTasklet" class="com.distributedfinance.mbi.bai.tasklet.FileArchivingTasklet"&gt;
          &lt;property name="downloadFileKey" value="input.file.url"/&gt;
          &lt;property name="archiveDirectory" value="${bai.sftp.archive-dir}"/&gt;
          &lt;property name="purgeDays" value="${bai.sftp.purge-days}"/&gt;
      &lt;/bean&gt;
   &lt;/beans&gt;
  </code></pre>