Tuesday, May 1, 2007

Annotations - love to hate em

When annotations work, they really do feel nice. But when they don't, oh boy, the hurt they inflict can be quite horrible.

I've been working with Compass and JPA annotations. I'm starting to get a bit better with Compass and was starting to do a bit more fine grained control over some of the fields which get stored but not indexed (via @Searchable(index=Index.NO)). Suddenly on a build I get the following error:


SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'registryDao' defined in ServletContext resource [/WEB-INF/spring/persistence-context.xml]: Cannot resolve reference to bean 'entityManagerFactory' while setting bean property 'entityManagerFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in ServletContext resource [/WEB-INF/spring/persistence-context.xml]: Invocation of init method failed; nested exception is java.lang.IllegalAccessError: class sun.reflect.GeneratedConstructorAccessor11 cannot access its superclass sun.reflect.ConstructorAccessorImpl
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in ServletContext resource [/WEB-INF/spring/persistence-context.xml]: Invocation of init method failed; nested exception is java.lang.IllegalAccessError: class sun.reflect.GeneratedConstructorAccessor11 cannot access its superclass sun.reflect.ConstructorAccessorImpl
Caused by: java.lang.IllegalAccessError: class sun.reflect.GeneratedConstructorAccessor11 cannot access its superclass sun.reflect.ConstructorAccessorImpl
at sun.misc.Unsafe.defineClass(Native Method)
at sun.reflect.ClassDefiner.defineClass(ClassDefiner.java:45)
at sun.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:381)
at java.security.AccessController.doPrivileged(Native Method)
at sun.reflect.MethodAccessorGenerator.generate(MethodAccessorGenerator.java:377)
at sun.reflect.MethodAccessorGenerator.generateConstructor(MethodAccessorGenerator.java:76)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:30)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:494)
at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:588)
at sun.reflect.annotation.AnnotationParser.annotationForMap(AnnotationParser.java:239)
at sun.reflect.annotation.AnnotationParser.parseAnnotation(AnnotationParser.java:229)
at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:69)
at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:52)
at java.lang.reflect.Field.declaredAnnotations(Field.java:1002)
at java.lang.reflect.Field.getAnnotation(Field.java:989)
at java.lang.reflect.AccessibleObject.isAnnotationPresent(AccessibleObject.java:175)
at oracle.toplink.essentials.internal.ejb.cmp3.metadata.MetadataHelper.isAnnotationPresent(MetadataHelper.java:653)
at oracle.toplink.essentials.internal.ejb.cmp3.metadata.MetadataHelper.isAnnotationPresent(MetadataHelper.java:668)
at oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.MetadataAccessor.isAnnotationPresent(MetadataAccessor.java:377)
at oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.ClassAccessor.isTransient(ClassAccessor.java:385)
at oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.ClassAccessor.isValidPersistenceElement(ClassAccessor.java:408)
at oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.ClassAccessor.isValidPersistenceField(ClassAccessor.java:417)
at oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.ClassAccessor.processAccessorFields(ClassAccessor.java:525)
at oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.ClassAccessor.processAccessors(ClassAccessor.java:552)
at oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.ClassAccessor.process(ClassAccessor.java:483)
at oracle.toplink.essentials.internal.ejb.cmp3.metadata.MetadataProcessor.processAnnotations(MetadataProcessor.java:225)
at oracle.toplink.essentials.ejb.cmp3.persistence.PersistenceUnitProcessor.processORMetadata(PersistenceUnitProcessor.java:354)
at oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerSetupImpl.predeploy(EntityManagerSetupImpl.java:584)
at oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider.createContainerEntityManagerFactory(EntityManagerFactoryProvider.java:178)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:204)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:242)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1118)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1085)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:429)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:250)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:141)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:247)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:161)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:245)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:124)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1019)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:809)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:425)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:250)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:141)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:247)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:161)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:273)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:346)
at org.springframework.web.context.support.AbstractRefreshableWebApplicationContext.refresh(AbstractRefreshableWebApplicationContext.java:156)
at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:246)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:184)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:49)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3763)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4211)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:759)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:739)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:524)
at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:809)
at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:698)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:472)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1122)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:310)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1021)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:718)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1013)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:442)
at org.apache.catalina.core.StandardService.start(StandardService.java:450)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:709)
at org.apache.catalina.startup.Catalina.start(Catalina.java:551)
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:585)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:294)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:432)

You'd think that some kind of sense would be made of that by a Java developer. But it's actually quite hard to begin digging for what was really going wrong:
  • What was the class which caused the error?
  • What was the annotation being processed?
Trying to look into or step through the java.reflect package yields a "source not found". Finally, where to we look for answers - I was able to guess that this error was in one of my annotations for Compass which was a bit of a stab in the dark but worked, but this error could as likely be related to Compass, JPA/Toplink or Spring.

So now having found the error - for some reason whenever I put on a "@SearchableProperty" on a member variable on one of my classes (it's just a plain old String variable...) I get this error. I've been able to workaround this error, but I can't see a way forward to identify which part of my technology stack is actually causing it - which makes the entire Java community all the poorer for it. If this is a common scenario in the community, are we headed for more fragile and confusing builds where debugging goes back to the opaque world it used to be.

In case anyone thinks of it, I'm already using the InstrumentationLoadTimeWeaver instead of a RelfectiveLoadTimeWeaver due to previous JPA/Toplink + Tomcat errors.

1 comments:

ijuma said...

I have experienced something similar. See this Spring bug[1] for more information.

[1] http://opensource.atlassian.com/projects/spring/browse/SPR-3564