管理WebSphere Application Server V8的迁移和新应用程序中的依赖性

本文探讨了IBM WebSphere Application Server与Rational Application Developer在应用程序开发中的协同作用,特别是依赖性管理,包括如何有效处理JAR文件,避免类冲突,以及通过不同策略管理类加载过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

IBM WebSphere Application Server可以通过快速交付创新的应用程序来帮助企业提供更丰富的用户体验。 开发人员可以从支持的基于开放标准的全面编程模型集中进行选择,从而Swift开始开发工作并利用其技能,从而使他们能够更好地使项目需求与编程模型功能和开发人员技能保持一致。 WebSphere Application Server还通过鼓励重用和延长现有应用程序资产的寿命来加快应用程序交付。

IBM Rational Application Developer提供了一个单一的,全面的开发环境,旨在满足从Web界面到服务器端应用程序,个人开发到高级团队环境以及从Java™开发到应用程序集成的各种需求。 Rational Application Developer是IBM Rational软件开发平台的一部分,该系列产品全部基于Eclipse开源平台构建,用于创建应用程序开发工具。 Rational桌面系列中的每个产品都提供相同的集成开发环境(IDE)。 这些产品之间的差异反映了每种配置中可用的插件工具。

依赖关系管理在迁移后场景中或在具有大量WebSphere Application Server依赖JAR的应用程序开发过程中起着重要作用。 例如,在某些情况下,可能会将应用程序代码从符合Java 1.4规范的竞争性平台迁移到基于最新Java规范构建的WebSphere Application Server V8。 如果在这种情况下,依存关系安排不当,您可能会遇到与类相关的异常。 尽管每个应用程序服务器都有自己的保留应用程序JAR文件的方式,但是最好使用Rational Application Developer和WebSphere Application Server提供的最佳选项来重新排列这些JAR。

本文研究了通过Rational Application Developer V8.0和WebSphere Application Server V8.0进行的依赖性管理。 这里的重点是迁移后的方案,但是此处提供的大多数信息也适用于其他情况。

应用架构分析

从Rational工具(图1)生成的EAR包含一个EJB模块和一个Web模块,以及一个可选的应用程序客户端,连接器模块等等,其中以下部署描述符标识了每个模块:

  • application.xml
  • ejb-jar.xml
  • web.xml
  • ra.xml。
图1.应用程序EAR结构
图1.应用程序EAR结构

请记住,EAR可以具有多个EJB和Web模块,因此可能会遇到以下情况:

  • 因为在EJB和Web模块中都使用了某些应用程序类,所以它们在两者中都被复制了。
  • 在EJB和Web模块中都引用了一些JAR,因此JAR的副本保存在多个位置。

这种依赖关系的几个例子都涉及记录器,XML解析器等。 下一节将说明如何有效管理这些内容。

在将EAR放入Rational Application Developer工作空间中的应用程序开发或迁移后的过程中,重要的一步是分析应用程序体系结构以标识其使用的库。 除了通常的JSP,Servlet和EJB,应用程序可能由诸如Struts,Spring,Hibernate等开源框架组成。 在许多情况下,这些框架依赖项仅位于Web模块中。 EJB和Web模块将很少使用诸如记录器(例如log4j)之类的依赖项。 如上所述,在EJB和Web模块中都可能存在重复的类,因为它们在两者中都使用了。 除此之外,应用程序可以具有许多JAR依赖项来支持框架JAR。 这些依赖关系相互之间具有内部引用,对于应用程序执行可能很重要。

很少有开源应用程序服务器将其JAR捆绑在EAR中,从而增加了不必要的依赖性。 一个示例是j2ee.jar,它可以解析特定于J2EE的类。 通过使用Rational工具提供的WebSphere Application Server V8.0运行时来构建应用程序代码,可以减少这些JAR文件的存在。 您可以通过在项目构面中设置应用程序服务器运行时来执行此操作。

一种选择是使用{APPSERVER_ROOT} / plugins JAR(前缀为javax.j2ee。*和org.apache。*)来解决应用程序依赖性。 这将需要一次性的代码重建工作。 (请注意,在服务器启动期间会加载javax.j2ee.servlet.jar和com.ibm.ws.runtime.jar。)

