1

In my code I have a generic "Value" POJO, which contains value itself and it's class:

public class Value<T extends Serializable> implements Serializable {
    private T value;
    private Class<T> type;

    ...

}

I am using Spring Data GemFire and "repositories" feature of Spring Data (the DAOs are created automatically from interfaces). When Spring creates DAO for this bean I got:

FactoryBean threw exception on object creation; nested exception is java.lang.SecurityException: Can not make a java.lang.Class constructor accessible:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'conditionProcessor': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'globalStatusElementDAO': FactoryBean threw exception on object creation; nested exception is java.lang.SecurityException: Can not make a java.lang.Class constructor accessible
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:307) ~[spring-context-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185) ~[spring-beans-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537) ~[spring-beans-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475) ~[spring-beans-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304) ~[spring-beans-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) ~[spring-beans-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300) ~[spring-beans-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195) ~[spring-beans-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700) ~[spring-beans-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760) ~[spring-context-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482) ~[spring-context-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403) ~[spring-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306) ~[spring-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106) [spring-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4973) [tomcat-embed-core-7.0.52.jar:7.0.52]
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5467) [tomcat-embed-core-7.0.52.jar:7.0.52]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [tomcat-embed-core-7.0.52.jar:7.0.52]
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559) [tomcat-embed-core-7.0.52.jar:7.0.52]
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549) [tomcat-embed-core-7.0.52.jar:7.0.52]
    at java.util.concurrent.FutureTask.run(FutureTask.java:262) [na:1.7.0_51]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_51]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_51]
    at java.lang.Thread.run(Thread.java:744) [na:1.7.0_51]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'globalStatusElementDAO': FactoryBean threw exception on object creation; nested exception is java.lang.SecurityException: Can not make a java.lang.Class constructor accessible
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:151) ~[spring-beans-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:103) ~[spring-beans-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1514) ~[spring-beans-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315) ~[spring-beans-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:445) ~[spring-context-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:419) ~[spring-context-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:544) ~[spring-context-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:155) ~[spring-beans-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) ~[spring-beans-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:304) ~[spring-context-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    ... 22 common frames omitted
Caused by: java.lang.SecurityException: Can not make a java.lang.Class constructor accessible
    at java.lang.reflect.AccessibleObject.setAccessible0(AccessibleObject.java:139) ~[na:1.7.0_51]
    at java.lang.reflect.AccessibleObject.setAccessible(AccessibleObject.java:129) ~[na:1.7.0_51]
    at org.springframework.util.ReflectionUtils.makeAccessible(ReflectionUtils.java:444) ~[spring-core-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.data.mapping.PreferredConstructor.<init>(PreferredConstructor.java:57) ~[spring-data-commons-1.5.3.RELEASE.jar:na]
    at org.springframework.data.mapping.model.PreferredConstructorDiscoverer.buildPreferredConstructor(PreferredConstructorDiscoverer.java:106) ~[spring-data-commons-1.5.3.RELEASE.jar:na]
    at org.springframework.data.mapping.model.PreferredConstructorDiscoverer.<init>(PreferredConstructorDiscoverer.java:74) ~[spring-data-commons-1.5.3.RELEASE.jar:na]
    at org.springframework.data.mapping.model.BasicPersistentEntity.<init>(BasicPersistentEntity.java:79) ~[spring-data-commons-1.5.3.RELEASE.jar:na]
    at org.springframework.data.mapping.model.BasicPersistentEntity.<init>(BasicPersistentEntity.java:62) ~[spring-data-commons-1.5.3.RELEASE.jar:na]
    at org.springframework.data.gemfire.mapping.GemfirePersistentEntity.<init>(GemfirePersistentEntity.java:40) ~[spring-data-gemfire-1.3.3.RELEASE.jar:1.3.3.RELEASE]
    at org.springframework.data.gemfire.mapping.GemfireMappingContext.createPersistentEntity(GemfireMappingContext.java:38) ~[spring-data-gemfire-1.3.3.RELEASE.jar:1.3.3.RELEASE]
    at org.springframework.data.gemfire.mapping.GemfireMappingContext.createPersistentEntity(GemfireMappingContext.java:29) ~[spring-data-gemfire-1.3.3.RELEASE.jar:1.3.3.RELEASE]
    at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:246) ~[spring-data-commons-1.5.3.RELEASE.jar:na]
    at org.springframework.data.mapping.context.AbstractMappingContext$PersistentPropertyCreator.doWith(AbstractMappingContext.java:398) ~[spring-data-commons-1.5.3.RELEASE.jar:na]
    at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:579) ~[spring-core-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:260) ~[spring-data-commons-1.5.3.RELEASE.jar:na]
    at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:171) ~[spring-data-commons-1.5.3.RELEASE.jar:na]
    at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:140) ~[spring-data-commons-1.5.3.RELEASE.jar:na]
    at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:66) ~[spring-data-commons-1.5.3.RELEASE.jar:na]
    at org.springframework.data.gemfire.repository.support.GemfireRepositoryFactory.getEntityInformation(GemfireRepositoryFactory.java:81) ~[spring-data-gemfire-1.3.3.RELEASE.jar:1.3.3.RELEASE]
    at org.springframework.data.gemfire.repository.support.GemfireRepositoryFactory.getTargetRepository(GemfireRepositoryFactory.java:97) ~[spring-data-gemfire-1.3.3.RELEASE.jar:1.3.3.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:136) ~[spring-data-commons-1.5.3.RELEASE.jar:na]
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:153) ~[spring-data-commons-1.5.3.RELEASE.jar:na]
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:43) ~[spring-data-commons-1.5.3.RELEASE.jar:na]
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:144) ~[spring-beans-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    ... 32 common frames omitted

How can I store java.lang.Class in GemFire with Spring Data?

UPD:

public interface GlobalStatusElementDAO
  extends CrudRepository<GlobalStatusElement, String>
{
}

@Region("xxx")
public class GlobalStatusElement<T extends Serializable>
  extends Value<T>
{
  public GlobalStatusElement( final Class<T> type )
  {
    super( type );
  }
}
madhead
  • 31,729
  • 16
  • 153
  • 201
  • Can you post the full stacktrace? – Sotirios Delimanolis Mar 25 '14 at 14:40
  • I really meant the full thing, with `BeanCreationException` and the wrapping exceptions. I'd like to see why/where/from what it's trying to create a `Class` object. Your configuration wouldn't hurt as well. – Sotirios Delimanolis Mar 25 '14 at 14:44
  • @SotiriosDelimanolis, this bean does not have a cache region, it is a part of another entity. – madhead Mar 25 '14 at 14:48
  • I don't know gemfire (or maybe you aren't showing us something), so I'll suggest this: try to figure out why Spring is trying to create a `Value` object by creating and injecting a `Class` object. Do you have `javax.annotation` annotations on your `globalStatusElementDAO` bean's class? Can we see that? – Sotirios Delimanolis Mar 25 '14 at 15:03
  • @SotiriosDelimanolis it's not trying to create value. It fails on metadata creation stage. (`PreferredConstructorDiscoverer`) `globalStatusElementDAO` does not have any annotations, it is configured with `` – madhead Mar 25 '14 at 15:09
  • Let's see the `globalStatusElementDAO` bean class. – Sotirios Delimanolis Mar 25 '14 at 15:30
  • I think I'll write custom serializer for this field or bean. – madhead Mar 25 '14 at 15:39

1 Answers1

1

Class objects are generally not amenable to serialising via reflection. It is significantly easier to simply store the full class name and instantiate the class object from the name when you need it.

You could achieve this by either changing your Value class to store the class name as a String instead of the class object, or by changing how Value gets serialised.

For the second option, this can be done either by making Value implement DataSerializable, or by registering a DataSerializer for Value

jon hanson
  • 8,722
  • 2
  • 37
  • 61