从 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" 中加载了耳朵,这就是寻找对于众所周知的文件夹中的应用程序库。
然后我完成如下:
- 我按照 Oracle 文档中的描述设置了 war 项目,以便
在 war
附近的 lib 文件夹中查找库
- 我配置 maven(*) 将所有依赖项添加到 MANIFEST.MF 但 不是 在 war 的 WEB-INF/lib
- 最后,我在 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>
每个依赖项。
我在 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" 中加载了耳朵,这就是寻找对于众所周知的文件夹中的应用程序库。 然后我完成如下:
- 我按照 Oracle 文档中的描述设置了 war 项目,以便 在 war 附近的 lib 文件夹中查找库
- 我配置 maven(*) 将所有依赖项添加到 MANIFEST.MF 但 不是 在 war 的 WEB-INF/lib
- 最后,我在 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>
每个依赖项。