一旦确定了这些依赖性,就可以解决这些JAR文件的分发问题。

管理Web模块的JAR

该Web模块由JSP和servlet组成,可以使用标准模板库(JSTL等),MVC和ORM框架(Struts,Hibernate等),XML框架,Web服务等进一步增强。 根据这些库的使用方式,JAR可以成倍增长,因此需要进行管理。 这些JAR通常保存在WEB-INF / lib目录中(图2),默认情况下由WAR类加载器加载。 您可以通过Rational Application Developer将JAR放入此文件夹。 稍后我们将讨论可以作为例外管理多少个JAR。

图2. WEB-INF / lib目录
图2. WEB-INF / lib目录

管理EJB模块的依赖关系

可以将EJB模块中的类所引用的Java归档保存在EAR级别的共享库中,该库可以通过Rational Application Developer创建。 要将外部JAR导入为EAR级别的共享库,您需要将其作为Java EE实用程序jar导入。 去做这个:

  1. 在Rational Application Developer中的EAR上单击鼠标右键,然后选择Import> Java EE Utility Jar(图3)。
    图3. JavaEE Utility Jar选项
    图3. JavaEE Utility Jar选项
  2. 从外部位置单选按钮, 将Utility jar复制到现有的EAR中 (图4),然后单击Next
    图4.从外部位置将实用程序jar复制到现有的EAR中
    图4.从外部位置将实用程序jar复制到现有的EAR中
  3. 浏览找到JAR文件(图5),选择文件,然后单击Finish 。 导入完成后,您应该看到在EAR中创建了一个lib文件夹(图6)。
    图5.选择外部罐子
    图5.选择外部罐子
    图6.导入后创建的lib文件夹
    图6.导入后创建的lib文件夹

EAR级别的依赖关系对于Web和EJB模块都是可见的。 因此,按照上述步骤,还可以将需要在模块之间共享的自定义应用程序JAR与第三方JAR一起放置在此位置。

跨多个模块共享应用程序类

在某些情况下,应用程序EAR在EJB和Web模块中可能具有重复的Java类。 这些重复的类可以保存在一个单独的通用模块(称为Java实用程序模块)中。 在Rational Application Developer中,您可以通过导航到File> New> Other ...> Java EE> Utility Project (图7)来在EAR中创建Java实用程序模块。

图7. Utility Project选项
图7. Utility Project选项

命名Utility项目并将其与现有EAR关联(图8)。 这将在EAR中创建一个lib文件夹。 如果lib文件夹已经存在,例如,如前所述,通过导入JAR,则在导出EAR之后,实用程序模块将作为JAR复制到该文件夹​​中。

图8.命名实用程序项目
图8.命名实用程序项目

要在多个模块之间共享类,请将所有Java类以及完全合格的包层次结构复制到此Utility项目的src文件夹中(图9)。

图9.共享实用程序项目中的类
图9.共享实用程序项目中的类
图10. EAR内的lib文件夹
图10. EAR内的lib文件夹
图11. lib文件夹的内容
图11. lib文件夹的内容
图12. SharedClassesUtility jar中的类
图12. SharedClassesUtility jar中的类

要在引用此共享实用程序的其他模块(Web和EJB)中构建代码,可以在要从中访问其类的每个模块中添加对该实用程序的项目引用(图13)。

图13.其他模块中的引用共享实用程序
图13.其他模块中的引用共享实用程序

图14和15显示了WebSphere Application Server为此特定EAR加载类的顺序。

图14. Web模块看到的类
图14. Web模块看到的类
图15. EJB模块看到的类
图15. EJB模块看到的类

在EAR之外管理其他依赖项

如果EAR内的应用程序受多个JAR依赖项的支持足以显着增加EAR的大小,则最好将这些JAR保留在外部文件夹中,并将其与应用程序关联为共享库。

要创建共享库,请在文件系统上的任何位置(最好在{APPSERVER_ROOT}上)创建一个文件夹,然后在Environment> Shared library的Classpath字段中设置其位置(图16)。

图16.配置共享库
图16.配置共享库

