Giovanni Azua Giovanni Azua - 26 days ago 11
Java Question

can't instantiate singleton with `factory-method`

I had a piece of code working that integrated Hibernate 3.3.2.GA and Spring 2.5.x and these versions were old so I decided to upgrade. I first upgraded Spring to the latest available version 3.2.0.RELEASE and this worked. Actually the working project with the latest Spring version may be checked out using

svn co https://perfectjpattern.svn.sourceforge.net/svnroot/perfectjpattern/trunk perfectjpattern
. Trying to upgrade to Hibernate 4 I get a different Spring beans behavior that eludes me and it is apparently unrelated to Hibernate 4.

The failing bean configuration is below. The full working configuration using Hibernate 3 is here (I haven't checked in the failing one using Hibernate 4 ofc):

<bean id="localDaoFactory" class="org.perfectjpattern.jee.integration.dao.LocalDaoFactory"
factory-method="getInstance">
<property name="sessionStrategy">
<ref bean="daoSessionStrategy" />
</property>
<property name="transactionStrategy">
<ref bean="daoTransactionStrategy" />
</property>
<property name="personDao">
<ref bean="personDao" />
</property>
</bean>


and the stacktrace of the exception is shown below, meaning it could not initialize
org.perfectjpattern.jee.integration.dao.LocalDaoFactory
and apparently it fails while looking for accessible constructors BUT in this configuration I specify to use a factory-method and not to instantiate the bean directly. This worked before upgrading Hibernate but not after and for the same Spring (latest) version which is very confusing.

java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:157)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:313)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:284)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
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:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:53)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:123)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:104)
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.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:164)
at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:110)
at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:175)
at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcessWhenForked(SurefireStarter.java:107)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:68)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'localDaoFactory' defined in URL [file:src/test/resources/test-applicationContext.xml]: Instantiation of bean failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class org.perfectjpattern.jee.integration.dao.LocalDaoFactory
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:581)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1029)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:925)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:490)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:607)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:106)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:57)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:100)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:248)
at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:124)
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:148)
... 30 more
Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.perfectjpattern.jee.integration.dao.LocalDaoFactory
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.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:160)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:570)
... 47 more


UPDATE: while loading the Spring configuration, Spring can't find the class
LocalDaoFactory
but it did before ...

UPDATE: this is the result of running
mvn dependency:tree -Dverbose
and there are no unresolved conflicts

