Piotr Zgadzaj
Piotr Zgadzaj

Reputation: 19

Random ClassCastException when using Spring proxied bean of type conversation access

I have a JEE application written in Java8 which uses Spring 4.3.24. As the fronted of my application is using JSF 2.x, I also use custom spring scope - conversation access provided by third party library which is myfaces-orchestra in version 1.4

As the application is extensively covered with Selenium tests, i'm currently analyzing the topic of running the test in multiple threads. In details: One JVM which hosts the appserver - in my case it's WebSphere 8.5.5 and one JVM which with use of JUnit 4.10 is running selenium tests in multiple threads.

Problem which i face with, but only when running tests in parallel, are occasional ClassCastExceptions thrown out of CGLIB classes when trying to interact with Conversation access beans.

The exception looks as follows:

Exception: java.lang.ClassCastException: com.sun.proxy.$Proxy499 incompatible with some.package.PageBackingBean
    at some.package.PageBackingBean$$FastClassBySpringCGLIB$$ecd1ff4d.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:736)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:133)
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:121)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:671)

As said, exception happens only from time to time. Also, it can be noticed, that it happens usually in cases when two or more threads are referring the conversation bean of the same type in the very same millisecond (of course as these two threads are using different sessions, the underlying beans are different)

What i ruled out already is:

  1. It's not a problem related to initialization of the underlying bean. Despite the fact that the bean has a PostConstruct, it's initialized successfully
  2. I thought that this problem was brought up with the upgrade to spring 4.x (from 3.x) so i tried to disable the Objenesis (by setting spring.objenesis.ignore to "true") but this also did not help

Upvotes: 0

Views: 340

Answers (1)

Piotr Zgadzaj
Piotr Zgadzaj

Reputation: 19

After further investigation, i think i found a root cause of the problem - it was located in Orchestra implementation

Basically, Orchestra each time when instantiating conversation access bean, manipulated bean definition attributes - it tried to set

AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE=Boolean.TRUE

As far as i understand, this setting tells AOP to create CGLIB proxy of the bean. As the bean attributes in bean definition are kept in standard HashMap, then this approach lead to race condition which later ended up in double proxying of conversation access beans

Upvotes: 0

Related Questions