[精华文章集锦] 调试WebSphere应用程序

IBM文章编辑 2007-08-07
本文介绍如何使用该调试器及其某些基本/集成功能调试 Java 应用程序,这些应用程序在 WebSphere Studio Application Developer 中使用 EJB、servlet 和 JSP。

2001 年,IBM 为开放源代码社区引入了 Eclipse 平台,以努力使其产品的工具对第三方产品更加开放,同时也努力对平台进行总体上的加强。作为这个战略的一部分,IBM 现在提供了一套新工具,用来构建基于 Eclipse 平台的企业 Java™ 应用程序。这套新工具称为 WebSphere™Studio Application Developer,它集成了一个基于 Java 的调试器来作为它自己的调试器。

这给我们带来了很大的好处,因为我们不必再使用两个调试器。VisualAge™forJava 由一个在 VisualAge for Java 内进行调试的内部调试器和一个用于调试远程服务器的 IBM 远程调试器(IBM Remote Debugger)组成。现在我们可以使用一个调试器,它可以满足您的全部需要,并且具有 IBM 一贯提供的丰富的功能。

我们打算在两篇文章中向您介绍这个调试器。我们假设读者熟练掌握了 J2EE、WebSphere Studio Application Developer 开发和部署的基础知识。

在这篇文章中,我们通过在 WebSphere Studio Application Developer 内使用 EJB、Servlet 和 JSPs™,向您介绍如何使用这个调试器及其某些基本/集成功能来调试 Java 应用程序。我们将采取一种实际操作的办法介绍一个简单的 Web 应用程序,这个应用程序存在几个相互嵌套的问题(一个问题在 JSP 代码中,一个问题在 Servlet 代码中,还有一个问题在 EJB 代码中),我们将使用这个调试器发现和修正全部三个问题。

在第2 部分中,我们将说明,把应用程序部署到 WebSphere Application Server,高级版(Advanced Edition(AE))之后,如何使用 WebSphere Studio Application Developer 来调试它。

从这里可下载文件DebugInWSADpt1.zip ,包含有本文所描述的类和归档。

调试一个简单的 Java 应用程序

在调试器中启动您的应用程序

   1. 切换到(或打开)一个 Java 透视图。
   2. 创建一个新的 Java 工程并将之称为 TestDebug。
   3. 将样本 Java 应用程序 testdebug.jar 文件导入到 TestDebug 工程。
   4. 请检查 poc.debug.app.AppDebug.java 。它是一个简单的应用程序,我们将用它来演示调试器的基础知识。
   5. 插入一个断点到 main 方法中的循环内的以下语句: x = y + z;

      要这样做,您可以双击源代码的左窗格,或使用弹出菜单,如下面的图 1 所示。
   6.

      图 1. 向源代码添加断点

      向源代码添加断点
   7. 在工具栏中,单击 Debug( Debug 图标)按钮。您将看到一个对话框,询问您想使用哪一个启动程序。选择 Java Application,选中 Set as default launcher...复选框,然后单击 Next。

      运行应用程序的另一个按钮是 Run( Running man 图标)按钮。这个按钮在非调试 Java JVM 中运行应用程序,这种 JVM 的执行速度更快,但不允许调试或使用断点。这是 WebSphere Studio ApplicationDeveloper 和 VisualAge for Java 之间的根本不同之处,VisualAge for Java 在它自己的 JVM 中运行所有应用程序,并且总是在调试模式中。而 WebSphere Studio Application Developer 则使用可插式 JVM,并且您可以选择是否要在调试模式中运行。

   8. 选择您想测试的类。WebSphere Studio Application Developer 给您一个选项,让您选择要用应用程序启动程序(Application Launcher)启动的、在同一个工程中的一组类。
   9. 这个启动程序将启动另一个 JVM 进程来运行您的应用程序(看一下 Windows Task Manager ,其中将显示一个额外的 javaw 进程,并且将出现一个带 AppDebug.java 源代码的 Debug 视图。)

现在让我们停下来,快速看一下我们在调试模式中可以使用的不同视图和功能。

调试器透视图和调试器任务

Debug/Process/Navigator 视图

Debug 视图显示当前线程、先前终止的线程、执行堆栈和停止时所在的当前断点。请注意,正是这个 debug 视图带有这些熟悉的按钮: Step、 Step into、 Step out、 Run、 Suspend和其它调试控制按钮。

单击 Process 窗格将向您显示当前进程,系统正在用来运行这个应用程序的可执行文件(在我们的案例中是 javaw )。