[INFO] --- maven-dependency-plugin:2.1:tree (default-cli) @ perfectjpattern-spring ---
[INFO] perfectjpattern:perfectjpattern-spring:jar:1.0.3-SNAPSHOT
[INFO] +- perfectjpattern:perfectjpattern-api:jar:1.0.3-SNAPSHOT:compile
[INFO] +- commons-lang:commons-lang:jar:2.5:compile
[INFO] +- org.springframework:spring-core:jar:3.2.0.RELEASE:compile
[INFO] +- org.springframework:spring-jdbc:jar:3.2.0.RELEASE:compile
[INFO] | +- (org.springframework:spring-core:jar:3.2.0.RELEASE:compile - omitted for duplicate)
[INFO] | +- (org.springframework:spring-tx:jar:3.2.0.RELEASE:compile - omitted for duplicate)
[INFO] | \- (org.springframework:spring-beans:jar:3.2.0.RELEASE:compile - omitted for duplicate)
[INFO] +- org.springframework:spring-orm:jar:3.2.0.RELEASE:compile
[INFO] | +- (org.springframework:spring-core:jar:3.2.0.RELEASE:compile - omitted for duplicate)
[INFO] | +- (org.springframework:spring-jdbc:jar:3.2.0.RELEASE:compile - omitted for duplicate)
[INFO] | +- (org.springframework:spring-tx:jar:3.2.0.RELEASE:compile - omitted for duplicate)
[INFO] | +- aopalliance:aopalliance:jar:1.0:compile
[INFO] | \- (org.springframework:spring-beans:jar:3.2.0.RELEASE:compile - omitted for duplicate)
[INFO] +- org.springframework:spring-tx:jar:3.2.0.RELEASE:compile
[INFO] | +- (org.springframework:spring-core:jar:3.2.0.RELEASE:compile - omitted for duplicate)
[INFO] | +- (aopalliance:aopalliance:jar:1.0:compile - omitted for duplicate)
[INFO] | \- (org.springframework:spring-beans:jar:3.2.0.RELEASE:compile - omitted for duplicate)
[INFO] +- org.springframework:spring-aop:jar:3.2.0.RELEASE:compile
[INFO] | +- (aopalliance:aopalliance:jar:1.0:compile - omitted for duplicate)
[INFO] | +- (org.springframework:spring-core:jar:3.2.0.RELEASE:compile - omitted for duplicate)
[INFO] | \- (org.springframework:spring-beans:jar:3.2.0.RELEASE:compile - omitted for duplicate)
[INFO] +- org.springframework:spring-context:jar:3.2.0.RELEASE:compile
[INFO] | +- (org.springframework:spring-core:jar:3.2.0.RELEASE:compile - omitted for duplicate)
[INFO] | +- (org.springframework:spring-aop:jar:3.2.0.RELEASE:compile - omitted for duplicate)
[INFO] | +- org.springframework:spring-expression:jar:3.2.0.RELEASE:compile
[INFO] | | \- (org.springframework:spring-core:jar:3.2.0.RELEASE:compile - omitted for duplicate)
[INFO] | \- (org.springframework:spring-beans:jar:3.2.0.RELEASE:compile - omitted for duplicate)
[INFO] +- org.springframework:spring-context-support:jar:3.2.0.RELEASE:compile
[INFO] | +- (org.springframework:spring-core:jar:3.2.0.RELEASE:compile - omitted for duplicate)
[INFO] | +- (org.springframework:spring-context:jar:3.2.0.RELEASE:compile - omitted for duplicate)
[INFO] | \- (org.springframework:spring-beans:jar:3.2.0.RELEASE:compile - omitted for duplicate)
[INFO] +- org.springframework:spring-beans:jar:3.2.0.RELEASE:compile
[INFO] | \- (org.springframework:spring-core:jar:3.2.0.RELEASE:compile - omitted for duplicate)
[INFO] +- commons-logging:commons-logging:jar:1.1.1:test
[INFO] +- org.springframework:spring-test:jar:3.2.0.RELEASE:test
[INFO] | +- org.springframework:spring-webmvc:jar:3.2.0.RELEASE:test
[INFO] | | +- (org.springframework:spring-context:jar:3.2.0.RELEASE:test - omitted for duplicate)
[INFO] | | +- (org.springframework:spring-core:jar:3.2.0.RELEASE:test - omitted for duplicate)
[INFO] | | +- org.springframework:spring-web:jar:3.2.0.RELEASE:test
[INFO] | | | +- (org.springframework:spring-context:jar:3.2.0.RELEASE:test - omitted for duplicate)
[INFO] | | | +- (org.springframework:spring-core:jar:3.2.0.RELEASE:test - omitted for duplicate)
[INFO] | | | +- (org.springframework:spring-aop:jar:3.2.0.RELEASE:test - omitted for duplicate)
[INFO] | | | +- (aopalliance:aopalliance:jar:1.0:test - omitted for duplicate)
[INFO] | | | \- (org.springframework:spring-beans:jar:3.2.0.RELEASE:test - omitted for duplicate)
[INFO] | | +- (org.springframework:spring-expression:jar:3.2.0.RELEASE:test - omitted for duplicate)
[INFO] | | \- (org.springframework:spring-beans:jar:3.2.0.RELEASE:test - omitted for duplicate)
[INFO] | \- (org.springframework:spring-core:jar:3.2.0.RELEASE:test - omitted for duplicate)
[INFO] +- perfectjpattern:perfectjpattern-testcommon:jar:1.0.3-SNAPSHOT:test
[INFO] | +- junit:junit:jar:4.8.1:test
[INFO] | +- org.slf4j:slf4j-log4j12:jar:1.7.2:test
[INFO] | | +- org.slf4j:slf4j-api:jar:1.7.2:test
[INFO] | | \- log4j:log4j:jar:1.2.17:test
[INFO] | \- org.easymock:easymock:jar:2.5.2:test
[INFO] +- org.hsqldb:hsqldb:jar:2.2.9:test
[INFO] \- perfectjpattern:perfectjpattern-hibernate:jar:1.0.3-SNAPSHOT:test
[INFO] +- perfectjpattern:perfectjpattern-jee:jar:1.0.3-SNAPSHOT:test
[INFO] | +- perfectjpattern:perfectjpattern-core:jar:1.0.3-SNAPSHOT:test
[INFO] | | +- (perfectjpattern:perfectjpattern-api:jar:1.0.3-SNAPSHOT:test - omitted for duplicate)
[INFO] | | +- (org.slf4j:slf4j-api:jar:1.7.2:test - omitted for duplicate)
[INFO] | | \- (commons-lang:commons-lang:jar:2.5:test - omitted for duplicate)
[INFO] | +- org.apache.geronimo.specs:geronimo-ejb_3.0_spec:jar:1.0.1:test
[INFO] | +- org.apache.geronimo.specs:geronimo-jpa_3.0_spec:jar:1.1.1:test
[INFO] | \- org.apache.geronimo.specs:geronimo-jta_1.1_spec:jar:1.1.1:test
[INFO] +- javassist:javassist:jar:3.8.0.GA:test
[INFO] +- commons-collections:commons-collections:jar:3.2.1:test
[INFO] \- org.hibernate:hibernate-core:jar:4.1.9.Final:test
[INFO] +- antlr:antlr:jar:2.7.7:test
[INFO] +- org.jboss.logging:jboss-logging:jar:3.1.0.GA:test
[INFO] +- org.javassist:javassist:jar:3.17.1-GA:test
[INFO] +- org.jboss.spec.javax.transaction:jboss-transaction-api_1.1_spec:jar:1.0.0.Final:test
[INFO] +- dom4j:dom4j:jar:1.6.1:test
[INFO] +- org.hibernate.javax.persistence:hibernate-jpa-2.0-api:jar:1.0.1.Final:test
[INFO] \- org.hibernate.common:hibernate-commons-annotations:jar:4.0.1.Final:test
[INFO] \- (org.jboss.logging:jboss-logging:jar:3.1.0.CR2:test - omitted for conflict with 3.1.0.GA)