一旦配置了共享库,您就可以通过导航到应用程序>企业应用程序> {应用程序名称}>共享库引用 ,将其与应用程序关联,并将其与EAR或Web模块关联(图17)。

图17.将共享库与EAR相关联
图17.将共享库与EAR相关联

类加载行为

接下来,让我们看一下如何使用WebSphere Application Server管理控制台中可用的类加载器查看器来观察运行时的类加载行为。 在调查与类加载器相关的问题时,此信息很有用。 在WebSphere Application Server中,有两种类型的类加载器起着重要的作用。 应用程序类加载器将与应用程序关联的Enterprise JavaBean™(EJB)模块,共享库,资源适配器档案(RAR文件)和依赖性Java档案(JAR)文件分组。 依赖关系JAR文件是JAR文件,其中包含可由企业bean和servlet使用的代码。 应用程序类加载器是Web应用程序归档(WAR)类加载器的父级。 默认情况下,Web模块具有自己的WAR类加载器,以加载Web模块的内容。 应用程序类加载器的WAR类加载器策略值确定是使用WAR类加载器还是应用程序类加载器加载Web模块的内容。

图18.类加载器的层次结构图
图18.类加载器的层次结构图

与WebSphere Application Server V8.0关联的缺省服务器级别的类加载器策略是“ Multiple”(父类加载器优先)。 这表示每个EAR将获得自己的类加载器,并且在每个应用程序中,首先加载EAR级别的库,然后再加载Web库。

为了通过类加载器查看器了解类加载器的行为,我们将使用log4j库,并观察将其保存在EJB模块,Web模块或两者中以用于类加载策略时的加载行为。 通过导航到“ 疑难解答”>“类加载器查看器”>“ server1”>“ {YOUR APPLICATION}”,可以通过管理控制台访问“ 类加载器查看器”

使用PARENT_FIRST的类加载行为

首先加载应用程序库,然后是Web库。 如果JAR依赖项仅由Web模块类使用,则可以将其保留在WEB-INF / lib中,而开发人员创建的已编译Java类将包含在WEB-INF / classs中。 让我们看两种情况:

  • 情况1:将log4j jar复制到WEB-INF / lib目录中

    当log4j JAR仅保存在WEB-INF / lib目录中时,它将由Web类加载器加载,并且JAR内的类仅对Web模块Java类可见(图19)。

    图19. Web类加载器加载的log4j jar
    图19. Web类加载器加载的log4j jar
  • 情况2:在应用程序级库复制的log4j jar

    当log4j.jar文件保存在EAR级别的库中时,两个模块中的类均可见。 在图20中,log4j并未从WEB-INF / lib中删除,只是为了展示如何在EAR级别库中加载附加JAR并在类加载器查看器中看到它。

    图20.由应用程序和WEB类加载器加载的log4j jar
    图20.由应用程序和WEB类加载器加载的log4j jar

检测重复和版本化的JAR

放置在EAR中不同位置或相同位置的同一库的两个版本可能会导致类冲突,例如与版本有关的问题。 例如,假设在EAR级别上,您具有包含方法f()的JAR文件的版本1,在Web级别上,您具有相同的JAR文件的版本3,其中包含了方法f(String),并且删除了f()由于弃用。 如果应用程序类尝试访问f(String),它将获得java.lang.NoSuchMethodError,因为Web模块中的类只能看到由不具有f(String)方法的应用程序类加载器加载的JAR。 为了测试这一点,将两个版本的log4j保留在EAR和Web模块级别,并通过类加载器查看器进行了验证,如图21所示。

图21.重复的jar检测
图21.重复的jar检测

使用PARENT_LAST的类加载行为

当类加载设置更改为PARENT_LAST时,Web类加载器的优先级高于应用程序类加载器的加载类。 在这种情况下,Web应用程序将无法查看EAR级别的可用类。 与上面的图21相比,您可以在图22中看到在../TestApp.ear/lib/log4j-1.2.16.jar之前加载../WEB-INF/lib/log4j.jar。

图22.父类最后一个类加载器策略
图22.父类最后一个类加载器策略

测试应用场景

依赖可见性测试

随附的下载资料随附的测试用例显示了log4j库和共享实用程序的配置,因此可以从EJB和基于Web模块的应用程序类中调用它。 创建了两个log4j属性文件,以分别写入EJB和Web模块的日志。 这些属性文件保存在定制文件夹{PROFILE_ROOT} / log4jProperty中(图23和24)。 log4j jar保留在EAR级别的库中,以使其对EAR的所有模块中的类可见。

图23. log4j属性文件文件夹
图23. log4j属性文件文件夹
图24. log4j属性文件
图24. log4j属性文件

各个属性文件被加载到相关模块中,如图25和26所示。

图25.在EJB中加载属性文件
图25.在EJB中加载属性文件
图26.在servlet中加载属性文件
图26.在servlet中加载属性文件

由于在EJB和Web模块中都引用了log4j库,因此应保持依赖关系,以便对两个模块都可见(图27)。

图27.生成的日志
图27.生成的日志

共享实用程序测试

该测试显示了如何在多个模块之间共享通用应用程序类。 为了测试共享实用程序,我们开发了一个TestSharedUtility类,该类已从EJB和Web模块中成功调用,并记录了响应(图28至30)。

图28.共享实用程序类
图28.共享实用程序类
图29.来自EJB模块的类调用
图29.来自EJB模块的类调用
图30.来自Web模块的类调用
图30.来自Web模块的类调用

类冲突测试

为了测试类冲突,使用两个具有相同名称但具有不同参数的方法创建了两个JAR依赖项。 假定已经弃用了依赖项1的方法并将其从依赖项2中删除。尽管可能存在多个排列来保留这些依赖项,但是在EAR级别将依赖项1保留为实用程序JAR,而在WEB中保留了依赖项2 -INF / lib目录。 知道依赖项1是由应用程序类加载器加载的,而依赖项2是由Web类加载器加载的,观察来自Servlet的调用中的行为(图31和32)。

图31. Version1类方法签名
图31. Version1类方法签名
图32. Version2类方法签名
图32. Version2类方法签名

在版本2的情况下,由于不推荐使用,方法f()已被删除。 较旧的JAR版本1test.jar保持在EAR级别,而较新的JAR版本2test.jar保持在WEB-INF / lib中(图33)。

图33.复制的JAR的位置
图33.复制的JAR的位置

假设测试servlet要调用较新的JAR的方法,并且先前的JAR被错误地保持在EAR级别,则新结果如图34所示。

图34.调用新方法版本
图34.调用新方法版本

运行测试时,该servlet将看到version1test.jar文件的类,因此将抛出清单1中所示的异常。

异常跟踪
[4/13/12 6:25:10:247 EDT] 00000021 servlet
E com.ibm.ws.webcontainer.servlet.ServletWrapper service Uncaught service() exception 
thrown by servlet com.ibm.test.VersionTestServlet: java.lang.NoSuchMethodError: 
com/ibm/test/TestClass.f(Ljava/lang/String;)Ljava/lang/String;
   at com.ibm.test.VersionTestServlet.doPost(VersionTestServlet.java:41)
   at javax.servlet.http.HttpServlet.service(HttpServlet.java:595)
   at javax.servlet.http.HttpServlet.service(HttpServlet.java:668)
   at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1147)
   at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:
	722)
   at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:
	449)
   at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest
	(ServletWrapperImpl.java:178)
   at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters
	(WebAppFilterManager.java:1020)
   at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:3703)
   at com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:304)
   at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:953)
   at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1655)
   at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:195)
   at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination
	(Http	InboundLink.java:452)
   at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewRequest
	(HttpInboundLink.java:511)

您可以通过从EAR中删除version1test.jar并将其保留在WEB-INF / lib中的方式来删除该异常,或者通过将version1test.jar替换为version2test.jar并将其从WEB-INF / lib中删除的方式来删除该异常(如果其类需要)也可以从EJB调用。

结论

在设计新的应用程序或执行迁移时,计划依赖关系始终是最佳实践。 它不仅有助于更好的应用程序管理,而且还减少了与类相关问题的故障排除相关的复杂性。

致谢

作者感谢Deepak Gupta对本文的审阅。


翻译自: https://www.ibm.com/developerworks/websphere/techjournal/1205_chandra/1205_chandra.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值