From: Giovanni Meo Date: Tue, 10 Sep 2013 10:05:56 +0000 (+0200) Subject: Fix a ClassNotFoundException raised during demarshalling X-Git-Tag: releasepom-0.1.0~111^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=81004658f4171a0f06c3a5496f39c61801189c04 Fix a ClassNotFoundException raised during demarshalling Under certain conditions an error like: Caused by: java.lang.ClassNotFoundException: org.opendaylight.controller.sal.reader.FlowOnNode at org.eclipse.gemini.web.tomcat.internal.loading.BundleWebappClassLoader.loadClass(BundleWebappClassLoader.java:312) ~[na:na] at java.lang.ClassLoader.loadClass(ClassLoader.java:356) ~[na:1.7.0_09] at java.lang.Class.forName0(Native Method) ~[na:1.7.0_09] at java.lang.Class.forName(Class.java:264) ~[na:1.7.0_09] at org.jboss.marshalling.AbstractClassResolver.loadClass(AbstractClassResolver.java:135) ~[na:na] at org.jboss.marshalling.AbstractClassResolver.resolveClass(AbstractClassResolver.java:116) ~[na:na] at org.jboss.marshalling.river.RiverUnmarshaller.doReadClassDescriptor(RiverUnmarshaller.java:893) ~[na:na] at org.jboss.marshalling.river.RiverUnmarshaller.doReadNewObject(RiverUnmarshaller.java:1205) ~[na:na] at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:272) ~[na:na] at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:209) ~[na:na] this is due to the fact that by default the Jboss Marshaller used by Infinispan uses the Thread Context Class Loader to retrieve the classloader to be used in the demarshalling function. Equinox provides a default one (org.eclipse.core.runtime.internal.adaptor.ContextFinder) as TCCL, however it heuristically try to find the classloader and in some cases can fetch the wrong one. Now given that all the classes managed by clustering services must go via OSGi it make sense to force the usage of only the bundle class loader and we let OSGi framework to figure out how to load the class. Change-Id: I24a9056eda5f6ab7b8cf0ab2e476be56cb61f6c1 Signed-off-by: Giovanni Meo --- diff --git a/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClassResolver.java b/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClassResolver.java new file mode 100644 index 0000000000..521a773966 --- /dev/null +++ b/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClassResolver.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.clustering.services_implementation.internal; + +import java.lang.ref.WeakReference; + +import org.jboss.marshalling.ContextClassResolver; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class ClassResolver extends ContextClassResolver { + private WeakReference osgiClassLoader = null; + private static final Logger logger = LoggerFactory.getLogger(ClassResolver.class); + + public ClassResolver() { + ClassLoader cl = this.getClass() + .getClassLoader(); + if (cl != null) { + this.osgiClassLoader = new WeakReference(cl); + logger.trace("Acquired weak reference to OSGi classLoader {}", cl); + } + } + + @Override + protected ClassLoader getClassLoader() { + ClassLoader ret = null; + if (this.osgiClassLoader != null) { + ret = this.osgiClassLoader.get(); + if (ret != null) { + if (logger.isTraceEnabled()) { + logger.trace("Returning OSGi class loader {}", ret); + } + return ret; + } + } + + logger.warn("Could not resolve classloader!"); + return ret; + } +} diff --git a/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManager.java b/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManager.java index f5c655a4ea..cd3a295791 100644 --- a/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManager.java +++ b/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManager.java @@ -33,6 +33,9 @@ import javax.transaction.TransactionManager; import org.infinispan.Cache; import org.infinispan.configuration.cache.Configuration; +import org.infinispan.configuration.global.GlobalConfigurationBuilder; +import org.infinispan.configuration.parsing.ConfigurationBuilderHolder; +import org.infinispan.configuration.parsing.ParserRegistry; import org.infinispan.manager.DefaultCacheManager; import org.infinispan.manager.EmbeddedCacheManager; import org.infinispan.notifications.Listener; @@ -247,8 +250,14 @@ public class ClusterManager implements IClusterServices, IContainerAware { } logger.info("Starting the ClusterManager"); try { - //FIXME keeps throwing FileNotFoundException - this.cm = new DefaultCacheManager("config/infinispan-config.xml"); + ParserRegistry parser = new ParserRegistry(this.getClass() + .getClassLoader()); + ConfigurationBuilderHolder holder = parser.parseFile("config/infinispan-config.xml"); + GlobalConfigurationBuilder globalBuilder = holder.getGlobalConfigurationBuilder(); + globalBuilder.serialization() + .classResolver(new ClassResolver()) + .build(); + this.cm = new DefaultCacheManager(holder, false); logger.debug("Allocated ClusterManager"); if (this.cm != null) { this.cm.start();