Answer

The message Could not initialize class org.perfectjpattern.jee.integration.dao.LocalDaoFactory means that the JVM has been unable to statically initialize the class with this name.

I looked at source of this class and its superclasses HibernateDaoFactory and AbstractDaoFactory. The only static initialization done by LocalDaoFactory and HibernateDaoFactory is to create a single instance of each class and store it in a private static final field named INSTANCE. So, there must be a problem instantiating these singletons.

LocalDaoFactory has no constructor of its own, and AbstractDaoFactory's constructor uses only standard Java classes and ones in the same package as it. HibernateDaoFactory's constructor is a little more interesting, in that it creates a HibernateCurrentSessionStrategy and a HibernateConfiguredTransactionStrategy. The code itself doesn't look particularly problematic, so it seems likely that some of the classes that this code is trying to instantiate are missing.

The only dependencies that I could see on code outside PerfectJPattern were:

  • Hibernate Core,
  • Apache Commons Lang.

I'm going to assume that you do have the relevant Hibernate core JAR, so that leaves the finger of blame pointing at Apache Commons Lang.

The Apache Commons Lang website mentions that commons-lang version 3 uses a different package to earlier versions of commons-lang. Given that your project worked before upgrading to Hibernate 4 and now doesn't work, I'm going to guess that upgrading to Hibernate 4 replaces commons-lang 2.6 or earlier with commons-lang 3 or later, and the problem arises because PerfectJPattern has a dependency on commons-lang 2.

EDIT: it looks like your project does include commons-lang v2.5, so the absence of that would seem not to be the problem. A NoClassDefFoundError with message Could not initialize class ... means that the JVM has tried and failed to load the class at least twice - if you could get hold of the exception message when it failed for the first time, that might help you more. I'm afraid all I can really suggest is to start your project under a debugger that has been set to break on exceptions.