Navigator 窗格只是一个浏览器,它允许您全面浏览代码,而且不用离开调试透视图就可以再多设置些断点。

图 2. Debug/Process/Navigator 视图

Debug/Process/Navigator 视图

Breakpoint/Inspector/Variables/Inspector 视图

这个视图的缺省窗格是 Breakpoints 视图,您将在其中看到程序中可用断点的列表。您也可以在一个断点上单击鼠标右键并从弹出菜单中选择 HitCount,它告诉调试器在一定数量的命中后停止。如果你想让循环停止于某次迭代,在这样的循环内设置断点,这很有用。

把您的断点的 HitCount设置为 2。

如果您在 Variable 窗格上单击,那么您将有机会看见可用的变量以及它们的值。在任何变量上单击鼠标右键,您都将得到以下选项:

    * Inspect-- variables 视图可能包含许多变量。inspector 视图允许您集中在感兴趣的少量变量上。
    * Change Value-- 这是一个非常重要的功能。当您选择这个选项时,您将可以改变所选定的变量的值,并可以研究这一改变对程序执行的影响。
    * Show Type Names-- 这个选项显示变量的类型。
    * Show Qualified Names-- 这个选项允许您看到变量类型的全限定名。

图 3. Breakpoint 视图

Breakpoint 视图

图 4. Variables 视图

Variables 视图

单击 Run( Run 图标)按钮,您将注意到执行将在断点处停止。检查 count 变量和其它变量的值,确认程序执行在循环的第二次迭代处停止。这是我们前面设置的命中计数(hit count)。

Code、Outline 和 Tasks/Console 视图

Code 和 outline 视图跟您在其它透视图中看到过的视图是相同的。tasks 视图也一样,它与 Console 视图共享同一个窗格。这个调试器的优秀功能之一是可以运行到代码的某个点上。

例如,如果我们现在想运行到并停止在循环后面紧跟的语句上,则我们可以在 code 视图中,在该语句上单击鼠标右键并选择 Run to Line。当您单步执行(step-over)该语句时,程序在 console 视图中输出 x 的值。请注意 console 视图如何自动变成活动的窗格。这是 console 视图的缺省行为,每次您输出一些内容时,console 视图都会变成活动的。您可以从 Preferences 对话框的 Debug 窗格改变这种行为和 console 视图中的输出格式。

在运行调试器时修改代码(热修改)

在 VisualAge for Java 中,我们有了“热方法编译(hot method compiling)”功能。这意味着我们可以在调试一个方法时修改该方法内的代码,调试器会自动跳回到执行块的开头,我们可以继续调试而无需重新运行应用程序。这是一个可用于 VisualAge for Java JVM(我们称它为“J9”类 JVM)的功能。这个功能在标准 JVM(例如:WebSphere Studio Application Developer 附带的 JVM)中是没有的。

这个新工具确实虑及了在您修改 WebSphere Application Server 中的 Servlet 后重新装入它。这保证了这个 Servlet 方法的第二次执行将反映您的最新修改。

Servlet/JSP 的调试

要演示编译器调试 Servlet/JSP 的功能,请将 TestEAR.ear 文件装入到名为 TestEAR的工程。如果您遇到了任何编译错误,请确保刚刚创建的 AdderEJB 工程在 AdderWEB 工程的类路径中。

理解 Adder 企业应用程序

我们构建了一个名为 poc.debug.ejbs.AdderSession 的会话 EJB,它提供 strCat 方法,这个方法使用内存缓冲区(在 Java 中将字符串连接起来的快速的、推荐的办法)将两个字符串连接起来。

我们还有一个围绕我们的会话 bean 的访问 bean -- poc.debug.ejbs.AdderSessionAccessBean 。

我们使用 WebSphere Studio Application Developer 构建访问这个访问 bean 的 Web,它生成如下内容:

    * poc.debug.Servlet.AdderController -- 一个 Servlet,它将表单的输入导到输出 JSP。
    * poc.debug.Servlet.AdderViewBean -- 这个 bean 封装调用访问 Bean 的 strCat 的逻辑,然后将结果传回到调用者。
    * AdderInputForm.html -- 这是一张输入表单,它接受用户输入并调用 AdderController Servlet。
    * AdderResults.jsp -- 这是 JSP 结果页,它使用 AdderViewBean 显示结果。

