You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@geode.apache.org by "Francesco Foresti (JIRA)" <ji...@apache.org> on 2018/02/05 15:09:00 UTC

[jira] [Comment Edited] (GEODE-800) Geode's classloading mechanism is unable to resolve classes found within nested jars

    [ https://issues.apache.org/jira/browse/GEODE-800?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16352510#comment-16352510 ] 

Francesco Foresti edited comment on GEODE-800 at 2/5/18 3:08 PM:
-----------------------------------------------------------------

The problem seems to disappear if You override the classloaders in the FastClasspathScanner, e.g. this way (class is org.apache.geode.management.internal.cli.util.ClasspathScanLoadHelper):
{code:java}
 public static Set<Class<?>> scanPackageForClassesImplementing(String packageToScan,
                                                                  Class<?> implementedInterface) {
        Set<Class<?>> classesImplementing = new HashSet<>();
        new FastClasspathScanner(packageToScan)
                .overrideClassLoaders(ClasspathScanLoadHelper.class.getClassLoader())
                .matchClassesImplementing(implementedInterface, classesImplementing::add).scan();

        return classesImplementing.stream().filter(ClasspathScanLoadHelper::isInstantiable)
                .collect(toSet());
    }
{code}


was (Author: francesco.foresti):
The problem seems to disappear if You override the classloaders in the FastClasspathScanner, w.g. this way (class is org.apache.geode.management.internal.cli.util.ClasspathScanLoadHelper):
{code}
 public static Set<Class<?>> scanPackageForClassesImplementing(String packageToScan,
                                                                  Class<?> implementedInterface) {
        Set<Class<?>> classesImplementing = new HashSet<>();
        new FastClasspathScanner(packageToScan)
                .overrideClassLoaders(ClasspathScanLoadHelper.class.getClassLoader())
                .matchClassesImplementing(implementedInterface, classesImplementing::add).scan();

        return classesImplementing.stream().filter(ClasspathScanLoadHelper::isInstantiable)
                .collect(toSet());
    }
{code}

> Geode's classloading mechanism is unable to resolve classes found within nested jars
> ------------------------------------------------------------------------------------
>
>                 Key: GEODE-800
>                 URL: https://issues.apache.org/jira/browse/GEODE-800
>             Project: Geode
>          Issue Type: Bug
>          Components: configuration, gfsh
>    Affects Versions: 1.0.0-incubating
>            Reporter: Jens Deppe
>            Priority: Major
>              Labels: ClassLoader, DeployCommand, deploy, gfsh
>
> This issue is particularly evident when using Geode in a Spring Boot app which creates an 'über' jar containing all dependent jars.
> When Geode is launched in this context, the following errors can be seen:
> {noformat}
> [warn 2016/01/20 08:53:29.431 PST <main> tid=0xd] (tid=13 msgId=0) Required Commands classes were not loaded. Check logs for errors.
> java.lang.IllegalStateException: Required Commands classes were not loaded. Check logs for errors.
>         at com.gemstone.gemfire.management.internal.cli.CommandManager.raiseExceptionIfEmpty(CommandManager.java:249)
>         at com.gemstone.gemfire.management.internal.cli.CommandManager.loadCommands(CommandManager.java:188)
>         at com.gemstone.gemfire.management.internal.cli.CommandManager.<init>(CommandManager.java:86)
>         at com.gemstone.gemfire.management.internal.cli.CommandManager.getInstance(CommandManager.java:278)
>         at com.gemstone.gemfire.management.internal.cli.CommandManager.getInstance(CommandManager.java:258)
>         at com.gemstone.gemfire.management.internal.cli.remote.CommandProcessor.<init>(CommandProcessor.java:58)
>         ...
> {noformat}
> The problem here is in {{ClasspathScanLoadHelper.getClasses()}}. In this method we call:
> {noformat}
> Enumeration<URL> resources = ClassPathLoader.getLatest().getResources(packagePath);
> {noformat}
> However {{getResources()}} doesn't just work against the 'latest' classloader, but also considers the thread context classloader. In the case of a Spring Boot app, Spring does provide such a classloader and {{getResources}} is able to find the necessary resources {{CommandMarker}} classes. (These classes are found within a nested jar. For ex. {{jar:file:/Users/jdeppe/src/woddrive/WodDrive-GF-Server/target/WodDriveGFServer.jar!/lib/gemfire-core-1.0.0-incubating-SNAPSHOT.jar!/com/gemstone/gemfire/management/internal/cli/commands}}). This is all fine, but subsequent code doesn't consider classes (or packages) within nested jars, and in addition, when classes actually get resolved, the thread context classloader (where those resources might have come from) is not considered.



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)