-
1. Re: WildFly 8.2 and built-in Infinispan - class cast exception when redeploying wars
jaikiran Dec 31, 2014 11:16 PM (in response to hr.stoyanov)Please post the entire exception stacktrace and also relevant code from your application where you use Infinispan.
-
2. Re: Re: WildFly 8.2 and built-in Infinispan - class cast exception when redeploying wars
hr.stoyanov Jan 3, 2015 4:07 AM (in response to jaikiran)Jaikiran Pai,
Below is the class cast exception and the Java code that causes it - this type of class cast exceptions (for the same class) occur only when the same class is loaded from different classloaders. Somehow the Wildfly built-in Infinispan cache retains the classloader from previous deployments, so when the web app is redeployed, it is associated with a new classloader and the exceptions occurs upon retrieving and casting the objects from the cache. The only solution I have so far is to restart the Wildfly server. Not pretty!
,,,
static ScreenDTO getScreensForDisplay(Cache<String, Object> cache, EntityManager em, String userId) {
AtomicMap<String, Object> map = AtomicMapLookup.getAtomicMap(cache, userId);
String key = getTopScreenKey();
ScreenDTO topScreen = ScreenDTO.class.cast(map.get(key));
if (topScreen != null) {
return topScreen;
}
...
}
Caused by: java.lang.ClassCastException: Cannot cast com.peruncs.s4g.web.gwt.client.shared.ScreenDTO to com.peruncs.s4g.web.gwt.client.shared.ScreenDTO
at java.lang.Class.cast(Class.java:3361) [rt.jar:1.8.0_25]
at com.peruncs.s4g.web.gwt.server.Screen.getScreensForDisplay(Screen.java:502) [classes:]
at com.peruncs.s4g.web.gwt.server.ScreensManagerImpl.getUserScreens(ScreensManagerImpl.java:52) [classes:]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.8.0_25]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) [rt.jar:1.8.0_25]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.8.0_25]
at java.lang.reflect.Method.invoke(Method.java:483) [rt.jar:1.8.0_25]
at org.jboss.as.ee.component.ManagedReferenceMethodInterceptor.processInvocation(ManagedReferenceMethodInterceptor.java:52)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
at org.jboss.invocation.WeavedInterceptor.processInvocation(WeavedInterceptor.java:53)
at org.jboss.as.ee.component.interceptors.UserInterceptorFactory$1.processInvocation(UserInterceptorFactory.java:63)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
at org.jboss.invocation.InterceptorContext$Invocation.proceed(InterceptorContext.java:407)
at org.jboss.as.weld.ejb.Jsr299BindingsInterceptor.doMethodInterception(Jsr299BindingsInterceptor.java:82) [wildfly-weld-8.2.0.Final.jar:8.2.0.Final]
at org.jboss.as.weld.ejb.Jsr299BindingsInterceptor.processInvocation(Jsr299BindingsInterceptor.java:93) [wildfly-weld-8.2.0.Final.jar:8.2.0.Final]
at org.jboss.as.ee.component.interceptors.UserInterceptorFactory$1.processInvocation(UserInterceptorFactory.java:63)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
at org.jboss.invocation.WeavedInterceptor.processInvocation(WeavedInterceptor.java:53)
at org.jboss.as.ee.component.interceptors.UserInterceptorFactory$1.processInvocation(UserInterceptorFactory.java:63)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
at org.jboss.as.ejb3.component.invocationmetrics.ExecutionTimeInterceptor.processInvocation(ExecutionTimeInterceptor.java:43) [wildfly-ejb3-8.2.0.Final.jar:8.2.0.Final]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)
at org.jboss.as.jpa.interceptor.SBInvocationInterceptor.processInvocation(SBInvocationInterceptor.java:47) [wildfly-jpa-8.2.0
The Infinispan docs mention that one can configure:
<store-as-binary />
as a way to achieve classloader isolation. However, this configuration is not mentioned in the Wildfly Infinispan intergration document. I wonder if this can help me with my issue.
Here is my cache configuration:
...
<subsystem xmlns="urn:jboss:domain:infinispan:2.0">
<cache-container name="S4GCacheContainer" default-cache="S4GLocalCache">
<local-cache name="S4GLocalCache">
<transaction mode="NON_XA"/>
<eviction strategy="LRU" max-entries="5000"/>
<expiration lifespan="86400000"/>
<file-store passivation="true" purge="true"/>
</local-cache>
</cache-container>
...
</cache-container>
-
3. Re: WildFly 8.2 and built-in Infinispan - class cast exception when redeploying wars
rs3vans Jan 3, 2015 11:47 AM (in response to hr.stoyanov)In Java, every object retains a reference to its Class, and every Class retains a reference to its ClassLoader. If you store objects in a cache which is not part of the deployed WAR (and therefore, not destroyed when the WAR is undeployed), then those objects are not garbage collected, and their classes are not unloaded. When your newly deployed WAR starts to access the cache, it is getting instances of those objects which were part of the previous ClassLoader - they are not considered the same.
I have run into the same thing before, and I was left with manually clearing the cache just after redeploying the WAR. There may be a way to serialize the objects going into the infinispan cache, but I'm not sure how to do that...
-
4. Re: WildFly 8.2 and built-in Infinispan - class cast exception when redeploying wars
wdfink Jan 3, 2015 5:20 PM (in response to hr.stoyanov)One option to solve this might be to store the ScreenDTO class in module and use a dependency from the war. In this case the class loader does not change if you redeploy the war.
But why you need such objects if you redeploy?
-
5. Re: WildFly 8.2 and built-in Infinispan - class cast exception when redeploying wars
hr.stoyanov Jan 3, 2015 6:00 PM (in response to wdfink)Wolf-Dieter Fink,
I do not need the ScreenDTO objests when I redeploy. In fact, I configured
the cache to purge upon restart (see the module configuration I posted).
But the purge attribute does not help when redeployment wars into a running
wildfly container.
I am exploring two options now:
1. Make Infinispan serialize to binaries. This way there will be no
classloaders retained. This seems to be possible according to the
Infinispan docs and is explicitly said to guard against classloaders
issues, but seems to be unsupported by the wildfly module?
2. Implement @WebListener in my war file to start/stop the cache upon
deploy /undeploy. This way the war life cycle is synced up with
starting/stopping the cache. But early tests yesterday did not work...
Will to more tonight y
Any other ideas are welcome. This should be much easier...
/Hristo Stoyanov
-
6. Re: WildFly 8.2 and built-in Infinispan - class cast exception when redeploying wars
jaikiran Jan 4, 2015 1:15 AM (in response to hr.stoyanov)I can see why the purge attribute may not work in this case, since the cache has no link with the web application and hence no idea about the lifecycle management of the source of the cached objects. I don't know what the recommend way to deal with such cases is. Perhaps a application specific cache configured at application level instead of subsystem level? I'm just guessing though.
pferraro would know more about this (It's a holiday season right now so you might see a delayed response).
-
7. Re: WildFly 8.2 and built-in Infinispan - class cast exception when redeploying wars
pferraro Jan 7, 2015 11:55 AM (in response to hr.stoyanov)I suspect that your cache is not properly scoped to your deployment. The easiest way to properly handle cache lifecycle correctly is to let WildFly manage it (i.e. via @Resource(lookup) of the cache). That way, when your application deploys, any injected caches will start automatically, and stop automatically on undeploy (provided no other deployment/service depends on them). Stopping a cache that uses a file-store will force all cache contents to passivate. When the cache contents are passivated, they are serialized using the module identifier of the deployment - and so are able to be recognized upon re-activation by the redeployed application. However, if purge is enabled, the cache contents are discarded on stop - so each deployment *should* start with an empty cache.
It sounds to me like your cache isn't stopping properly on undeploy - which could be due to a number of reasons, including improper use of start="EAGER". Can you post your code where you obtain a reference to your cache manager and cache - and/or attempt to start/stop your cache?
-
8. Re: Re: WildFly 8.2 and built-in Infinispan - class cast exception when redeploying wars
hr.stoyanov Jan 8, 2015 12:35 AM (in response to pferraro)Paul,
Gou it to work! Thanks!
1. Here is my cache configuration:
<cache-container name="S4GCacheContainer" default-cache="S4GLocalCache">
<local-cache name="S4GLocalCache">
<transaction mode="NON_XA"/>
<eviction strategy="LRU" max-entries="5000"/>
<expiration lifespan="86400000"/>
<file-store passivation="true" purge="true"/>
</local-cache>
</cache-container>
2. Here is how I obtain the cache:
@Stateless
public class ScreensManagerImpl implements ScreensManager {
...
@Resource(lookup = "java:jboss/infinispan/cache/S4GCacheContainer/default")
private Cache<String, Object> cache;
...}
I am not sure I need the purge option, but now I see not classloader issues upon reloading the app!
Thanks!
-
9. Re: WildFly 8.2 and built-in Infinispan - class cast exception when redeploying wars
pferraro Jan 8, 2015 2:34 PM (in response to hr.stoyanov)Excellent! You would only need to enable purge if your application requires that your cache is initially empty.