介绍
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 应用程序
在调试器中启动您的应用程序
- 切换到(或打开)一个 Java 透视图。
- 创建一个新的 Java 工程并将之称为 TestDebug。
- 将样本 Java 应用程序
testdebug.jar
文件导入到 TestDebug 工程。 - 请检查
poc.debug.app.AppDebug.java
。它是一个简单的应用程序,我们将用它来演示调试器的基础知识。 - 插入一个断点到 main 方法中的循环内的以下语句:
x = y + z;
要这样做,您可以双击源代码的左窗格,或使用弹出菜单,如下面的图 1 所示。 - 在工具栏中,单击 Debug( )按钮。您将看到一个对话框,询问您想使用哪一个启动程序。选择 Java Application,选中 Set as default launcher...复选框,然后单击 Next。
运行应用程序的另一个按钮是 Run( )按钮。这个按钮在非调试 Java JVM 中运行应用程序,这种 JVM 的执行速度更快,但不允许调试或使用断点。这是 WebSphere Studio ApplicationDeveloper 和 VisualAge for Java 之间的根本不同之处,VisualAge for Java 在它自己的 JVM 中运行所有应用程序,并且总是在调试模式中。而 WebSphere Studio Application Developer 则使用可插式 JVM,并且您可以选择是否要在调试模式中运行。 - 选择您想测试的类。WebSphere Studio Application Developer 给您一个选项,让您选择要用应用程序启动程序(Application Launcher)启动的、在同一个工程中的一组类。
- 这个启动程序将启动另一个 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 视图
Breakpoint/Inspector/Variables/Inspector 视图
这个视图的缺省窗格是 Breakpoints 视图,您将在其中看到程序中可用断点的列表。您也可以在一个断点上单击鼠标右键并从弹出菜单中选择 HitCount,它告诉调试器在一定数量的命中后停止。如果你想让循环停止于某次迭代,在这样的循环内设置断点,这很有用。
把您的断点的 HitCount设置为 2。
如果您在 Variable 窗格上单击,那么您将有机会看见可用的变量以及它们的值。在任何变量上单击鼠标右键,您都将得到以下选项:
- Inspect-- variables 视图可能包含许多变量。inspector 视图允许您集中在感兴趣的少量变量上。
- Change Value-- 这是一个非常重要的功能。当您选择这个选项时,您将可以改变所选定的变量的值,并可以研究这一改变对程序执行的影响。
- Show Type Names-- 这个选项显示变量的类型。
- Show Qualified Names-- 这个选项允许您看到变量类型的全限定名。
单击 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
显示结果。
- 创建 WebSphere 4.0 测试实例/配置(Test Instance/Configuration)并命名为 TU(测试单元(Test Unit))。
- 在 TU 的 Configuration 中,单击鼠标右键并将 TestEAREAR 添加到配置中。
- 从 Servers 视图选择 TU服务器并单击 Run( )按钮。
- 在您的 Web 浏览器中,输入: http://localhost:8080/Adder/
- 这应自动装入
AdderInputForm.html
,因为它被配置为一个欢迎页面。 - 在输入表单中,输入任意两个字符串,单击 Submit并注意结果。
- 您应得到 404 error file not found AddResultX。
停止服务器,让我们找出如何使用这个调试器来定位这个问题。
- 在 Java 或 Web 透视图中,打开
AdderWeb
工程并定位到AdderController.performTask()
方法。 - 在
try
块的第一行:performServices(request, response);
,设置一个断点。 - 现在再次启动服务器,但这次请单击 Debug( )按钮,这样服务器将以调试模式启动,并启用了断点。
- 将
AdderInputForm.html
重新装入到 Web 浏览器。 - 在输入表单的两个域中输入任意两个字符串并单击 Submit。
- 您会注意到 Server 透视图变成活动的了,您将可以在其中进行调试。
在 server 透视图中,您将注意到的第一件事是,Debug、Console 和 Variables 窗格共享同一个窗口!由于在您单步遍历执行(step through)代码的过程中,每当需要检查变量值时都要切换窗口,所以这可能不太方便。这个问题的解决办法是,或者自己重新安排这些 server 视图,或者在 Debug 视图中进行调试,Debug 视图更适合于这个过程。在 Debugger 透视图中进行调试有两种方式。第一种容易的方式是在命中代码中的断点之前手工切换到 debugger 透视图。这并非总是容易的。比如说,您在HttpServlet.init()
方法(被设置为在启动时自动装入)中设置了一个断点。所以,现在我们将向您展示如何在 Debug 透视图中调试服务器,即使您在该服务器或任何其它透视图中获取了断点。 - 切换到 Debug 透视图
- 在 Debug 视图中,首先定位到 Server 进程,如下面的图 5 所示。
- 在运行在 server 之下的线程的列表中,定位到列表底端附近的线程,也就是紧靠着底端的 Suspended (breakpoint ...,如下面的图 6 所示。如上面的图 5 所示,由于有 +号紧靠着它,定位这个线程显然很容易。如果展开这个线程,您将看到执行堆栈。
- 双击该堆栈的顶部,您将在 Debug 透视图中看到源代码。
- 单步遍历执行您的 Servlet 代码。您将看到,我们将变量
nextPage
的值手工设置为AddResultX
。我们应使用getInitParameters()
方法取代它。 - 将代码中的如下一行注释掉:
nextPage = "AddResultx";
- 取消对下面这一行(这一行包含正确的代码)的注释:
//nextPage =getInitParameter(request.getParameter("command"));
- 保存 Servlet。
前面已经提到过,WebSphere Application Server 4.0 能够自动重新装入 Servlet 和 JSP,所以,您不必在每次更改 Servlet 或 JSP 时都重新启动服务器。 - 考虑到实际操作问题,由于我们将不再需要 Servlet 中的断点,如果您将它除去/禁用,事情将变得更加容易。
- 将输入屏重新装入到 Web 浏览器。输入一些值并单击 Submit。
- 这次您应得到正确的 JSP 页面,但打印出来的值是 null值。
下一步是调试 JSP,看看我们是否有可能进一步修正问题。
- 在您的 Web 透视图或任何其它透视图中,浏览到
AdderResults.jsp
文件并打开它。 - 在 source 窗格中单击,观察这个 JSP 的源代码。
- 请注意,有 Java 调用的第一行在第 48 行。它的样子象这样:
String st1 = newjava.lang.String(request.getParameter("str21"));
- 在此行的下一行单击鼠标右键并选择 Add Breakpoint。
- 将
AdderInputForm.html
重新装入到 Web 浏览器。 - 在输入表单的两个域中输入任意两个字符串并单击 Submit。
- 回到 debug 透视图(如前一部分所述)。
- 单步跳过(step over)开头两个语句,验证变量
str1
和str2
是否保存了您输入到 HTML 表单的值。 - 然后,在第 50 行单击 Step-into( )按钮。这将把您带到
AdderView
bean 的代码中。 - 一旦您处在了
AdderView
源代码中,您将意识到我们正在调用错误的方法。我们本应该调用AdderView.strCat()
方法,而不是AdderView.badStrCat()
。 - 所以,现在您将需要回到您的 JSP 文件,编辑第 50 行并将它修改为:
String method0 =AdderBean.StrCat(st1 , st2 );
- 保存 JSP。切勿除去断点(我们将需要它来演示客户机调试和 EJB)。
- 重新装入您的输入表单。在两个域中输入两个不同的值。例如:“Hello”和“World”,单击 submit。
- 现在,您将注意到 null已经消失,但我们将得到第一个字符串与它自身连接在一起形成的字符串。
要修正这一错误,我们将需要再次调试对 EJB 的 JSP 调用。
EJB 的调试
我们使用 EJB 访问 bean 来访问负责完成字符串连接的会话 bean。试图单步跳入(step into)对 EJB 的调用将使我们陷入一片混乱的存根和服务器所生成的代码。在象这样的情况下,在可能发生问题的调用中的 EJB 上设置断点是常见的做法。在我们的例子中是 AdderSessionBean.StrCat()
。
- 在 Java 或 J2EE 透视图中,从
AdderEJB
工程打开poc.debug.ejbs.AdderSessionBean.java
。 - 在
StrCat
方法的第一个执行行添加一个断点。 - 重新装入您的输入表单。在两个域中输入两个不同的值(即“Hello”和“World”)并单击 Submit。
- 您将首先命中 JSP 中的断点。单步跳过前两行,然后单步跳入行号 50。
- 在
AdderView.StrCat
方法中,单步跳过这个样子的行:ret = bean.StrCat(str1,str2);
请注意,在这个案例中,在应用程序服务器(App Server)空间中运行的AdderView
bean 实际就是我们的 EJB 的客户机,不过,在这个特定的案例中,它们共享同一个 JVM。所以,如果您在 Process 视图查看执行堆栈内部,您将注意到它们是在同一个进程上运行。另一个客户机(在EJBclient.zip
中)可以用作独立 Java 应用程序,用来测试您的 EJB。当您把这个客户机添加到任何 Java 工程中时,请确保您把下列内容添加到了工程的构建路径。 -
- j2ee.jar *
- ijvejb35.jar *
AdderEJB
工程
(*)这些文件可在
<WASROOT>/plugins/com.ibm.etools.websphere.runtime/lib
目录找到。当您调试这个应用程序时,您将注意到两个重要事实:
- 存在两个独立的进程。一个用于应用程序,一个用于 EJB 服务器。
- 在您的代码的执行过程中,WebSphere Studio Application Developer 调试器有从一个 JVM 到另一个 JVM 来回切换的强大能力。
- 单击 Step-over( )按钮,您会注意到调试器将在 EJB
StrCat
方法内的断点处停止。 - 单步遍历执行 EJB,您将认识到错误。我们只是把
str1
连接了两次,根本没使用str2
。 - 修正这个问题并保存代码。
- 您将需要重新启动服务器以刷新 EJB 代码。别忘了要在调试模式中启动它。与 Servlet 和 JSP 的情况不同,当您修改了您的 EJB 中的代码时,WebSphere 4.0 将要求重新装入服务器。
- 重新装入您的输入表单,输入数据,跟踪您的代码到 EJB 语句。
- 验证
sf
变量是否确实带有正确的值。请注意,如果您从 EJB 单击 Return( )按钮,则您将运行回到服务器生成的 EJB 类。为了避免发生这样的事情,在堆栈中选择 JSP 调用就行了,如下面的图 7 所示。然后,您可以使用 Step-over( )按钮并继续执行 JSP 文件。 - 验证返回字符串是否带有正确的值(您输入的字符串的连接)。
现在,您成功地完成了存在问题的 Servlet、JSP 和 EJB 代码的调试。
结束语
到目前为止,我们在这篇实际操作的文章中所做的是,向您展示在不同的情形下如何使用 WebSphere Studio Application Developer 开发环境调试 Java 应用程序、Servlet、JSP 和 EJB。在下一篇文章中,我们将向您展示如何使用 WebSphere Studio Application Developer 调试器调试在 WebSphere AE 的远程实例中运行的应用程序。
Name | Size | Download method | |||||||||
DebugInWSADpt1.zip | 60 KB | HTTP | |||||||||