4

I have two public classes configured as follows in Spring application context:

public class LoadErrorData{
  private ExceptionData exceptionData;
  public LoadErrorData() { } 
  // reminder
}

public class ExceptionData implements Serializable{
  private Resource exceptionDataResource;
  public ExceptionData() { } 
  // reminder
}

Spring applicationContext.xml :

<beans:bean id="loadErrorData" class="com.startup.LoadErrorData" init-method="startup">
  <beans:property name="exceptionData" ref="exceptionData"/> 
</beans:bean>

<beans:bean id="exceptionData" class="com.server.ExceptionData" init-method="startup">
  <beans:property name="exceptionDataResource" value="classpath:${exception.datafile.path}"/>
</beans:bean>

It gives following Exception while initializing :

Oct 07, 2013 1:45:21 PM org.apache.catalina.core.StandardContext
listenerStart 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 'loadErrorData' defined in class path resource
[spring/startup-config.xml]: Initialization of bean failed; nested
exception is
org.springframework.beans.ConversionNotSupportedException: Failed to
convert property value of type 'com.sun.proxy.$Proxy12 implementing
java.io.Serializable,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised'
to required type 'com.server.IICExceptionData' for property
'exceptionData'; nested exception is java.lang.IllegalStateException:
Cannot convert value of type [com.sun.proxy.$Proxy12 implementing
java.io.Serializable,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised]
to required type [com.server.IICExceptionData] for property
'exceptionData': no matching editors or conversion strategy found at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:609)
at
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
at
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:469)
at
org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:383)
at
org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:283)
at
org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
at
org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4723)
at
org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5226)
at
org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5221)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166) at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724) Caused by:
org.springframework.beans.ConversionNotSupportedException: Failed to
convert property value of type 'com.sun.proxy.$Proxy12 implementing
java.io.Serializable,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised'
to required type 'com.server.IICExceptionData' for property
'exceptionData'; nested exception is java.lang.IllegalStateException:
Cannot convert value of type [com.sun.proxy.$Proxy12 implementing
java.io.Serializable,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised]
to required type [com.server.IICExceptionData] for property
'exceptionData': no matching editors or conversion strategy found at
org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:485)
at
org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:516)
at
org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:510)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.convertForProperty(AbstractAutowireCapableBeanFactory.java:1406)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1365)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1118)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
... 19 more Caused by: java.lang.IllegalStateException: Cannot convert
value of type [com.sun.proxy.$Proxy12 implementing
java.io.Serializable,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised]
to required type [com.server.IICExceptionData] for property
'exceptionData': no matching editors or conversion strategy found at
org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:241)
at
org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:470)
... 25 more

but when i put

<aop:scoped-proxy proxy-target-class="true"/>

in ExceptionData bean configuration OR if i remove

implements Serializable

from ExceptionData

exception goes away. My AOP pointcut is as follows:

expression="execution(* com..*(..))"

It seems that Spring is trying to create CGLIB proxy for bean LoadErrorData (as it does not implement any interface) and JDKdynamicProxy for its dependency ExceptionData (as it does implement interface Serializable). And it is not able to do so. Because when i tell spring to create CGLIB proxy explicitly for ExceptionData it works fine. Why is this so? Why it is not able to create JDKDynamic Proxy for a bean(ExceptionData) who is a dependency of bean (LoadErrorData) for which it is trying to Create CGLIB proxy? According to documentation it says that Spring will detect it automatically.

Shailesh Vaishampayan
  • 1,766
  • 5
  • 24
  • 52

1 Answers1

2

Actually the situation you describe is exactly what is happening.

LoadErrorData is going to be a CgLIB proxy (due to no interfaces. ExceptionData is going to be a JDK Dynamic Proxy.

However your LoadErrorData expects a bean of type ExceptionData, the JDK Dynamic proxy is only a Serializable (as it will only proxy interfaces and not classes). It will never be possible to cast this to an instance of ExceptionData and hence the loading of the context will fail. (This is also what the stacktrace tells you from the error message).

It will work if you are forcing class based proxies for everything or by removing the Serializable interface. Either way will lead to a classbased proxy.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
  • will it work if I change the type of instance variable stored in LoadErrorData to Serializable? Logically it should work right? – Shailesh Vaishampayan Oct 08 '13 at 08:12
  • 1
    Injection will then happen but what are you going to do with only `Serializable`? You cannot cast it to `ExceptionData`... – M. Deinum Oct 08 '13 at 08:15
  • 1
    correct..it means ideaaly i should program to some meaningful interface rather than just classess or marker inteface.(good old design principal).thanks @M. Deinum – Shailesh Vaishampayan Oct 08 '13 at 08:17
  • So it has got nothing to with mixing proxy mechanisms. it is all about simple java right? – Shailesh Vaishampayan Oct 08 '13 at 08:19
  • Correct, although this limit is due to the fact of using JDK Dynamic Proxies (it creates a proxy which acts like all the implemented interfaces and as such isn't castable to the actual type.). – M. Deinum Oct 08 '13 at 08:22