Announcement Announcement Module
Collapse
No announcement yet.
Exceptions with late binding Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Exceptions with late binding

    I have a job that will successfully run however I'd like to have some of the input values set via late binding. This is working fine for some classes but not others, oddly enough it works fine for classes I've written but not for any Spring Batch classes.

    The following xml definition works fine, the ftpLogProcessor has the value bound in correctly:
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:task="http://www.springframework.org/schema/task"
           xmlns:batch="http://www.springframework.org/schema/batch"
           xsi:schemaLocation="http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.1.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">
    
        <!-- FTP process, handles the processing of the ftp log files. -->
        <job id="ftpProcess" parent="latticeBaseJob" xmlns="http://www.springframework.org/schema/batch">
            <step id="ftpLogProcessStep">
                <tasklet>
                    <chunk reader="ftpLogFileReader" processor="ftpLogProcessor" writer="ftpLogFlatFileWriter"
                           commit-interval="10"/>
                </tasklet>
            </step>
        </job>
    
        <!-- This section contains all the definitions required for the job. -->
    
        <!-- FTP Log File -->
    
        <!--  this will automatically handle the reading of a ftp log file -->
        <bean id="ftpLogFileReader" class="org.springframework.batch.item.file.FlatFileItemReader">
            <property name="linesToSkip" value="0"/>
            <property name="resource" value="${ftp.log.input.file}"/>
            <property name="lineMapper">
                <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
                    <property name="lineTokenizer">
                        <bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
                            <property name="names" value="${ftp.log.column.names}"/>
                        </bean>
                    </property>
                    <property name="fieldSetMapper" ref="ftpLogFieldSetMapper"/>
                </bean>
            </property>
        </bean>
    
        <!-- This will automatically handle the mapping of values from the csv file to the FTPLogEntry bean.
            As long as the values are given to the DelimitedLineTokenizer it will match to a setter value on the bean.
         -->
        <bean id="ftpLogFieldSetMapper" class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
            <property name="prototypeBeanName" value="ftpLogEntry"/>
        </bean>
    
        <bean id="ftpLogFlatFileWriter" class="com.mit.deta.lattice.batch.writer.ShardingItemWriter">
            <property name="defaultFileDirectory" value="${default.output.location}"/>
            <property name="outputFileExtension" value="${output.file.extension}"/>
        </bean>
    
        <bean id="ftpLogProcessor" class="com.mit.deta.lattice.batch.job.ftpprocess.processor.FTPLogProcessor" scope="step">
            <property name="logFileId" value="#{jobParameters[logId]}" />
        </bean>
    </beans>
    However if I change the ftpLogFileReader entry to:
    Code:
        <bean id="ftpLogFileReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
            <property name="linesToSkip" value="0"/>
            <property name="resource" value="#{jobParameters[identifier]}"/>
            <property name="lineMapper">
                <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
                    <property name="lineTokenizer">
                        <bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
                            <property name="names" value="${ftp.log.column.names}"/>
                        </bean>
                    </property>
                    <property name="fieldSetMapper" ref="ftpLogFieldSetMapper"/>
                </bean>
            </property>
        </bean>
    I receive the following stack trace (note this is cut down to fit in the post):
    Code:
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ftpLogProcessStep': Cannot resolve reference to bean 'ftpLogFileReader' while setting bean property 'itemReader'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ftpLogFileReader' defined in BeanDefinition defined in URL [bundleentry://99.fwk1945132040/META-INF/spring/lattice-job-ftp-process.xml]: Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class $Proxy323
    	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
    	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:106)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1305)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1067)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)
    	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:290)
    	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:287)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:189)
    	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:322)
    	... 70 common frames omitted
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ftpLogFileReader' defined in BeanDefinition defined in URL [bundleentry://99.fwk1945132040/META-INF/spring/lattice-job-ftp-process.xml]: Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class $Proxy323
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)
    	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:290)
    	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:287)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:189)
    	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:322)
    	... 80 common frames omitted
    Caused by: java.lang.NoClassDefFoundError: Could not initialize class $Proxy323
    	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    	at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    	at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:588)
    	at org.springframework.aop.framework.JdkDynamicAopProxy.getProxy(JdkDynamicAopProxy.java:117)
    	at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:112)
    	at org.springframework.aop.scope.ScopedProxyFactoryBean.setBeanFactory(ScopedProxyFactoryBean.java:109)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1422)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1389)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:512)
    	... 86 common frames omitted
    I'm completely baffled as everyone else seems to use this fine.

    I'm using:
    - Spring Batch 2.1.0.M4
    - Spring 3.0.0.RELEASE
    All running on Spring DM Server: 2.0.0.RELEASE


    Any help would be appreciated.

  • #2
    Looks like a classpath issue. How did you set that up?

    Comment


    • #3
      Hi Dave, since its all running as OSGi bundles I'm not really getting a window into the classpath. My gut feel was that it's a weird OSGi class loading issue, but since it works for somethings and not others I'm not entirely convinced.

      When I run the bundle normally I can see that the bundle that this config is in has successfully loaded and in its imported packages I can see the Spring Batch bundles, the Spring AOP bundle and also the AOP Alliance bundle. With all these loaded up I would have thought that would have been enough.
      Last edited by StimpyCat; Feb 1st, 2010, 05:42 PM.

      Comment


      • #4
        Debugging ClassDefNotFound in an OSGi container is a bit of a black art, especially when it comes to proxying - you might need a reverse dependency to make sure that the bundle using the proxy also has visibility of the AOP framework classes. Can I suggest you go to the dm Server forum for advice?

        Comment


        • #5
          Ok, thanks Dave I will. I resolved a couple of tricky OSGi issues today, hopefully I'll get this one off the list soon.

          Comment


          • #6
            Success I've finally worked this out. Seems that in an OSGi world that I need to import the package of the class that I'm trying to late bind the properties to. In this case I was trying to bind to org.springframework.batch.item.file.FlatFileItemRe ader so I needed to import the pacakge org.springframework.batch.item.file.

            It seems this comes about because my bundle is handed a Proxy of the object, in this case the FlatFileItemReader. When it comes time to use the class the Proxy tries to create the class and alas can't because it can't see it.

            Hope this helps someone else.

            Comment

            Working...
            X