Spring Framework
  1. Spring Framework
  2. SPR-8433

Regression on 3.1.0.M2: NoSuchMethodException on Inner Class

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Won't Fix
    • Affects Version/s: 3.1 M2
    • Fix Version/s: None
    • Component/s: Test
    • Labels:
      None
    • Last commented by a User:
      false

      Description

      I seem to have found a regression between 3.0.5.RELEASE and 3.1.0.M2.

      Here is the offending code:

      DaoFactory.java
      @Component("daoFactory")
      public class DaoFactory {
      
          @Autowired
          private ApplicationContext applicationContext;
      
          public TestDao getTestDao() {
              return applicationContext.getBean("test", TestDaoImpl.class);
          }
      
          @Repository("test")
          public class TestDaoImpl extends AbstractDao<Model> implements TestDao {
      
              public TestDaoImpl() {
                  super(Model.class);
              }
      
              @Override
              public Model create() {
                  return null;
              }
      
          }
      }
      

      If I run this via a simple unit test:

      DaoFactoryTest.java
      @RunWith(SpringJUnit4ClassRunner.class)
      @ContextConfiguration(locations = "classpath:applicationContext-testing.xml")
      public class DaoFactoryTest {
      
          private DaoFactory daoFactory;
      
          @Test
          public void assertGetArticleDao() {
              final TestDao testDao = daoFactory.getTestDao();
              assertNotNull(testDao);
          }
      
          @Resource
          public void setDaoFactory(final DaoFactory daoFactory) {
              this.daoFactory = daoFactory;
          }
      }
      

      I obtain this error in 3.1.0.M2:

      java.lang.IllegalStateException: Failed to load ApplicationContext
      	at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:181) ~[spring-test-3.1.0.M2.jar:3.1.0.M2]
      	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109) ~[spring-test-3.1.0.M2.jar:3.1.0.M2]
      	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75) ~[spring-test-3.1.0.M2.jar:3.1.0.M2]
      	at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321) ~[spring-test-3.1.0.M2.jar:3.1.0.M2]
      	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:220) [spring-test-3.1.0.M2.jar:3.1.0.M2]
      	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:301) [spring-test-3.1.0.M2.jar:3.1.0.M2]
      	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) [junit-dep-4.8.2.jar:na]
      	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:303) [spring-test-3.1.0.M2.jar:3.1.0.M2]
      	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240) [spring-test-3.1.0.M2.jar:3.1.0.M2]
      	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49) [junit-dep-4.8.2.jar:na]
      	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) [junit-dep-4.8.2.jar:na]
      	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) [junit-dep-4.8.2.jar:na]
      	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) [junit-dep-4.8.2.jar:na]
      	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) [junit-dep-4.8.2.jar:na]
      	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) [junit-dep-4.8.2.jar:na]
      	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) [spring-test-3.1.0.M2.jar:3.1.0.M2]
      	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) [spring-test-3.1.0.M2.jar:3.1.0.M2]
      	at org.junit.runners.ParentRunner.run(ParentRunner.java:236) [junit-dep-4.8.2.jar:na]
      	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180) [spring-test-3.1.0.M2.jar:3.1.0.M2]
      	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49) [.cp/:na]
      	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) [.cp/:na]
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) [.cp/:na]
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) [.cp/:na]
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) [.cp/:na]
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) [.cp/:na]
      Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'X.X.common.domain.dao.impl.DaoFactory$TestDaoImpl#0': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [X.X.common.domain.dao.impl.DaoFactory$TestDaoImpl]: No default constructor found; nested exception is java.lang.NoSuchMethodException: X.X.common.domain.dao.impl.DaoFactory$TestDaoImpl.<init>()
      	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:965) ~[spring-beans-3.1.0.M2.jar:3.1.0.M2]
      	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:911) ~[spring-beans-3.1.0.M2.jar:3.1.0.M2]
      	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485) ~[spring-beans-3.1.0.M2.jar:3.1.0.M2]
      	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) ~[spring-beans-3.1.0.M2.jar:3.1.0.M2]
      	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295) ~[spring-beans-3.1.0.M2.jar:3.1.0.M2]
      	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225) ~[spring-beans-3.1.0.M2.jar:3.1.0.M2]
      	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292) ~[spring-beans-3.1.0.M2.jar:3.1.0.M2]
      	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) ~[spring-beans-3.1.0.M2.jar:3.1.0.M2]
      	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:580) ~[spring-beans-3.1.0.M2.jar:3.1.0.M2]
      	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913) ~[spring-context-3.1.0.M2.jar:3.1.0.M2]
      	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464) ~[spring-context-3.1.0.M2.jar:3.1.0.M2]
      	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:73) ~[spring-test-3.1.0.M2.jar:3.1.0.M2]
      	at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:128) ~[spring-test-3.1.0.M2.jar:3.1.0.M2]
      	at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:172) ~[spring-test-3.1.0.M2.jar:3.1.0.M2]
      	... 24 common frames omitted
      Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [X.X.common.domain.dao.impl.DaoFactory$TestDaoImpl]: No default constructor found; nested exception is java.lang.NoSuchMethodException: X.X.common.domain.dao.impl.DaoFactory$TestDaoImpl.<init>()
      	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:72) ~[spring-beans-3.1.0.M2.jar:3.1.0.M2]
      	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:958) ~[spring-beans-3.1.0.M2.jar:3.1.0.M2]
      	... 37 common frames omitted
      Caused by: java.lang.NoSuchMethodException: X.X.domain.dao.impl.DaoFactory$TestDaoImpl.<init>()
      	at java.lang.Class.getConstructor0(Class.java:2706) ~[na:1.6.0_25]
      	at java.lang.Class.getDeclaredConstructor(Class.java:1985) ~[na:1.6.0_25]
      	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:67) ~[spring-beans-3.1.0.M2.jar:3.1.0.M2]
      	... 38 common frames omitted
      

      Whereas, in Spring 3.0.5.RELEASE, I get this:

      org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [X.X.common.domain.dao.impl.DaoFactory$TestDaoImpl] is defined: expected single bean but found 0: 
      	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:269)
      	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1083)
      	at X.X.common.domain.dao.impl.DaoFactory.getTestDao(DaoFactory.java:21)
      	at X.X.common.domain.dao.impl.DaoFactoryTest.assertGetArticleDao(DaoFactoryTest.java:22)
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      	at java.lang.reflect.Method.invoke(Method.java:597)
      	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
      	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
      	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
      	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
      	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
      	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
      	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
      	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
      	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
      	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
      	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
      	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
      	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
      	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
      	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
      	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
      	at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
      	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
      	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
      	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
      

      In the Inner Class, you can clearly see that there is a default constructor (which calls to a super which has a default constructor).

      =david=

        Activity

        Hide
        Chris Beams added a comment -

        Sam, from a brief analysis of the stack traces, and given that this works against 3.0.5 and not against 3.1 M2, this could be due to recent changes in TestContext. Could you triage? Thanks.

        Show
        Chris Beams added a comment - Sam, from a brief analysis of the stack traces, and given that this works against 3.0.5 and not against 3.1 M2, this could be due to recent changes in TestContext. Could you triage? Thanks.
        Hide
        Chris Beams added a comment -

        Sam, from a brief analysis of the stack traces, and given that this works against 3.0.5 and not against 3.1 M2, this could be due to recent changes in TestContext. Could you triage? Thanks.

        Show
        Chris Beams added a comment - Sam, from a brief analysis of the stack traces, and given that this works against 3.0.5 and not against 3.1 M2, this could be due to recent changes in TestContext. Could you triage? Thanks.
        Hide
        Chris Beams added a comment -

        Sam, from a brief analysis of the stack traces, and given that this works against 3.0.5 and not against 3.1 M2, this could be due to recent changes in TestContext. Could you triage? Thanks.

        Show
        Chris Beams added a comment - Sam, from a brief analysis of the stack traces, and given that this works against 3.0.5 and not against 3.1 M2, this could be due to recent changes in TestContext. Could you triage? Thanks.
        Hide
        Sam Brannen added a comment -

        Hi David,

        Seeing that your tests fail against both Spring 3.0.5 and 3.1 M2 and without seeing your configuration and full logs, I assume the cause of your problem is that TestDaoImpl is a non-static inner class. In this case TestDaoImpl's default constructor cannot be invoked reflectively without a reference to the enclosing outer class. So the Exception is correct.

        You have two options:

        1. make TestDaoImpl static, or
        2. make TestDaoImpl a top-level class in its own TestDaoImpl.java file.

        I'm resolving this issue as Won't Fix.

        If my above suggestions do not solve your problem, please post your findings here, and we can then reopen this issue.

        Regards,

        Sam

        Show
        Sam Brannen added a comment - Hi David, Seeing that your tests fail against both Spring 3.0.5 and 3.1 M2 and without seeing your configuration and full logs, I assume the cause of your problem is that TestDaoImpl is a non-static inner class. In this case TestDaoImpl's default constructor cannot be invoked reflectively without a reference to the enclosing outer class. So the Exception is correct. You have two options: make TestDaoImpl static, or make TestDaoImpl a top-level class in its own TestDaoImpl.java file. I'm resolving this issue as Won't Fix . If my above suggestions do not solve your problem, please post your findings here, and we can then reopen this issue. Regards, Sam

          People

          • Assignee:
            Sam Brannen
            Reporter:
            David Harrigan
            Last updater:
            Trevor Marshall
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:
              Days since last comment:
              2 years, 44 weeks, 3 days ago