title: Spring Batch Proxy Failure java.lang.ClassCastException: com.sun.proxy.$Proxy20 cannot be cast to
body: <p>Why would I be getting a cast error from a proxy based on a bean that is properly implementing an interface? Package and object names have been changed to protect proprietary data.</p>
  
  <p>I know the error </p>
  
  <pre><code>java.lang.ClassCastException: com.sun.proxy.$Proxy20 cannot be cast to package.Order
  </code></pre>
  
  <p>normally comes up when one is not implementing an interface as is expected. In this case I am implementing interfaces for facilitating Proxy generation.</p>
  
  <p>My specific problem is using a collection of domain objects in an enhanced for loop within an ItemWriter implementation. This exception is being thrown from the enhanced for loop I reference below.</p>
  
  <pre><code>public void write(List&lt;? extends Order&gt; items) throws Exception {
          for ( Order order : items){
  </code></pre>
  
  <p>Order is an interface implemented by OrderBean.</p>
  
  <pre><code>public class OrderBean implements Order
  </code></pre>
  
  <p>And is declared as a Prototype for use by a BeanWrapperFieldSetMapper in a Spring Java Configuration class. As below.</p>
  
  <pre><code>@Bean
  @Scope("prototype")
  public Order order()
  </code></pre>
  
  <p>As an experiment I commented out the Java Configuration declaration, and replaced it with the XML declaration below.</p>
  
  <pre><code>&lt;bean name="order"
          scope="prototype"
          class="package.OrderBean"/&gt;
  </code></pre>
  
  <p>The entirety of my configuration appears below as requested in comments. I am not sure why the Order objects are being proxied, unless possibly it comes from the BeanWrapperFieldSetMapper.</p>
  
  <p>Upon further testing, I found I get the same error from any bean set with the Step scope, as in @Scope("step").</p>
  
  <pre><code>@Configuration
  public class OrderProcessingBatchConfiguration {
  
      @Value("${batch.jdbc.driver}")
      private String driverClassName;
  
      @Value("${batch.jdbc.url}")
      private String driverUrl;
  
      @Value("${batch.jdbc.user}")
      private String driverUsername;
  
      @Value("${batch.jdbc.password}")
      private String driverPassword;
  
      @Value("${order.delimiter}")
      private String delimiter;
  
      @Value("${order.item.field.names}")
      private String[] orderItemFieldNames;
  
      @Value("${order.item.file.path}")
      private String orderItemFilePath;
  
      @Value("${order.field.names}")
      private String[] orderFieldNames;
  
      @Value("${order.file.path}")
      private String orderFilePath;
  
      @Value("${query.order.clear}")
      private String deleteOrderQuery;
  
      @Value("${query.order.item.clear}")
      private String deleteOrderItemQuery;
  
      @Value("${ftp.host.name}")
      private String ftpHostName;
  
      @Value("${ftp.host.port}")
      private Integer ftpHostPort;
  
      @Value("${ftp.client.mode}")
      private Integer ftpClientMode;
  
      @Value("${ftp.file.type}")
      private Integer ftpFileType;
  
      @Value("${ftp.host.username}")
      private String ftpUsername;
  
      @Value("${ftp.host.password}")
      private String ftpPassword;
  
      @Value("${ftp.tasklet.retryIfNotFound}")
      private Boolean retryIfNotFound;
  
      @Value("${ftp.tasklet.download.attempts}")
      private Integer downloadAttempts;
  
      @Value("${ftp.tasklet.retry.interval}")
      private Integer retryInterval;
  
      @Value("${ftp.tasklet.file.name.pattern}")
      private String fileNamePattern;
  
      @Value("${ftp.host.remote.directory}")
      private String remoteDirectory;
  
      @Value("${ftp.client.local.directory}")
      private File localDirectory;
  
      @Value("${ftp.tasklet.sftp}")
      private Boolean sftp;
  
      @Value("${query.order.insert}")
      private String orderInsertQuery;
  
      @Value("${query.order.items.insert}")
      private String orderItemInsertQuery;
  
      @Autowired
      @Qualifier("jobRepository")
      private JobRepository jobRepository;
  
  
      @Bean
      public DataSource dataSource() {
          BasicDataSource dataSource = new BasicDataSource();
          dataSource.setDriverClassName(driverClassName);
          dataSource.setUrl(driverUrl);
          dataSource.setUsername(driverUsername);
          dataSource.setPassword(driverPassword);
  
          return dataSource;
      }
  
      @Bean
      public SimpleJobLauncher jobLauncher() {
          SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
          jobLauncher.setJobRepository(jobRepository);
  
          return jobLauncher;
      }
  
      @Bean
      public PlatformTransactionManager transactionManager() {
          return new DataSourceTransactionManager(dataSource());
      }
  
      @Bean
      @Scope("prototype")
      public OrderItem orderItem(){
          return new OrderItemBean();
      }
  
      @Bean
      @Scope("prototype")
      public Order order(){
          return new OrderBean();
      }
  
      @Bean
      //@Scope("step")
      public DelimitedLineTokenizer orderItemLineTokenizer(){
          DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer(delimiter);
          lineTokenizer.setNames(orderItemFieldNames);
  
          return lineTokenizer;
      }
  
      @Bean
      //@Scope("step")
      public BeanWrapperFieldSetMapper&lt;OrderItem&gt; orderItemFieldSetMapper(){
          BeanWrapperFieldSetMapper&lt;OrderItem&gt; orderItemFieldSetMapper = new BeanWrapperFieldSetMapper&lt;OrderItem&gt;();
          orderItemFieldSetMapper.setPrototypeBeanName("orderItem");
  
          return orderItemFieldSetMapper;
      }
  
      @Bean
      //@Scope("step")
      public DefaultLineMapper&lt;OrderItem&gt; orderItemLineMapper(){
          DefaultLineMapper&lt;OrderItem&gt; orderItemLineMapper = new DefaultLineMapper&lt;OrderItem&gt;();
          orderItemLineMapper.setLineTokenizer(orderItemLineTokenizer());
          orderItemLineMapper.setFieldSetMapper(orderItemFieldSetMapper());
  
          return orderItemLineMapper;
      }
  
      @Bean
      //@Scope("step")
      public Resource orderItemResource(){
          Resource orderItemResource = new FileSystemResource(orderItemFilePath);
  
          return orderItemResource;
      }
  
      @Bean
      //@Scope("step")
      public FlatFileItemReader&lt;OrderItem&gt; orderItemItemReader(){
          FlatFileItemReader&lt;OrderItem&gt; orderItemItemReader = new FlatFileItemReader&lt;OrderItem&gt;();
          orderItemItemReader.setLineMapper(orderItemLineMapper());
          orderItemItemReader.setResource(orderItemResource());
  
          return orderItemItemReader;
      }
  
      @Bean
      //@Scope("step")
      public DelimitedLineTokenizer orderLineTokenizer(){
          DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer(delimiter);
          lineTokenizer.setNames(orderFieldNames);
  
          return lineTokenizer;
      }
  
      @Bean
      //@Scope("step")
      public BeanWrapperFieldSetMapper&lt;Order&gt; orderFieldSetMapper(){
          BeanWrapperFieldSetMapper&lt;Order&gt; orderItemFieldSetMapper = new BeanWrapperFieldSetMapper&lt;Order&gt;();
          orderItemFieldSetMapper.setPrototypeBeanName("order");
  
          return orderItemFieldSetMapper;
      }
  
      @Bean
      //@Scope("step")
      public DefaultLineMapper&lt;Order&gt; orderLineMapper(){
          DefaultLineMapper&lt;Order&gt; orderItemLineMapper = new DefaultLineMapper&lt;Order&gt;();
          orderItemLineMapper.setLineTokenizer(orderLineTokenizer());
          orderItemLineMapper.setFieldSetMapper(orderFieldSetMapper());
  
          return orderItemLineMapper;
      }
  
      @Bean
      //@Scope("step")
      public Resource orderResource(){
          Resource orderItemResource = new FileSystemResource(orderFilePath);
  
          return orderItemResource;
      }
  
      @Bean
      //@Scope("step")
      public FlatFileItemReader&lt;Order&gt; orderItemReader(){
          FlatFileItemReader&lt;Order&gt; orderItemItemReader = new FlatFileItemReader&lt;Order&gt;();
          orderItemItemReader.setLineMapper(orderLineMapper());
          orderItemItemReader.setResource(orderResource());
  
          return orderItemItemReader;
      }
  
      @Bean
      @Scope("step")
      public Map&lt;String, Order&gt; orderCache(){
          Map&lt;String, Order&gt; orderCache = new HashMap&lt;String, Order&gt;();
  
          return orderCache;
      }
  
      @Bean
      public JdbcTemplate jdbcTemplate(){
          return new JdbcTemplate(dataSource());
      }
  
      @Bean
      //@Scope("step")
      public AggregatingFlatFileOrderItemReader aggregatingFlatFileOrderItemReader(){
          AggregatingFlatFileOrderItemReader aggregatingFlatFileOrderItemReader = new AggregatingFlatFileOrderItemReader();
          aggregatingFlatFileOrderItemReader.setJdbcTemplate(jdbcTemplate());
          aggregatingFlatFileOrderItemReader.setOrderCache(orderCache());
          aggregatingFlatFileOrderItemReader.setOrderItemFlatFileItemReader(orderItemItemReader());
          aggregatingFlatFileOrderItemReader.setOrderFlatFileItemReader(orderItemReader());
          aggregatingFlatFileOrderItemReader.setDeleteOrderQuery(deleteOrderQuery);
          aggregatingFlatFileOrderItemReader.setDeleteOrderItemQuery(deleteOrderItemQuery);
  
          return aggregatingFlatFileOrderItemReader;
      }
  
      @Bean
      @Scope("step")
      public SessionFactory ftpSessionFactory(){
          DefaultFtpSessionFactory ftpSessionFactory = new DefaultFtpSessionFactory();
          ftpSessionFactory.setHost(ftpHostName);
          ftpSessionFactory.setClientMode(ftpClientMode);
          ftpSessionFactory.setFileType(ftpFileType);
          ftpSessionFactory.setPort(ftpHostPort);
          ftpSessionFactory.setUsername(ftpUsername);
          ftpSessionFactory.setPassword(ftpPassword);
  
          return ftpSessionFactory;
      }
  
      @Bean
      @Scope(value="step")
      public FtpGetRemoteFilesTasklet myFtpGetRemoteFilesTasklet(){
          FtpGetRemoteFilesTasklet  ftpTasklet = new FtpGetRemoteFilesTasklet();
          ftpTasklet.setRetryIfNotFound(retryIfNotFound);
          ftpTasklet.setDownloadFileAttempts(downloadAttempts);
          ftpTasklet.setRetryIntervalMilliseconds(retryInterval);
          ftpTasklet.setFileNamePattern(fileNamePattern);
          ftpTasklet.setRemoteDirectory(remoteDirectory);
          ftpTasklet.setLocalDirectory(localDirectory);
          ftpTasklet.setSessionFactory(ftpSessionFactory());
          ftpTasklet.setSftp(sftp);
  
          return ftpTasklet;
      }
  
      @Bean
      @Scope(value="step")
      public OrderItemWriter orderItemWriter(){
          OrderItemWriter orderItemWriter = new OrderItemWriter();
  
          orderItemWriter.setJdbcTemplate(jdbcTemplate());
          orderItemWriter.setOrderInsertQuery(orderInsertQuery);
          orderItemWriter.setOrderItemInsertQuery(orderItemInsertQuery);
  
          return orderItemWriter;
      }
  </code></pre>