GlassFish扩展了常见类加载器使用的JAR

时间:2012-05-23 19:34:50

标签: java java-ee glassfish classloader

我正在将几个应用程序从JBoss 4迁移到GlassFish 3.1.x.这些应用程序中的每一个都使用相同的API,它提供每个应用程序使用的公共类和接口。我们称之为CoreAPI.jar

CoreAPI.jar被放入GlassFish的<domain>/lib目录中,并由公共类加载器加载。

现在让我们说每个应用程序从名为Version的CoreAPI扩展一个类(而不是抽象):

public class Version {
    public String getVersion() { return null; }
}

方法getVersion()在API本身内的几个地方调用,每个使用API​​的应用程序负责扩展类并提供如下版本:

public class MyAppVersion extends Version {
    private static final String VERSION = "1.0";

    @Override
    public String getVersion() { return VERSION; }
}

当我将应用程序部署到GlassFish,捆绑在WAR或EAR中时,只要API从父类调用getVersion(),我就会得到java.lang.NullPointerException - 它似乎无法找到子类。

如果CoreAPI.jar与WAR绑定并从<domain>/lib目录中删除,则可以正确找到子类,但我不能这样做,因为许多应用程序需要它作为共享库。

有没有办法让共享库“看到”部署的应用程序中的子类?

谢谢!

澄清:我无权更改CoreAPI

2 个答案:

答案 0 :(得分:1)

要在所有应用程序之间共享库,您应该使用$GLASSFISH_HOME/glassfish/lib文件夹。当您通过更新工具向GlassFish安装加载项时,您甚至可能会注意到它将第三方jar复制到此文件夹,因此它可供所有应用程序使用。

要分享域名下的所有应用程序,您可以将其放在$GLASSFISH_HOME/glassfish/domains/your-domain/lib文件夹中,就像您一样。

为了测试你描述的内容,我创建了2个maven项目:

  • 一个叫做版本的java项目(你的CoreAPI的模拟)
  • 一个名为web-version的网络项目(将扩展CoreAPI的人)

java项目包含非抽象的CoreAPI类:

package com.acme.version;

public class Version
{
    public String getVersion() { return null; }
}

在web-version项目中,我向version-1.0.jar添加了一个提供的范围依赖项,因此它可以被编译,但是一旦它存在于Glassfish / lib文件夹中,它就不会被添加到项目中。< / p>

然后,web-version项目具有我用于测试的Version类的扩展版本:

package com.acme.web.controller;

import com.acme.version.Version;

public class ExtendedVersion extends Version
{
    private static final String VERSION = "1.0";

    @Override
    public String getVersion ()
    {
        return VERSION;
    }

    @Override
    public String toString()
    {
        return getVersion();
    }
}

然后我这样做了:

  • 构建版本项目并将生成的jar复制到$GLASSFISH_HOME/glassfish/lib文件夹,如上所述。

  • 创建了一个包含ExtendedVersion实例的控制器并部署了该应用。它在网页中输出1.0

  

有没有办法让共享库“看到”部署的应用程序中的子类?

嗯,这有点奇怪,因为正在加载共享库。似乎由于某种原因你的子类不是。 (日志中是否还有其他相关例外情况?)

我认为你已经描述过这个问题甚至可能与你使用JBoss x GlassFish转换的其他依赖关系有关,而不是你的子类或类加载方法。

答案 1 :(得分:1)

  

有没有办法让共享库“看到”一个子类   部署了应用程序?

没有。应用程序类加载器是公共类加载器的后代,类加载器只能看到它们的父级,而不能看到它们的属性。

当公共类试图在实际位于公共库中的代码中执行Class.forName("com.app.ImplementationClass")之类的操作时,通常会发现这种情况。