Details

    • Type: Sub-task Sub-task
    • Status: Open
    • Priority: Minor Minor
    • Resolution: Unresolved
    • Affects Version/s: 2.1.8
    • Fix Version/s: 2.0.1
    • Component/s: Infrastructure
    • Labels:
      None

      Description

      actual implemention of MultiResourceItemReader does not permit usage with step scope, to get it working the getCurrentResource needs to be added to an interface (itemstream perhaps?) or a new interface has to be introduced

        Activity

        Hide
        Dave Syer added a comment -

        I never liked that getter. Anyway, you can still use it with StepScope if you set proxy-target-class=true on the scope instance (should be in the user guide). If you really don't like that then shout, or else I'll resolve this issue.

        Show
        Dave Syer added a comment - I never liked that getter. Anyway, you can still use it with StepScope if you set proxy-target-class=true on the scope instance (should be in the user guide). If you really don't like that then shout, or else I'll resolve this issue.
        Hide
        Michael Lange added a comment -

        actually i would like an overhaul here, because:

        • getCurrentResource works reliable only if the user knows some spring batch internals, e.g. which listener to use (StepExecutionListener would be almost entirely wrong), when open/read/update is called, etc.
        • rather strange configuration to get it working with a stepScoped MRIR (..and stepScoped usage seems to be the standard here) and not so trivial coding to extract the target from the scoped proxy, actually i did not find an example for that on spring-core/batch doc

        some suggestions:

        must-have:

        nice-to-have:

        • extend itemStream interface
        • or add multi-resource-reader interface
        • and/or change internal implementation to save current.resource.0,1, and so on in executioncontext (loosely following the MultiResourcePartitioner implementation)
        Show
        Michael Lange added a comment - actually i would like an overhaul here, because: getCurrentResource works reliable only if the user knows some spring batch internals, e.g. which listener to use (StepExecutionListener would be almost entirely wrong), when open/read/update is called, etc. rather strange configuration to get it working with a stepScoped MRIR (..and stepScoped usage seems to be the standard here) and not so trivial coding to extract the target from the scoped proxy, actually i did not find an example for that on spring-core/batch doc some suggestions: must-have: add more javaDoc to the getCurrentResource(...), right now there is simply none: http://static.springsource.org/spring-batch/apidocs/org/springframework/batch/item/file/MultiResourceItemReader.html user guide entry for usage of step scoped beans as reference in other beans nice-to-have: extend itemStream interface or add multi-resource-reader interface and/or change internal implementation to save current.resource.0,1, and so on in executioncontext (loosely following the MultiResourcePartitioner implementation)
        Hide
        Dave Syer added a comment - - edited

        Fair enough, but no showstoppers there as far as I can see.

        Can you clarify a bit what you mean by knowing which listener to use?

        I think you are on the wrong track if you are thinking about how to extract targets from AOP proxies. All you need to do is set proxy-target-class=true on the StepScope and you will be able to inject MultiResourceItemReader as a concrete type, not its interface.

        Show
        Dave Syer added a comment - - edited Fair enough, but no showstoppers there as far as I can see. Can you clarify a bit what you mean by knowing which listener to use? I think you are on the wrong track if you are thinking about how to extract targets from AOP proxies. All you need to do is set proxy-target-class=true on the StepScope and you will be able to inject MultiResourceItemReader as a concrete type, not its interface.
        Hide
        Michael Lange added a comment -

        >> Can you clarify a bit what you mean by knowing which listener to use?

        to make sense it has to be at least a ChunkListener, StepExecutionListener and its after/beforeStep methods are of no use in combination with MultiResourceItemReader.getCurrentResource (except - and maybe - in case of restart, beforeStep might call reader.open(...))

        >> you will be able to inject MultiResourceItemReader as a concrete type, not its interface

        can't get that to work, keep getting
        java.lang.IllegalStateException: Cannot convert value of type [$Proxy8....

        but without proxy-target-class=true i can't extract the target so i'm halfway, is aspectj/cglib needed for this? until now i have none of these on my classpath

        Show
        Michael Lange added a comment - >> Can you clarify a bit what you mean by knowing which listener to use? to make sense it has to be at least a ChunkListener, StepExecutionListener and its after/beforeStep methods are of no use in combination with MultiResourceItemReader.getCurrentResource (except - and maybe - in case of restart, beforeStep might call reader.open(...)) >> you will be able to inject MultiResourceItemReader as a concrete type, not its interface can't get that to work, keep getting java.lang.IllegalStateException: Cannot convert value of type [$Proxy8.... but without proxy-target-class=true i can't extract the target so i'm halfway, is aspectj/cglib needed for this? until now i have none of these on my classpath
        Hide
        Dave Syer added a comment -

        If you see "[$Proxy*..." you are not using proxy-target-class=true. You will need CGlib on your classpath - the logs will tell you so if you set proxy-target-class=true and try and start an application that uses step scope.

        Show
        Dave Syer added a comment - If you see "[$Proxy*..." you are not using proxy-target-class=true. You will need CGlib on your classpath - the logs will tell you so if you set proxy-target-class=true and try and start an application that uses step scope.
        Hide
        Robert Kasanicky added a comment -

        Honestly the getCurrentResource() method wasn't meant to be public, it's actually an accidentally leaked implementation detail. Given it has found its use cases it would be interesting to hear more about them and perhaps we can improve the MRIR based on that.

        Show
        Robert Kasanicky added a comment - Honestly the getCurrentResource() method wasn't meant to be public, it's actually an accidentally leaked implementation detail. Given it has found its use cases it would be interesting to hear more about them and perhaps we can improve the MRIR based on that.
        Hide
        Michael Lange added a comment -

        is there a working test case for this ? right now i'm getting two stepScope Objects - yes i know don't mix namespace and stepScope bean, but i don't know how to set the proxyTargetClass to true while using the namespace and getting stepScope implicitly

        Show
        Michael Lange added a comment - is there a working test case for this ? right now i'm getting two stepScope Objects - yes i know don't mix namespace and stepScope bean, but i don't know how to set the proxyTargetClass to true while using the namespace and getting stepScope implicitly
        Hide
        Mark Pollack added a comment -

        I'd also like to see some better support for accessing the file currently being processed, putting it in the execution context seems pretty reasonable, though in my use case it would seem more direct to get the information from a FlatFileParseException directly.

        cglib is on my classpath and I set
        <bean class="org.springframework.batch.core.scope.StepScope">
        <property name="proxyTargetClass" value="true"/>
        </bean>

        and

        <bean id="reader" class="org.springframework.batch.item.file.MultiResourceItemReader" scope="step" >

        but still got errors trying to perform constructor injection of MRIR. Here are the two different errors, with and without setting proxyTargetClass=true. The [$Proxy4 appears in both cases, though the first shows the cglib is being used, so I'm not so sure that seeing [$Proxy is an indicator cglib isn't being used.

        with proxyTargetClass=true

        Unsatisfied dependency expressed through constructor argument with index 1 of type [org.springframework.batch.item.file.MultiResourceItemReader]: Could not convert constructor argument value of type [$Proxy4] to required type [org.springframework.batch.item.file.MultiResourceItemReader]: Failed to convert value of type '$Proxy4 implementing org.springframework.aop.scope.ScopedObject,java.io.Serializable,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised,net.sf.cglib.proxy.Factory,org.springframework.batch.item.ItemReader,org.springframework.batch.item.ItemStream' to required type 'org.springframework.batch.item.file.MultiResourceItemReader'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [$Proxy4 implementing org.springframework.aop.scope.ScopedObject,java.io.Serializable,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised,net.sf.cglib.proxy.Factory,org.springframework.batch.item.ItemReader,org.springframework.batch.item.ItemStream] to required type [org.springframework.batch.item.file.MultiResourceItemReader]: no matching editors or conversion strategy found

        without proxyTargetClass=false

        Unsatisfied dependency expressed through constructor argument with index 1 of type [org.springframework.batch.item.file.MultiResourceItemReader]: Could not convert constructor argument value of type [$Proxy4] to required type [org.springframework.batch.item.file.MultiResourceItemReader]: Failed to convert value of type '$Proxy4 implementing org.springframework.batch.item.ItemReader,org.springframework.batch.item.ItemStream,org.springframework.aop.scope.ScopedObject,java.io.Serializable,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised' to required type 'org.springframework.batch.item.file.MultiResourceItemReader'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [$Proxy4 implementing org.springframework.batch.item.ItemReader,org.springframework.batch.item.ItemStream,org.springframework.aop.scope.ScopedObject,java.io.Serializable,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [org.springframework.batch.item.file.MultiResourceItemReader]: no matching editors or conversion strategy found

        Show
        Mark Pollack added a comment - I'd also like to see some better support for accessing the file currently being processed, putting it in the execution context seems pretty reasonable, though in my use case it would seem more direct to get the information from a FlatFileParseException directly. cglib is on my classpath and I set <bean class="org.springframework.batch.core.scope.StepScope"> <property name="proxyTargetClass" value="true"/> </bean> and <bean id="reader" class="org.springframework.batch.item.file.MultiResourceItemReader" scope="step" > but still got errors trying to perform constructor injection of MRIR. Here are the two different errors, with and without setting proxyTargetClass=true. The [$Proxy4 appears in both cases, though the first shows the cglib is being used, so I'm not so sure that seeing [$Proxy is an indicator cglib isn't being used. with proxyTargetClass=true Unsatisfied dependency expressed through constructor argument with index 1 of type [org.springframework.batch.item.file.MultiResourceItemReader] : Could not convert constructor argument value of type [$Proxy4] to required type [org.springframework.batch.item.file.MultiResourceItemReader] : Failed to convert value of type '$Proxy4 implementing org.springframework.aop.scope.ScopedObject,java.io.Serializable,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised,net.sf.cglib.proxy.Factory,org.springframework.batch.item.ItemReader,org.springframework.batch.item.ItemStream' to required type 'org.springframework.batch.item.file.MultiResourceItemReader'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [$Proxy4 implementing org.springframework.aop.scope.ScopedObject,java.io.Serializable,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised,net.sf.cglib.proxy.Factory,org.springframework.batch.item.ItemReader,org.springframework.batch.item.ItemStream] to required type [org.springframework.batch.item.file.MultiResourceItemReader] : no matching editors or conversion strategy found without proxyTargetClass=false Unsatisfied dependency expressed through constructor argument with index 1 of type [org.springframework.batch.item.file.MultiResourceItemReader] : Could not convert constructor argument value of type [$Proxy4] to required type [org.springframework.batch.item.file.MultiResourceItemReader] : Failed to convert value of type '$Proxy4 implementing org.springframework.batch.item.ItemReader,org.springframework.batch.item.ItemStream,org.springframework.aop.scope.ScopedObject,java.io.Serializable,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised' to required type 'org.springframework.batch.item.file.MultiResourceItemReader'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [$Proxy4 implementing org.springframework.batch.item.ItemReader,org.springframework.batch.item.ItemStream,org.springframework.aop.scope.ScopedObject,java.io.Serializable,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [org.springframework.batch.item.file.MultiResourceItemReader] : no matching editors or conversion strategy found
        Hide
        Dave Syer added a comment -

        @Mark: maybe you are seeing the same problem as Michael (duplicate StepScope beans in the context and the wrong one is being used)?

        @Michael: there is a test for StepScope registration (AutoRegistering*Tests), but it doesn't test what happens if there is one already defined I think. Feel free to propose an improvement (but please open another JIRA ticket).

        @Mark: I slightly prefer the idea of extending the exception to carry the resource, to that of introducing a new interface to expose a method that (as Robert said) is not supposed to be public. It seems like it could be done, but not in a point release. Hopefully 2.2 will be the next release though, so it might be a good opportunity to do something in the exception imlementation.

        Show
        Dave Syer added a comment - @Mark: maybe you are seeing the same problem as Michael (duplicate StepScope beans in the context and the wrong one is being used)? @Michael: there is a test for StepScope registration (AutoRegistering*Tests), but it doesn't test what happens if there is one already defined I think. Feel free to propose an improvement (but please open another JIRA ticket). @Mark: I slightly prefer the idea of extending the exception to carry the resource, to that of introducing a new interface to expose a method that (as Robert said) is not supposed to be public. It seems like it could be done, but not in a point release. Hopefully 2.2 will be the next release though, so it might be a good opportunity to do something in the exception imlementation.

          People

          • Assignee:
            Dave Syer
            Reporter:
            Michael Lange
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated: