技术开发 频道

WebSphere Classloader对应用移植的影响

  实例

  接下来,我们用一个实例来说明针对特定的模块依赖关系应当如何设置WebSphere Classloader的装载策略(policy)以及如何将各个模块部署到合适的位置。

  有一个应用程序里有三个互相依赖的模块,其调用关系如下:

  图二、模块关系图

  其中,WAR模块中的SampleServlet类调用了UTILITY模块中SampleUtility类,如代码一所示:

  代码一、SampleServlet.java

1 public class SampleSevlet extends HttpServlet implements Servlet {
2
3   public void doGet(HttpServletRequest req, HttpServletResponse resp)
4
5   throws ServletException, IOException {
6
7   System.out.println("SampleServlet invokes SampleUtility");
8
9   new SampleUtility().callSampleSessionBean();
10
11   }
12
13   public void doPost(HttpServletRequest req, HttpServletResponse resp)
14
15   throws ServletException, IOException {
16
17   }
18
19   }
20
21

  UTILITY模块中SampleUtility类调用了EJB模块中的SampleSessionBean类(通过callSampleSessionBean方法),如代码二所示:

  代码二、SampleUtility.java

1 public class SampleUtility {
2
3   public void callSampleSessionBean() {
4
5   try{
6
7   Context initCtx = new InitialContext();
8
9   Object result = initCtx.lookup("ejb/sample/SampleSessionHome");
10
11   SampleSessionHome ssh = (SampleSessionHome)
12
13   PortableRemoteObject.narrow(
14
15   result, SampleSessionHome.class);
16
17   SampleSession ss = ssh.create();
18
19   System.out.println("SampleUtility invokes SampleSessionBean");
20
21   ss.callSampleUtility();
22
23   }catch(Exception e){
24
25   e.printStackTrace();
26
27   }
28
29   }
30
31   public void finish() {
32
33   System.out.println("The process has been finished");
34
35   }
36
37   }
38
39

  SampleSessionBean类又调用了UTILITY模块中的SampleUtility类,如代码三所示:

  代码三、SampleSessionBean.java

1 public class SampleSessionBean implements javax.ejb.SessionBean {
2
3   private javax.ejb.SessionContext mySessionCtx;
4
5   public javax.ejb.SessionContext getSessionContext() {
6
7   return mySessionCtx;
8
9   }
10
11   public void setSessionContext(javax.ejb.SessionContext ctx) {
12
13   mySessionCtx = ctx;
14
15   }
16
17   public void ejbCreate() throws javax.ejb.CreateException {
18
19   }
20
21   public void ejbActivate() {
22
23   }
24
25   public void ejbPassivate() {
26
27   }
28
29   public void ejbRemove() {
30
31   }
32
33   public void callSampleUtility() {
34
35   System.out.println("SampleSessionBean invokes SampleUtility");
36
37   new SampleUtility().finish();
38
39   }
40
41   }
42
43

  这三个类之间的调用关系如下图所示:

  图三、顺序图

  下面我们通过不同的部署策略来深入探讨WebSphere Classloader是如何影响应用程序运行的。1、如果将Utility模块(JAR文件)拷贝到Web 模块的 WEB-INF/lib 文件夹中,那么,Utility模块将会被视为War模块的一部分,如图所示:

  图四、Utility模块(JAR文件)在Web 模块中

  如果我们将WAR Classloader Policy设置为MODULE(默认设置),如图五所示:

  图五、WAR Classloader Policy设置

  那么WebSphere应用服务器会使用WAR Classloader来装载WAR模块的类文件。而EJB模块始终是通过Application Classloader进行装载,由于Application Classloader处于WAR classloader的上层,EJB模块无法引用War模块的类文件。这样,当SampleSessionBean调用SampleUtility时,会抛出异常:

  SystemOut O SampleServlet invokes SampleUtility

  SystemOut O SampleUtility invokes SampleSessionBean

  SystemOut O SampleSessionBean invokes SampleUtility

  ExceptionUtil E CNTR0020E: 在 bean"BeanId(Sample#SampleEJB.jar#SampleSession, null)"上处理方法"callSampleUtility"时发生非应用程序异常。异常数据:

  java.lang.NoClassDefFoundError: sample/SampleUtility

  at sample.SampleSessionBean.callSampleUtility(SampleSessionBean.java:41)

  如果我们将WAR Classloader Policy设置为APPLICATION,那么WebSphere应用服务器会使用Application Classloader来装载WAR模块和EJB模块的类文件。由于两个模块使用了相同的Classloader进行装载,所以两个模块间的类可以相互引用应用服务器输出的结果如下:

  SystemOut O SampleServlet invokes SampleUtility

  SystemOut O SampleUtility invokes SampleSessionBean

  SystemOut O SampleSessionBean invokes SampleUtility

  SystemOut O The process has been finished

  2、如果将Utility模块拷贝到%was_root%\lib\ext , Websphere应用服务器会使用WebSphere Extensions Classloader加载Utility模块中的类文件,由于WebSphere Extensions Classloader处于Application classloader和WAR classloader的上层,所以SampleServlet和SampleSessionBean可以引用到SampleUtility,但是SampleUtility引用不到SampleSessionBean,因此,当SampleUtility调用SampleSessionBean时会抛出异常。

  

0
相关文章