配置/运行应用程序

   1. 创建 WebSphere 4.0 测试实例/配置(Test Instance/Configuration)并命名为 TU(测试单元(Test Unit))。
   2. 在 TU 的 Configuration 中,单击鼠标右键并将 TestEAREAR 添加到配置中。
   3. 从 Servers 视图选择 TU服务器并单击 Run( Running man 图标)按钮。
   4. 在您的 Web 浏览器中,输入: http://localhost:8080/Adder/
   5. 这应自动装入 AdderInputForm.html ,因为它被配置为一个欢迎页面。
   6. 在输入表单中,输入任意两个字符串,单击 Submit并注意结果。
   7. 您应得到 404 error file not found AddResultX。

停止服务器,让我们找出如何使用这个调试器来定位这个问题。

调试 Servlet

   1. 在 Java 或 Web 透视图中,打开 AdderWeb 工程并定位到 AdderController.performTask() 方法。
   2. 在 try 块的第一行: performServices(request, response); ,设置一个断点。
   3. 现在再次启动服务器,但这次请单击 Debug( Debug 图标)按钮,这样服务器将以调试模式启动,并启用了断点。
   4. 将 AdderInputForm.html 重新装入到 Web 浏览器。
   5. 在输入表单的两个域中输入任意两个字符串并单击 Submit。
   6. 您会注意到 Server 透视图变成活动的了,您将可以在其中进行调试。

      在 server 透视图中,您将注意到的第一件事是,Debug、Console 和 Variables 窗格共享同一个窗口!由于在您单步遍历执行(step through)代码的过程中,每当需要检查变量值时都要切换窗口,所以这可能不太方便。这个问题的解决办法是,或者自己重新安排这些 server 视图,或者在 Debug 视图中进行调试,Debug 视图更适合于这个过程。在 Debugger 透视图中进行调试有两种方式。第一种容易的方式是在命中代码中的断点之前手工切换到 debugger 透视图。这并非总是容易的。比如说,您在 HttpServlet.init() 方法(被设置为在启动时自动装入)中设置了一个断点。所以,现在我们将向您展示如何在 Debug 透视图中调试服务器,即使您在该服务器或任何其它透视图中获取了断点。

   7. 切换到 Debug 透视图
   8. 在 Debug 视图中,首先定位到 Server 进程,如下面的图 5 所示。
   9.

      图 5. Debug 进程视图

      Debug 进程视图
  10. 在运行在 server 之下的线程的列表中,定位到列表底端附近的线程,也就是紧靠着底端的 Suspended (breakpoint ...,如下面的图 6 所示。如上面的图 5 所示,由于有 +号紧靠着它,定位这个线程显然很容易。如果展开这个线程,您将看到执行堆栈。
  11.

      图 6. debug 视图中的暂挂进程

      debug 视图中的暂挂进程
  12. 双击该堆栈的顶部,您将在 Debug 透视图中看到源代码。
  13. 单步遍历执行您的 Servlet 代码。您将看到,我们将变量 nextPage 的值手工设置为 AddResultX 。我们应使用 getInitParameters() 方法取代它。
  14. 将代码中的如下一行注释掉: nextPage = "AddResultx";
  15. 取消对下面这一行(这一行包含正确的代码)的注释: //nextPage =getInitParameter(request.getParameter("command"));
  16. 保存 Servlet。

      前面已经提到过,WebSphere Application Server 4.0 能够自动重新装入 Servlet 和 JSP,所以,您不必在每次更改 Servlet 或 JSP 时都重新启动服务器。

  17. 考虑到实际操作问题,由于我们将不再需要 Servlet 中的断点,如果您将它除去/禁用,事情将变得更加容易。
  18. 将输入屏重新装入到 Web 浏览器。输入一些值并单击 Submit。
  19. 这次您应得到正确的 JSP 页面,但打印出来的值是 null值。

下一步是调试 JSP,看看我们是否有可能进一步修正问题。

调试 JSP

   1. 在您的 Web 透视图或任何其它透视图中,浏览到 AdderResults.jsp 文件并打开它。
   2. 在 source 窗格中单击,观察这个 JSP 的源代码。
   3. 请注意,有 Java 调用的第一行在第 48 行。它的样子象这样: String st1 = newjava.lang.String(request.getParameter("str21"));
   4. 在此行的下一行单击鼠标右键并选择 Add Breakpoint。
   5. 将 AdderInputForm.html 重新装入到 Web 浏览器。
   6. 在输入表单的两个域中输入任意两个字符串并单击 Submit。
   7. 回到 debug 透视图(如前一部分所述)。
   8. 单步跳过(step over)开头两个语句,验证变量 str1 和 str2 是否保存了您输入到 HTML 表单的值。
   9. 然后,在第 50 行单击 Step-into( Step into 按钮)按钮。这将把您带到 AdderView bean 的代码中。
  10. 一旦您处在了 AdderView 源代码中,您将意识到我们正在调用错误的方法。我们本应该调用 AdderView.strCat() 方法,而不是 AdderView.badStrCat() 。
  11. 所以,现在您将需要回到您的 JSP 文件,编辑第 50 行并将它修改为: String method0 =AdderBean.StrCat(st1 , st2 );
  12. 保存 JSP。切勿除去断点(我们将需要它来演示客户机调试和 EJB)。
  13. 重新装入您的输入表单。在两个域中输入两个不同的值。例如:“Hello”和“World”,单击 submit。
  14. 现在,您将注意到 null已经消失,但我们将得到第一个字符串与它自身连接在一起形成的字符串。

要修正这一错误,我们将需要再次调试对 EJB 的 JSP 调用。

EJB 的调试

我们使用 EJB 访问 bean 来访问负责完成字符串连接的会话 bean。试图单步跳入(step into)对 EJB 的调用将使我们陷入一片混乱的存根和服务器所生成的代码。在象这样的情况下,在可能发生问题的调用中的 EJB 上设置断点是常见的做法。在我们的例子中是 AdderSessionBean.StrCat() 。

   1. 在 Java 或 J2EE 透视图中,从 AdderEJB 工程打开 poc.debug.ejbs.AdderSessionBean.java 。
   2. 在 StrCat 方法的第一个执行行添加一个断点。
   3. 重新装入您的输入表单。在两个域中输入两个不同的值(即“Hello”和“World”)并单击 Submit。
   4. 您将首先命中 JSP 中的断点。单步跳过前两行,然后单步跳入行号 50。
   5. 在 AdderView.StrCat 方法中,单步跳过这个样子的行: ret = bean.StrCat(str1,str2);

      请注意,在这个案例中,在应用程序服务器(App Server)空间中运行的 AdderView bean 实际就是我们的 EJB 的客户机,不过,在这个特定的案例中,它们共享同一个 JVM。所以,如果您在 Process 视图查看执行堆栈内部,您将注意到它们是在同一个进程上运行。另一个客户机(在 EJBclient.zip 中)可以用作独立 Java 应用程序,用来测试您的 EJB。当您把这个客户机添加到任何 Java 工程中时,请确保您把下列内容添加到了工程的构建路径。

   6.
          * j2ee.jar *
          * ijvejb35.jar *
          * AdderEJB 工程

      (*)这些文件可在 \plugins\com.ibm.etools.websphere.runtime\lib 目录找到。

      当您调试这个应用程序时,您将注意到两个重要事实:
          * 存在两个独立的进程。一个用于应用程序,一个用于 EJB 服务器。
          * 在您的代码的执行过程中,WebSphere Studio Application Developer 调试器有从一个 JVM 到另一个 JVM 来回切换的强大能力。
   7. 单击 Step-over( Step-over 按钮)按钮,您会注意到调试器将在 EJB StrCat 方法内的断点处停止。
   8. 单步遍历执行 EJB,您将认识到错误。我们只是把 str1 连接了两次,根本没使用 str2 。
   9. 修正这个问题并保存代码。
  10. 您将需要重新启动服务器以刷新 EJB 代码。别忘了要在调试模式中启动它。与 Servlet 和 JSP 的情况不同,当您修改了您的 EJB 中的代码时,WebSphere 4.0 将要求重新装入服务器。
  11. 重新装入您的输入表单,输入数据,跟踪您的代码到 EJB 语句。
  12. 验证 sf 变量是否确实带有正确的值。请注意,如果您从 EJB 单击 Return( Debug return 按钮)按钮,则您将运行回到服务器生成的 EJB 类。为了避免发生这样的事情,在堆栈中选择 JSP 调用就行了,如下面的图 7 所示。然后,您可以使用 Step-over( Step-over 按钮)按钮并继续执行 JSP 文件。
  13.

      图 7. 选择了 JSP 的 Debug 进程视图

      选择了 JSP 的 Debug 进程视图
  14. 验证返回字符串是否带有正确的值(您输入的字符串的连接)。

现在,您成功地完成了存在问题的 Servlet、JSP 和 EJB 代码的调试。

结束语

到目前为止,我们在这篇实际操作的文章中所做的是,向您展示在不同的情形下如何使用 WebSphere Studio Application Developer 开发环境调试 Java 应用程序、Servlet、JSP 和 EJB。在下一篇文章中,我们将向您展示如何使用 WebSphere Studio Application Developer 调试器调试在 WebSphere AE 的远程实例中运行的应用程序。
Global site tag (gtag.js) - Google Analytics