从 WAR 加载 类 时 WebLogic 中的不一致行为在 EAR 中公开 WebServices (Servlet 3.0)

inconsistent behaviour in WebLogic when loading classes from a WAR exposing WebServices (Servlet 3.0) within an EAR

我在 Weblogic 12c (12.2.1.0.0) 中部署 EAR 包时遇到了一个非常奇怪的问题。 首先,我们需要使用一个非常古老且特定的库,但是这个库在 class 上有问题,所以我们在不同的 jar 中重写了相同的 class 并将其放在 class-路径就在有问题的那个之前强制执行 class 加载顺序,以便在运行时我们的版本更早加载并且一切都按预期工作。 不幸的是,根据 the Oracle's documentation,在部署简单的 WAR 时,Weblogic 无法按预期使用 MANIFEST.MF 文件中的 Class-Path 条目。 为了让它工作,我需要按以下方式重新打包我的应用程序:

EAR
  + libz
  + META-INF
  + ws-webapp.war

我的 "libz" 文件夹包含所有依赖项,包括遗留 jar 和修补程序。 ws-webapp 中的 MANIFEST.MF 定义了我的 Class-Path,包括前缀 "libz",它似乎工作正常。

当我尝试使用注释定义 Web 服务时,出现了奇怪的情况。 假设我有一个名为 Foo 的 class,它在遗留库中, 是我需要修补的 classes 之一。

以下代码运行良好,代码编译,EAR 部署,网络服务运行,结果是预期的,即我收到了在补丁 class 中实现的 toString():

@WebService(serviceName = "MyWebService")
public class MyWebService {

    @WebMethod(operationName = "Foo")
    public void foo() {
        System.out.println(new Foo());
    }
}

另一方面,如果我只是创建一个返回 Foo 对象的方法,如下例所示:

@WebService(serviceName = "MyWebService")
public class MyWebService {

    @WebMethod(operationName = "Foo")
    public void foo() {
        System.out.println(getFoo());
    }

    private Foo getFoo() {
        return new Foo();
    }
}

我什至不能部署 EAR,因为 Weblogic returns 一个例外:

Caused by: java.lang.ClassNotFoundException: com.legacy.Foo 

我尝试使用 weblogic 部署描述符中的 "prefer-web-inf-classes",但这种方法不起作用,因为出于上述原因我需要保持 class 加载顺序,并且我不能强制 weblogic 使用 war 的清单中的那个。 任何帮助将不胜感激。

非常感谢。

终于,我找到了解决问题的办法。 jaxws 给出了奇怪的行为。由于它是本机 java 库,Weblogic 使用系统 class 加载程序加载它。当我的对象在方法中声明时,它们自然会在运行时加载。相反,方法签名是在部署时加载的,因此,由于我的库是在 war 的清单中定义的,它们还不是 "seen",所以 ClassNotFoundException。

另一个错误,是在 ear 文件中定义自定义库文件夹:

EAR
+ libz
+ META-INF
+ ws-webapp.war

长话短说:我将 libz 重命名为 lib 并且 Weblogic 在 "standard way" 中加载了耳朵,这就是寻找对于众所周知的文件夹中的应用程序库。 然后我完成如下:

  1. 我按照 Oracle 文档中的描述设置了 war 项目,以便 在 war
  2. 附近的 lib 文件夹中查找库
  3. 我配置 maven(*) 将所有依赖项添加到 MANIFEST.MF 但 不是 在 war 的 WEB-INF/lib
  4. 最后,我在 Weblogic.xml 部署描述符中添加了指令,首先通过元素“prefer-web-inf-classes[=30= 从 war 加载库]”。

部署描述符中的 prefer-web-inf-classes 很重要,它指示 Weblogic 我们要使用 MANIFEST.MF 中描述的 Class-Path 条目 要告诉 Maven 在 MANIFEST 中包含库而不是在 WEB-INF/lib 中,只需添加

<optional>true</optional> 

每个依赖项。