Announcement Announcement Module
Collapse
No announcement yet.
spring-agent load time weaver too late if generic Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • spring-agent load time weaver too late if generic

    I have encountered a problem when writing tests dependent upon @Configurable based injection.

    We use Load Time Weaving within our development environment using spring-agent.jar and configuration of the Load Time Weaver as follows:

    Code:
    <context:load-time-weaver aspectj-weaving="on"/>
    We are using the TestContext framework (in Spring 2.5.4), so the test references this bean through the @ContextConfiguration.

    We have a class annotated as @Configurable (ConfigurableSuperClass), and with a dependency of @Resource, the dependency then defined in the Spring XML.

    All works fine, unless we have some generic class referenced and instantiated within the class (even if the method is not called).

    For example:

    Base Configurable class:
    Code:
    @Configurable
    public class ConfigurableSuperClass {
    
        private IDependency withSetterDependency; // NOPMD
        
        /**
         * @return true if the underlying dependency has been called
         */
        public boolean ableToCallWithSetterDependency() {
    
            return (null == this.withSetterDependency) ? false : this.withSetterDependency.doSomething();
        }
    
        /**
         * @param withSetterDependency The withSetterDependency to set.
         */
        @Resource
        public void setWithSetterDependency(final IDependency withSetterDependency) {
            this.withSetterDependency = withSetterDependency;
        }
    }
    Class extending this:
    Code:
    @Configurable
    public class PlainSubClass extends ConfigurableSuperClass {
    }
    The generic class:
    Code:
    public class GenericBasedHelper<S extends ConfigurableSuperClass> {
        
        /**
         * @param someObject
         */
        public GenericBasedHelper(final S someObject) {
            
        }
    
    }
    The test case.
    Code:
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations={"ConfigurableInjectionTestContext.xml"})
    public class ConfigurableInjectionTest {
        @Test
        public void testConfigurableSuperClassNoSetter() {
            final ConfigurableSuperClass classExpectingInjection = new ConfigurableSuperClass();
            assertTrue("There is a setter method, and as this is annotated as a Resource, dependency is injected.",  //$NON-NLS-1$
                    classExpectingInjection.ableToCallWithSetterDependency()); 
        }
    
        private void referenceGeneric() {
            // This will allow test to pass
    //        final ConfigurableSuperClass classExpectingInjection = new ConfigurableSuperClass();
    //        GenericBasedHelper<ConfigurableSuperClass> helper = new GenericBasedHelper<ConfigurableSuperClass>(classExpectingInjection);
            // This fails the test
            final PlainSubClass classExpectingInjection = new PlainSubClass();
            GenericBasedHelper<PlainSubClass> helper = new GenericBasedHelper<PlainSubClass>(classExpectingInjection);
        }
    }
    When the Generic instance is defined, the Configurable class appears to be class loaded prior to the Spring application context, meaning that it is not woven.

    Commenting out the private method means that the test passes.
    Although this is purely a test scenario for me (i.e. we use Compile Time Weaving within our built application) I'd appreciate any help in understanding the cause for this (or the coding error), as I do tend to write intergration tests of this type.

    Many Thanks

  • #2
    Can you file a JIRA issue? That is the best way to track this down.

    -Ramnivas

    Comment


    • #3
      Issue has been raised with test case, and responded to.

      http://jira.springframework.org/browse/SPR-4963

      "Juergen Hoeller updated SPR-4963:
      ---------------------------------

      Fix Version/s: (was: 2.5.6)
      3.0 M2

      This is probably caused by the test class itself being loaded eagerly, including the test method code. In this case, all classes referenced in the test code would be loaded before the Spring application context bootstraps - with the bean configurer aspect indeed getting registered too late for those classes. I'm afraid there is not much we can do about this for the time being.

      I suppose we'll have to do redefinition of classes for those cases, as supported by Java 6. We'll consider that for Spring 3.0.

      Juergen"

      Now thinking about how I can workaroud the issue. I use these type of tests as within the IDE we do not use Compile Time Weaving (performance across a large code base was unworkable). However, when integration testing a number of components (screen to Domain Object, to dependency) I need to inject in the dependency (normally a mock) into the Configurable Domain Object. (Within our build environment, Compile Time Weaving is performed).
      I have looked previously at ways of bootstrapping the test runner (JUNIT4), so that before any test class is loaded, Spring is initialised with the Load Time Weaver turned on, but have not had much success.

      Any help very much appreciated.
      Marc

      Comment

      Working...
      X