• Save
Part 6 debugging and testing java applications
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
4,517
On Slideshare
4,517
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
0
Comments
0
Likes
2

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Rational Application Development certification prep, Part 6: Debugging and testing Java applications Skill Level: Intermediate Matthew Stobo (mstobo@us.ibm.com) IBM Senior IT Specialist IBM 11 Apr 2006 In this sixth in a series of seven tutorials created to help you prepare for the IBM Certification Test 255, Developing with IBM Rational Application Developer for WebSphere Software V6, learn how to debug and test components of a J2EE application using the Integrated Test Environment of Rational Application Developer and its built-in support for JUnit. Using breakpoints and other features of the Debug Perspective, step through Java code to find possible code breakers. Finish by mastering the art of creating JUnit TestCases and TestSuites and running them inside the development environment. Section 1. Before you start About this series Rational® Application Developer for WebSphere® Software is the IBM Software Development Platform that allows you to quickly design, develop, analyze, test, profile and deploy Web, Web services, Java™, J2EE, and portal applications. This series of seven tutorials helps you prepare to take the IBM certification Test 255, Developing with IBM Rational Application Developer for WebSphere Software V6 to become an IBM Certified Associate Developer. This certification targets entry level developers and is intended for new adopters of IBM Rational Web Developer or IBM Rational Application Developer for WebSphere Software V6.0, specifically professionals and students entering into Web development using IBM products. About this tutorial Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 1 of 62
  • 2. developerWorks® ibm.com/developerWorks This tutorial is the sixth in the series designed to help you prepare for the IBM Certification Test 255: Developing with IBM Rational Application Developer for WebSphere Software V6. It focuses on debugging and testing components of a J2EE application using the Integrated Test Environment of Rational Application Developer and its built-in support for JUnit. It will ensure you understand how to set and manage breakpoints to allow you to step through and examine your code using the integrated debugger. You will also learn of a few other testing features such as the Scrapbook, which allows you to test snippets of code without needing a full class structure around them, and the built-in support for JUnit, which provides wizards for creating TestCases and TestSuites for unit testing. After you complete this tutorial, continue with the seventh and final tutorial in the series. Objectives By the end of this tutorial, you should have a good understanding of how to: • Manage breakpoints • Step through and examine Java code • View variables and execute, display, and inspect expressions • Create and run code in Scrapbook page • Perform JSP page debugging • Use step-by-step debugging • Locate and view WebSphere application server logs • Perform unit testing using JUnit Prerequisites The tutorial assumes that you have followed the certification series tutorial track and are already somewhat familiar with the development environment. If you are unfamiliar with the environment, or J2EE applications, review all the preceding tutorials before attempting this tutorial. System requirements To run the examples in this tutorial, install Rational Application Developer for WebSphere Software or Rational Web Developer for WebSphere Software. You can download a free trial version of Rational Application Developer for WebSphere Software if you don't already have a copy of it. The hardware and software requirements for this software can be located at IBM Rational Application Developer System Requirements. Debugging and testing Java applications Page 2 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 3. ibm.com/developerWorks developerWorks® Key concepts While you develop a simple J2EE application in this tutorial, doing so is not its focus. This tutorial assumes that you are already familiar with the development environment of Rational Application Developer, hereafter Application Developer. This tutorial focuses on debugging and testing components of a J2EE application using the Integrated Test Environment and Application Developer's built-in support for JUnit. Section 2. Creating the application If you want to go through the steps of creating the application, complete all the sections within the tutorial. To just work with the debugger, download the completed application and import it into Application Developer. Launch a new workspace to the directory C:tutorialsdebugging: Figure 1. Workspace Launcher Close the Welcome view by clicking on the X in the top right-hand corner of the view. You are presented with the J2EE Perspective. If you are not automatically switched here, do so now. Before you can use the debugger, you need an application to debug. Because the focus of this tutorial is on the debugger itself, and not on coding, the design of the Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 3 of 62
  • 4. developerWorks® ibm.com/developerWorks application is kept as simple as possible, so you don't lose sight of the goal. The application that you are building is called NameSorter. It is a very simple application that takes a name as input from an HTML form and adds it to a Java collection. It is the job of the application to first make sure that the name is converted to uppercase and then sort the results in their natural order by name. To simplify the setup for the application, do not use a database. Instead, store the names in a Java collection, namely a SortedSet. This decision means that the results are not persistent between server restarts. If you want to make your information persist, feel free to implement a database solution. Start by building a J2EE application; call it, NameSorter. It is to contain a Web project called SorterWeb. There are many different ways to create an enterprise application in Application Developer; choose the one you find most convenient. If you are unsure how to create a project, here is one approach: 1. Select File > New > Enterprise Application Project. 2. Enter NameSorter as the name for the project. Click Show Advanced to see extra details of your project. Your screen should look like the following image: Figure 2. New Enterprise Application wizard 3. Click Next to advance to the next screen of the wizard. 4. On this screen, create a new Web project by clicking New Module... Figure 3. EAR Module Project screen Debugging and testing Java applications Page 4 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 5. ibm.com/developerWorks developerWorks® 5. When the next screen opens, uncheck all of the project creation options except the one to create a Web project. Name the Web project SorterWeb. Figure 4. New Module Project screen Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 5 of 62
  • 6. developerWorks® ibm.com/developerWorks 6. Click Finish to create the project. Click Finish again on the next screen to let the wizard finish its tasks for creating an Enterprise Application. You should now have an Enterprise Application named NameSorter that contains a Web module named SorterWeb. Figure 5. Project Explorer view Debugging and testing Java applications Page 6 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 7. ibm.com/developerWorks developerWorks® Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 7 of 62
  • 8. developerWorks® ibm.com/developerWorks Now that you have a Web module, create a servlet to act as the controller for your application. Call the Servlet NameController. Again, choose your favorite method to create the Servlet. If you are not familiar with how to do this, here is one approach: 1. Open a context menu on the SorterWeb project and choose New > Other > Web > Servlet. 2. Enter NameController as the name for the servlet and click Next. Figure 6. Create Servlet wizard 3. On the screen that follows enter com.debug.tutorial.servlet as the package name. Accept the defaults for the rest of the items in the wizard. It should look like the screen below. Be sure that javax.servlet.http.HttpServlet is in the Superclass field. 4. Click Finish. Debugging and testing Java applications Page 8 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 9. ibm.com/developerWorks developerWorks® Figure 7. Servlet details 5. You should now be able to locate the source file for NameController in the JavaSource directory under SorterWeb > Java Resources > JavaSource as pictured below. Figure 8. SorterWeb project in Project Explorer view Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 9 of 62
  • 10. developerWorks® ibm.com/developerWorks Debugging and testing Java applications Page 10 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 11. ibm.com/developerWorks developerWorks® 6. Double-click on NameController.java to open a Java editor. Add a call to processRequest(arg0, arg1) to both the doGet and doPost methods. Use the Quick Fix editor (click on the light bulb) to create this new processRequest method. Figure 9. NameController editor 7. Enter the following code into the processRequest method: String name = req.getParameter("name"); NameHandler handler = new NameHandler(name); getServletConfig().getServletContext(). getRequestDispatcher("/WEB-INF/NameList.jsp").forward(req,resp); 8. You get an error stating that the NameHandler class cannot be resolved or is not a type. Use Quick Fix, as before, to help you resolve the error. Click on the light bulb and choose Create class 'NameHandler' or use the wizards to create the Java class, instead. This approach was chosen for convenience. Figure 10. Quick Fix editor Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 11 of 62
  • 12. developerWorks® ibm.com/developerWorks 9. When the Java class wizard opens, complete the fields as follows: • Package: com.debug.tutorial.helper • Interfaces: java.io.Serializable • Check the options for Constructors from superclass and Inherited abstract methods Figure 11. New Java Class wizard Debugging and testing Java applications Page 12 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 13. ibm.com/developerWorks developerWorks® 10. Click Finish. 11. After the wizard has completed, you find yourself in a Java editor for the NameHandler.java class. Code this class now. Either code the class on your own or enter the code from the following listing: package com.debug.tutorial.helper; import java.io.Serializable; import java.util.Iterator; import java.util.SortedSet; import java.util.TreeSet; public class NameHandler implements Serializable { public static final SortedSet nameSet = new TreeSet(); private NameHandler() { super() } public static void processName(String name){ String capitalizedName = nameCapitalizer(name); Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 13 of 62
  • 14. developerWorks® ibm.com/developerWorks nameSet.add(name); } private static String nameCapitalizer(String name) { return name.toUpperCase(); } } 12. Make sure that you add the appropriate import statements to resolve any errors. 13. Return to the NameController.java file to finish coding your processRequest method. 14. The final code should look like this: String name = req.getParameter("name"); NameHandler.processName(name); getServletConfig().getServletContext(). getRequestDispatcher("/WEB-INF/NameList.jsp").forward(req,resp); You have yet to code the NameList.jsp. You can do that in just a moment. You actually need two forms: one to input names and the other to display the names in a list. The first form is very simple with one field. It is used to input information. It does not need to be a JSP page. Code it as HTML. Figure 12. Web Content directory Debugging and testing Java applications Page 14 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 15. ibm.com/developerWorks developerWorks® Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 15 of 62
  • 16. developerWorks® ibm.com/developerWorks 1. Open a context menu on the WebContent directory in the SorterWeb module. From the menu choose New > HTML/XHTML file. When the HTML wizard opens, enter Index.html for the name of the file. 2. Click Finish to create the page. 3. Change to the Web perspective to create the rest of this page. 4. Replace the existing text on the page with Please type in a name:. 5. Insert an HTML form below the text. 6. In the properties view, set the Action and Method to be /SorterWeb/NameController and Post, respectively. To set the Action field, click the browse button and choose Servlet. Your Servlet should appear in a list. Choose it. Figure 13. Properties view 7. Insert a table into the form by using either the palette or the Insert menu. The dimensions for your table should be 2x2 with a border width of 0, as shown in the image below: Figure 14. Insert table wizard Debugging and testing Java applications Page 16 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 17. ibm.com/developerWorks developerWorks® 8. In the first cell of the table type the value: Name. In the second cell of the first row enter a text field. Name the text field to match the parameter that is read in by the Servlet. Figure 15. Insert text field wizard Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 17 of 62
  • 18. developerWorks® ibm.com/developerWorks 9. In the second row add two buttons. The first cell should have a Submit button. Use Submit for the name and caption, as well. To the second cell, add a Reset button with Clear for the caption. You can find these buttons on the palette under Form Tags. 10. Save the page. To complete the application you have to create the JSP page to display the names. For now, just create the page to complete the application flow and fix any broken links that you may have. Code the rest of this page later in this tutorial. 1. Open a context menu on the WEB-INF directory contained in SorterWeb > Web content. Figure 16. WEB-INF directory Debugging and testing Java applications Page 18 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 19. ibm.com/developerWorks developerWorks® Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 19 of 62
  • 20. developerWorks® ibm.com/developerWorks 2. Choose New > Other > JSP file to open the New JSP file wizard. 3. Enter NameList.jsp for the name. Click Finish. For now you are finished with this page. You complete it later on. Section 3. Testing the code Now it's time to test out some of your code. Before you do, make sure that all of your code is saved and that you have no errors in the Problems view. Ignore warnings about imports not being used. First test out the code. To test if the application works: 1. Open a context menu on Input.html and choose Run > Run on Server... 2. Choose to manually define a server type of WebSphere v6.0 Server. Set it as your project default by checking the check box. Click Finish. Figure 17. Server selection page Debugging and testing Java applications Page 20 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 21. ibm.com/developerWorks developerWorks® 3. The Input.html file should open. Enter a name into the text field to test the flow of the application. You should end up on the NameList.jsp. Remember that you are not expecting the names to show up at this time, as you have yet to code that portion of the application. You are just testing the flow for now. Now try testing the flow using the debugger. 4. The test environment has two modes of operation -- normal runtime mode and debug mode. To debug on the server it must be running in debug mode. Stop the server if it is still running. 5. Set a breakpoint in your code. Open NameController.java (the Servlet) and set a breakpoint in the doPost method. To set a breakpoint, double-click on the gray margin next to the executable line of code on which you want the JVM to suspend. While the breakpoint is enabled, thread execution suspends before that line of code is executed. The debugger selects the thread that has suspended and displays the stack Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 21 of 62
  • 22. developerWorks® ibm.com/developerWorks frames on that thread's stack. The line where the breakpoint was set is highlighted in the editor in the Debug perspective. Another way to set a breakpoint is to open a context menu on the margin and select toggle breakpoint. A breakpoint is represented by a blue ball. Set a breakpoint on the second executable line of the processRequest method, as well. It is important to note that you cannot set a breakpoint on a method signature. Figure 18. Setting a breakpoint 6. Go to the servers view and select your server. Click on the scarab (bug) icon to start the server in Debug mode. Alternatively, open a context menu and select Debug. Figure 19. Servers view 7. Return to Index.html and select Debug on Server from the context menu. 8. If you get a confirmation screen asking you if you want to switch Debugging and testing Java applications Page 22 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 23. ibm.com/developerWorks developerWorks® perspectives, choose Yes. Figure 20. Confirm perspective switch screen 9. When you are switched to the Debug perspective, take a moment to look at the Debug view. In it there is a list of all of the currently running threads on the server. Look for the suspended thread. You can recognize the suspended thread by the yellow pause icon...all the other threads have a green arrow beside them indicating that they are running. If there is a + (plus) sign beside the suspended thread, it indicates that the call stack is currently collapsed (not visible). To see the call stack, click on the + sign. It should now look similar to the screen below. The blue icons represent calls to various methods of various objects running on the server. The method at the very top of the call stack is where the thread is currently suspended. In your case you are suspended in the doPost method of the NameController class. Notice that it even specifies the line number. Figure 21. Debug View 10. While still in the Debug perspective, also take a look at the Breakpoints view. You see the two breakpoints that you set earlier listed in this view. Open a context menu on the breakpoint for the processRequest method, the top method in the image below. When the menu opens select Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 23 of 62
  • 24. developerWorks® ibm.com/developerWorks ...Go to file. Notice that it takes you right to the spot in the source code where you placed the breakpoint. Figure 22. Breakpoints view 11. Once again, open a context menu on the processRequest breakpoint. This time select ...Properties from the context menu. In the properties dialog, you have the ability to set conditional breakpoints. Conditional breakpoints can be used when you notice that you have a bug in your code when only certain values are entered. It provides the opportunity to step through your code when those conditions are true. Try setting one now. Check the Enable Condition check box and enter the following condition: name.length()==0. Figure 23. Properties editor Debugging and testing Java applications Page 24 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 25. ibm.com/developerWorks developerWorks® 12. Click OK to exit the window. 13. Above the Debug view, click the resume button (green arrow). It causes the suspended thread to resume its execution. You may have to click it twice depending on which breakpoint you were suspended on. Look in the Debug view to make sure that there are no suspended threads. Disable the breakpoint in the doPost method by unchecking the box next to it in the Breakpoints view. 14. Now return to a browser view and refresh the Index.html page. First enter any name in the name text field and then click the submit button. Remember, the condition was that you only stopped at the breakpoint if the name value was of zero length. No thread should be suspended upon executing this program. Try the exact same thing, except this time do not place a value in the text field and click submit. The program should suspend on the conditional breakpoint. Take a moment to examine the variable by looking at it in the Variables view. You see that it is, indeed, an empty string. Figure 24. Variables view Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 25 of 62
  • 26. developerWorks® ibm.com/developerWorks Let's take a moment to review some of the things that you have learned, so far. You have learned that the server has two modes of operation: normal and debug. You have learned how to set a breakpoint and run the server in debug mode to suspend a thread. You have also seen how to manage breakpoints by toggling on, disabling, and setting a conditional breakpoint. You have also used much of the Debug Perspective, in particular the Debug view to explore the stack trace, and the Breakpoints view to manage breakpoints. Let's spend a little more time in the Debug perspective to learn how to step through code. Section 4. Stepping through code Now it's time to learn how to step through and examine code. 1. If you currently have a thread suspended in the debugger, resume it (green arrow). Look at the source code for NameController. You find the two breakpoints that you set earlier. Remember that a regular breakpoint is represented with a blue ball. What did you do to get these other icons? You probably guessed correctly that the blue ball with a question mark represents a conditional breakpoint and the white breakpoint represents a disabled breakpoint. Open a context menu on the conditional breakpoint and go to Breakpoint Properties.. to remove the condition. 2. In the properties view remove the condition. 3. Open a context menu on the disabled breakpoint in the doPost method Debugging and testing Java applications Page 26 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 27. ibm.com/developerWorks developerWorks® and choose Enable Breakpoint. Both breakpoints should now be regular blue ones again. Figure 25. Breakpoints in Java editor 4. Return to a browser view and return to Index.html. Enter the name Sam Smith for your example here and click OK. Assuming that you left your server running in debug mode, you are once again suspended at the breakpoint in the doPost method. 5. Now try stepping through some code. Above the Debug view there is a series of icons on a tool bar. These icons are used to step through your program. Figure 26. Step tool bar Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 27 of 62
  • 28. developerWorks® ibm.com/developerWorks 6. Click the Step Into button in the Debug view tool bar, or press F5. The next expression on the currently selected line to be executed is invoked, and execution suspends at the next executable line in the method that is invoked. You should now be suspended on the first line of the processRequest method. Remember that you are suspended before the execution of this line. 7. Click the Step Over button in the Debug view toolbar, or press F6. The currently selected line is executed and suspends on the next executable line. Look in the Variables view and notice that the name variable is now in scope and has been assigned the value Sam Smith for the request parameter. Figure 27. Variables view 8. In the Java editor, within the current line of execution, place the cursor on the name of a method that you would like to step into. In this case, there is only one choice. 9. Click Step into Selection in the Java editor context menu, or press Debugging and testing Java applications Page 28 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 29. ibm.com/developerWorks developerWorks® Ctrl-F5. Execution resumes until the selected method is invoked. You should now find yourself inside the processName method of the NameHandler class. 10. Let's take this opportunity to explore another important function of the Debugger called the Display function. Use your mouse to highlight the first line of code within the processName method. 11. With this line highlighted, open a context menu and select Display from the menu. A new window opens to display what the results of this method would be if you executed it. In this case, it shows the name you entered in uppercase. Figure 28. Display results 12. You can do the same thing by opening a Display view. Try this! If you do not currently have a Display view open, open one by using the Window menu (Window > Show View > Display) to open the view. 13. Within the Display view type the following code: return NameHandler.nameCapitalizer("Matt"); 14. Highlight the line of code and click the Display Result button (it looks like a Notepad with a "J" on it). The results display within the window. Figure 29. Display view 15. An alternative to using the Display view is to use the Expressions view. If Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 29 of 62
  • 30. developerWorks® ibm.com/developerWorks the expressions view is not open, open one using the same method you used to open the Display view. In the Expression view, open a context menu and select ...Add Watch Expression. 16. Enter the following code into the window as the expression that you are watching: String capitalizedName = nameCapitalizer(name) Figure 30. Add watch expression window 17. Click OK. In the Expressions view you see the object returned from the expression and its value. Explore the object by expanding the String value for capitalizedName. You find an array of characters holding the values for the String. Another way to do this is to highlight the line of code in the Java editor and select Inspect from the context menu. Figure 31. Expressions view Debugging and testing Java applications Page 30 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 31. ibm.com/developerWorks developerWorks® 18. Click Step Return in the Debug view tool bar or press F7. Execution resumes until the next return statement in the current method is executed, and execution suspends on the next executable line. 19. Feel free to play with the other step options like Run to line and Step Filters. The last one to look at is the Drop to Frame option. This command lets you drop back and re-enter a specified stack frame. This feature is similar to running backwards and restarting your program part way through. To drop back and re-enter a specified stack frame, select the stack frame that you want to drop to, and select Drop to Frame. Some caveats apply to this feature: • You cannot drop past a native method on the stack. • Global data are unaffected and retain their current values. For example, a static vector containing elements is not cleared. Note: This command is only enabled if the underlying VM supports this feature. 20. Use Step Into button to step part way through the program. For example, step into the processName method of the NameHandler class. 21. Locate the doPost method in the stack trace of the Debug view. With the doPost method selected, click the Drop to Frame button. The execution of the code now rewinds to doPost method. You have now seen how to step through and examine code using the Step Into, Step Over, and other stepping features. You also had an opportunity to view variables and execute, display, and inspect expressions. Now let's move on to Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 31 of 62
  • 32. developerWorks® ibm.com/developerWorks another testing feature of Application Developer called the Scrapbook! Section 5. Creating and running code in a Scrapbook page The JDT contributes a scrapbook facility that can be used to experiment with and evaluate Java code snippets before building a complete Java program. Edit and evaluate Snippets in the Scrapbook page editor. It then reports resultant problems in the editor. From a Java scrapbook editor, select a code snippet, evaluate it, and display the result as a String. You can also show the results from evaluating code snippets in the debugger's expressions view. The first time you evaluate an expression in a scrapbook page, a VM is launched. It is important to note that a VM is launched for each scrapbook page in which you are evaluating expressions. The VM for a page remains active until you close the page, explicitly terminate it (in the debugger or using the Stop the Evaluation button in the editor toolbar), or when you code a System.exit() in a page and evaluate it. Let's try creating a Scrapbook page. 1. First create a new Folder: Select File > New > Folder. 2. Select SorterWeb/JavaSource as the parent folder and enter Scrapbooks for the Folder Name. Figure 32. New folder wizard Debugging and testing Java applications Page 32 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 33. ibm.com/developerWorks developerWorks® 3. Click Finish. 4. Now it is time to create your first scrapbook page. From the menus select File > New > Other. 5. Select Java > Java Run/Debug > Scrapbook Page. 6. Click Next. 7. On the Create Java Scrapbook Page screen of the wizard, select the Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 33 of 62
  • 34. developerWorks® ibm.com/developerWorks newly created Scrapbooks project. Enter SorterScrapbook as the file name. Figure 33. New scrapbook page wizard 8. Click Finish. 9. In the Scrapbooks folder, you now find your newly created scrapbook page; notice that it has a .jpage extension. The tool should have opened an editor for you on this page. If it did not, open one by double-clicking the file. Again, the intent of the scrapbook is to allow you to test and run code without having to build a full class structure around it. Try a simple experiment first and enter the following code in the editor: System.out.println("Hello Debugging and testing Java applications Page 34 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 35. ibm.com/developerWorks developerWorks® World)"; 10. Select the entire line that you just entered and open a context menu on it. In the context menu, select display... The tool then starts a JVM for you to execute your code. This JVM continues to run until you shut it down. Look in the console for your output. As you did not specify an explicit return value, the tool puts an entry in your file that says No explicit return value specified. Remove this line before executing the scrap again; otherwise, your code will not compile. 11. Let's enter some logic around the code. Put a for loop around your code to have it write out its output 10 times. for(int i = 0; i<10;i++){ System.out.println("Hello World"); } 12. Run the display option again in the context menu. You are not limited to running your code using the classes that are in the rt.jar file of the Java runtime; the scrapbook can also run against classes in your project. 13. Enter the following snippet into the scrapbook. Hint: Use code assist (ctrl + spacebar) to save you some typing on the fully qualified names. com.debug.tutorial.helper.NameHandler.processName("jim"); com.debug.tutorial.helper.NameHandler.processName("sally"); com.debug.tutorial.helper.NameHandler.processName("an ping"); System.out.println(com.debug.tutorial.helper.NameHandler.nameSet); 14. Highlight the code and select Display from the context menu one more time. Your output should look like the following image: Figure 34. Jpage output in console Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 35 of 62
  • 36. developerWorks® ibm.com/developerWorks 15. You have just used the scrapbook to detect a bug in your code. When the items are stored in the nameSet, they should be stored in uppercase. Open an editor on NameHandler.java and make an adjustment to the code. 16. This is the current processName method. Notice that you passed in the name variable instead of the capitalizedName variable. Don't get mad! Yes, we asked you to do this, so we could later point out this feature. Change the highlighted variable, name, which was passed in as an argument to the SortedSet's add() method to capitalizedName. The resulting code is shown below: public static void Debugging and testing Java applications Page 36 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 37. ibm.com/developerWorks developerWorks® processName(String name){ String capitalizedName = nameCapitalizer(name); nameSet.add(name); //change the argument to capitalizedName } 17. Save your changes and test your code in the scrapbook again. Your output should now read as follows: [AN PING, JIM, SALLY] 18. To exit the dedicated JVM for your scrapbook, open a context menu and select Stop Evaluation. By saving and storing these scraps with your project, you can see that the scrapbook is a convenient way to write tests to save and version with your code for execution again later. Section 6. Debugging JSP pages Complete your JSP page to display the results that were generated from your model, the NameHandler class. Take a few moments to edit the NameList.jsp. Remember that you placed it inside the WEB-INF directory to keep users from browsing to it directly. Currently, NameList.jsp is just a place holder to prevent you from getting broken link errors when the Servlet tries to forward on its results. Implement the JSP page and see what features are available to you to debug your JSP implementation. Before you start to write the JSP page, you have to refactor the current implementation of the application. Remember that you are trying to set up a simple Model-View-Controller architecture. The Servlet acts as the controller. The controller processes the initial input and delegates to the model any computations, calculations, or data storage or retrieval. The controller stores the results from the model, on one of the application's shared scopes. The controller then forwards control of the application on to the JSP page to retrieve and format the results for presentation. Currently your model, NameHandler, does the work of changing the name to uppercase and storing the results in a SortedSet. The Servlet and JSP page are unaware of these results at this time, so you have to make a slight change to your current code. 1. Open NameHandler.java for editing. Currently, the code in the Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 37 of 62
  • 38. developerWorks® ibm.com/developerWorks processName method is as follows: public static void processName(String name){ String capitalizedName = nameCapitalizer(name); nameSet.add(capitalizedName); } 2. The method returns void. In order for the Servlet to pass the results on to the JSP page for presentation, the Servlet first needs the results. Change the signature of the processName method to return a java.util.SortedSet. You also have to have the method return the nameSet object that contains the results. public static SortedSet processName(String name){ String capitalizedName = nameCapitalizer(name); nameSet.add(capitalizedName); return nameSet; } 3. Of course, a change to model's interface also means that you have to make a change to the Servlet, as well. Open the Servlet, NameController.java, for editing. The changes you make to this class are in the processRequest method. The current implement of this method is as follows: private void processRequest(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String name = req.getParameter("name"); NameHandler.processName(name); getServletConfig().getServletContext(). getRequestDispatcher("/WEB-INF/NameList.jsp").forward(req,resp); } 4. Make two changes to this method. The first relates to the change that you made on the NameHandler class. The processName method of this class now returns a SortedSet. Create a variable to hold these results. Add a variable called sortedNames of type java.util.SortedSet to hold the results that are returned from the NameHandler class. 5. There is one more change for you to make: pass the results on to the JSP page to be presented to the user. To do this, store the results on the request scope. Add a line of code that stores the SortedSet onto the HttpServletRequest. For the sake of convenience, call the attribute sortedNames, as well. Your new code should look as follows: private void processRequest(HttpServletRequest req, HttpServletResponse resp) Debugging and testing Java applications Page 38 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 39. ibm.com/developerWorks developerWorks® throws ServletException, IOException { String name = req.getParameter("name"); SortedSet sortedNames = NameHandler.processName(name); req.setAttribute("sortedNames", sortedNames); getServletConfig().getServletContext(). getRequestDispatcher("/WEB-INF/NameList.jsp").forward(req,resp); } 6. Remember to add any import statements that are needed to resolve class path problems. Feel free to set a breakpoint and step through the changes you made to the code. 7. Build the JSP page. Close any editors that you currently have open. Open NameList.jsp for editing. It should currently look similar to the following image. Figure 35. NameList.jsp editor 8. Replace the line that reads Place content here with The following names are currently in the list:. 9. At the top of the page, add a useBean tag. From the menus choose JSP > Insert Bean. The Insert JSP Bean window opens. 10. Add the following values: ID: sortedNames Scope: Request Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 39 of 62
  • 40. developerWorks® ibm.com/developerWorks Type: java.util.SortedSet Figure 36. Insert JSP bean dialog 11. Click OK. 12. You have just added a useBean tag to the page. Remember that the bean, in this case a java.util.SortedSet, contains the results that were passed here by the Servlet. Now add a scriplet to the page that iterates through the collection and displays the results. 13. Go the JSP menu and select Insert Scriptlet. 14. Go to the Source code page and edit the source by adding the following code: <%java.util.Iterator names = sortedNames.iterator(); while(names.hasNext()){%> <%= names.next() %><BR> <%}%> 15. Set a breakpoint next to the line where the Iterator is declared. Set breakpoints in a JSP editor the exact same way as you do in a Java editor. The only caveat is that you are only allowed to set breakpoints on JSP tags. You cannot set breakpoints on regular HTML. Figure 37. Breakpoint in NameList.jsp Debugging and testing Java applications Page 40 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 41. ibm.com/developerWorks developerWorks® 16. Test your code. If you have any other breakpoints set at this time, go into the Debug perspective and disable them. Remember to use the Breakpoints view to do this. 17. Run the server in Debug mode. Remember to run Index.html as it is the entry point to your application. As an experiment try and run NameList.jsp directly. What happens? Why? Remember that you placed NameList in the WEB-INF directory. It can only be reached through the RequestDispatcher; therefore, in this case the Servlet has to forward to this page. You cannot browse to it directly. Your thread of execution should now be suspended at your breakpoint in the NameList.jsp. Figure 38. Debug view Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 41 of 62
  • 42. developerWorks® ibm.com/developerWorks 18. Take a moment to explore the Debug perspective to view what is different. Not much! The only real difference is what is shown in the Outline view. It contains the structure of your JSP page, and the editor contains the html source of your JSP page, not the compiled Servlet. (Remember that a JSP page gets compiled into a Servlet. It is not shown here). Take a moment to examine the variables that are in scope in the Variables view. You find references to the various scopes of the Web Container. 19. Now try stepping through the code by using the Step icons as you did before, or the hotkeys (F5, F6, and so forth). After you Step Over the line that creates the Iterator, take a moment to look at its contents in the Variables view. You should find the name that you typed in Input.html. It should be shown in uppercase (In the following picture you can see that you entered Matt as the name). Figure 39. Inspecting variables Debugging and testing Java applications Page 42 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 43. ibm.com/developerWorks developerWorks® 20. To see what your current output is to the browser, examine the out variable. Find the current buffer of characters stored under the variable named cb. Feel free to continue stepping through code. When ready, click on the Resume button (green arrow) to allow the thread to continue its execution. Look in the browser to see if the name is displaying correctly. Try entering a few more names to test the functionality of the application. When you are happy with it, stop the server and continue on to the next section. Your output should be similar to the following image. Figure 40. Web Browser Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 43 of 62
  • 44. developerWorks® ibm.com/developerWorks Section 7. Using step-by-step debugging Another feature that is available in Application Developer is step-by-step debugging. To enable step-by-step debugging, select a WebSphere Application Server debug target, thread, or stack frame in the Debug view, and do one of the following: • Click the Enable/Disable Step-by-Step Debug button • Right-click and choose Step-by-Step Debug from the pop-up menu Debugging and testing Java applications Page 44 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 45. ibm.com/developerWorks developerWorks® Figure 41. Step-by-Step Enable Now with step-by-step debugging enabled, try debugging your application once more by entering a name in Input.html. Make sure the server is running in debug mode. When step-by-step debugging is enabled you are presented with a screen that asks you if you want to step into the current element. In this case, notice that it is asking if you want to step into NameController.doPost. Click OK. Figure 42. Step-by-Step Debug window Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 45 of 62
  • 46. developerWorks® ibm.com/developerWorks If step-by-step debugging is enabled, disable it by taking one of the above actions. To disable step-by-step mode by default, select the Disable step-by-step mode check box in the Step-by-Step Debug dialog box or change the default step-by-step mode in the preferences. The default mode is applied when a new debug session is started. Once the debug session is started, change the mode using one of the methods described above. If step-by-step mode is enabled, you are prompted to debug every Web object loaded in the server in the application you are debugging. If step-by-step mode is disabled, the Web object that you are debugging continues to run. The debugger stops at breakpoints if step-by-step mode is enabled or disabled. Once you have stepped into a method, the normal debugger controls are available to you. Assuming that your thread is now suspended inside the debugger, click the resume button. Notice that it stopped on the next Web object, namely NameList.jsp, and not the NameHandler helper class. It would, however, stop on any breakpoints if they were still set. Figure 43. Step-by-Step Debug in NameList.jsp Debugging and testing Java applications Page 46 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 47. ibm.com/developerWorks developerWorks® Step-by-step debugging is a convenient feature when trying to establish the overall flow of an application. To debug an application you would typically use regular debugging or step-by-step debugging combined with regular debugging: step-by-step for high-level debugging, and regular debugging for a finer level or granularity. Section 8. Locating and viewing WebSphere Application Server logs Using the debugger is one part of troubleshooting an application. Sometimes, however, the problem may lie with the server itself. Being aware of the logs and where to find them can help you troubleshoot in those instances. The logs for the WebSphere Test Environment can be found under <install root>runtimesbase_v6profiles<profile_name>logs. In the image below you see some of the main logs for the WebSphere environment, such as the activity log, that contains binary information that can be read by the Log Analyzer tool. The Log Analyzer tool can compare the errors found in this log against a System database (an xml file) to try and analyze and report any environment problems. Figure 44. WebSphere logs Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 47 of 62
  • 48. developerWorks® ibm.com/developerWorks Logs for the application server itself are buried one level deeper under <install_root>runtimesbase_v6profiles<profile_name>logs<server_name>. Figure 45. Server 1 logs Debugging and testing Java applications Page 48 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 49. ibm.com/developerWorks developerWorks® In this directory find such logs as startServer, SystemErr, SystemOut, trace. The logs follow a standard format of <timestamp><pid><Component><message type><message nbr: message> pid: thread id message type: Message type symbols definitions Ã#Â Entry to a method (debug) < Exit of a method (debug) A Audit W Warning X Error E Event (Debug) Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 49 of 62
  • 50. developerWorks® ibm.com/developerWorks D Detail (Debug) T Terminate (Exits process) F Fatal (Exits process) I Information O Program Output C Configuration Here is an example of the SystemOut.log. Figure 46. SystemOut log Timestamps give good clues as they are real machine time values. They are good when comparing traces from different processes. Look for exceptions from the top. Events prior to the exception are the probable cause. Any events after the exception are recovery attempts. You may often find it useful to follow a particular thread (PID) to see what is happening. Let's talk about a few of the log files. System.out and System.err are the logs for Standard JVM output and error logging, respectively. They contain server as well as user program information (sent by: System.out.xxx code in the program). The startServer.log and stopServer.log contain output from the application server on attempts to start and stop it. They can also be found in <install_root>logs<server_name>. The trace.log holds information from a diagnostic trace, should you turn one on. Debugging and testing Java applications Page 50 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 51. ibm.com/developerWorks developerWorks® Section 9. Performing unit testing with JUnit The final section of this tutorial introduces you to Application Developer's built-in support for JUnit. This tutorial does not teach a testing methodology, nor does it teach all of the capabilities of JUnit. Rather, it shows how Application Developer supports JUnit. Still, we must talk a little about JUnit for those who know nothing about it. JUnit is a regression testing framework written by Erich Gamma and Kent Beck. It is used by the developer who implements unit tests in Java. JUnit is open source software, released under the Common Public License Version 1.0 and hosted on SourceForge. (See Resources for links to sites on JUnit and Common Public License.) The fundamental part of JUnit is a TestCase. Build TestCases to run tests against individual classes. Those TestCases can then be run together in a TestSuite. All of these tests can be versioned with your source code to provide a mechanism for regression testing. Let's see the support that Application Developer has for JUnit. 1. To use JUnit, first select the class for which you want to build the test case. In this case select the NameHandler.java file in the Project Explorer. Go to the File menu and select File > New > Other. 2. When the window opens select Java > JUnit > JUnit Test Case. 3. If you do not see the JUnit folder, select the Show All Wizards check box. Figure 47. New wizard selection window Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 51 of 62
  • 52. developerWorks® ibm.com/developerWorks 4. Click Next. 5. Application Developer then verifies if JUnit is on your projects class path. If it is not, the following window opens: Figure 48. Classpath verifier 6. Click Yes to add the junit.jar to you build path. 7. By first selecting the NameHandler.java file in the Project Explorer, the wizard is pretty much filled out for you when it opens. If yours is not, fill in Debugging and testing Java applications Page 52 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 53. ibm.com/developerWorks developerWorks® the fields to match the following image: Figure 49. New JUnit test case wizard 8. You have to check the check boxes in either case. After you have filled in this screen, click Next. 9. You are now presented with a screen that allows you to create the Test methods for your TestCase. Any methods that you check here are added to your class and prefaced with test (for example, testProcessName). The JUnit runtime then uses reflection to search for any methods that begin with test... and runs them serially. The setUp method is run before each and every test... method and the tearDown is run after each and every test... method to make sure that no residual effects from a previous test affect the next one. 10. Check the check box next to the processName(String) method. Figure 50. Test methods view of wizard Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 53 of 62
  • 54. developerWorks® ibm.com/developerWorks 11. Click Finish. 12. Once the wizard has completed, open an editor on the NameHandlerTest.java file. The methods have already been stubbed out for you based on your input to the wizard. Edit the methods of the class to make them look like the following code. Comments have been added in the listing below to describe what the code is doing. It is not necessary to put them in your code. public class NameHandlerTest extends TestCase { /*In JUnit speak, instance variables are referred to as the fixture. They are usually initialized and reset by the setUp and tearDown methods, respectively.*/ String testName = null; public static void main(String[] args) { /*The main method is not used in our case. It could be used if you wanted to run JUnit from the command line instead of through the GUI*/ Debugging and testing Java applications Page 54 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 55. ibm.com/developerWorks developerWorks® junit.textui.TestRunner.run(NameHandlerTest.class); } protected void setUp() throws Exception { /*The setUp method is used to initialize the fixture. It is run before each test... method.*/ super.setUp(); testName = "default"; } protected void tearDown() throws Exception { /*The teardown method is used to reset the fixture and prevent residual effects from previous tests. It is run after each test... method.*/ super.tearDown(); testName = null; } public void testProcessName() { /*The test... method uses an assertion to test for some "truth." In this case, it is checking to see if the expected value "true" matches the actual value that is returned from the second argument.*/ assertEquals(true, NameHandler.processName(testName). contains(testName.toUpperCase())); } } 13. Save the changes to your code. Now select the NameHandlerTest.java file in the Project Explorer. Open a context menu and choose Run > JUnit Test. Application Developer now uses the JUnit runtime to execute your test case. It also adds a new view to your perspective called the JUnit view. Change to this view to see the results of your test. The GUI for JUnit gives immediate feedback on your tests. You do not have to interpret the test results yourself: If the bar is green, the code is clean (This statement is made with apologies to the late Johnnie Cochran!). Okay, your code may not be clean, but it at least passed your test. You have to make sure you write quality tests to make sure that your code is clean. Figure 51. JUnit view Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 55 of 62
  • 56. developerWorks® ibm.com/developerWorks 14. Make a slight change to the assertion in the testProcessName method of the NameHandlerTest class. Change the word true to false and rerun your test. The bar should now be red. In the failure trace it also reports why the test failed, listing what was expected versus what was actually returned. Figure 52. Hierarchy screen of JUnit view Normally, you would create a series of test methods for this class within the same TestCase; however, you are going to do something different here to illustrate how to create and run a TestSuite. A TestSuite is a holder for many different TestCases. Add different TestCases to the suite and then run them together as a group instead of individually. To create your TestSuite you need a couple of TestCases; you already have one. Let's create another! For illustrative purposes, the easiest way to do this is to make a copy of your previous TestCase and edit it. Debugging and testing Java applications Page 56 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 57. ibm.com/developerWorks developerWorks® 1. Open a context menu on NameHandlerTest.java. 2. Choose Copy from the menu. Now, paste it back into the same package. When you do a Name Conflict window opens! Use it to enter the name for your new TestCase: NameHandlerTestforNull. Figure 53. Name conflict dialog 3. Open a java editor on your new TestCase and make the following change to the testProcessName() method: public void testProcessName() { NameHandler.processName(testName); assertNotNull(NameHandler.nameSet); } To create the TestSuite, use the File menu to open a wizard. 1. Choose File > New > Other. 2. Select Java > JUnit > JUnit Test Suite. Figure 54. Select a wizard view Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 57 of 62
  • 58. developerWorks® ibm.com/developerWorks 3. Click Next. 4. Edit your dialog to match the following screen. Be sure to check both TestCases, as this is how to add them to the TestSuite. Optionally check the check box to create a main() method. Remember that this is only used if you want to access your test from the command line. Namely, it provides a way to script your tests through frameworks such as ANT. Figure 55. New JUnit test suite wizard Debugging and testing Java applications Page 58 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 59. ibm.com/developerWorks developerWorks® 5. Click Finish. Now you are ready to test your suite. Use the exact same steps you used for running an individual test -- by running the TestSuite as a JUnit test. Do so now! You see the results from the two TestCases listed in the JUnit view. If you left the value in the testProcessName method set to false you have failed one, or both of your tests. Change the value back to true to pass. Figure 56. JUnit view for TestSuite Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 59 of 62
  • 60. developerWorks® ibm.com/developerWorks Section 10. Conclusion You have now seen some of the support that Application Developer has for JUnit. If you are curious about the other debugging and profiling features of Application Developer, be sure to search the help system. A search term to use in the help system is Hyades. If you understand what you have done so far you have a sound understanding of the support that Application Developer has for JUnit. This concludes our tutorial on testing and debugging in Rational Application Developer. Good luck with the rest of this series and on your certification exam! Debugging and testing Java applications Page 60 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.
  • 61. ibm.com/developerWorks developerWorks® Downloads Description Name Size Download method Download the solution for the tutorial tut6_solution.zip 27KB HTTP Information about download methods Debugging and testing Java applications © Copyright IBM Corporation 1994, 2007. All rights reserved. Page 61 of 62
  • 62. developerWorks® ibm.com/developerWorks Resources Learn • Get certified as an IBM Certified Associate Developer. Check out the objectives, sample assessment tests, and training resources for test 255, Developing with IBM Rational Application Developer for WebSphere Software V6. • If you haven't already, take the other Rational Application Developer certification preparation tutorials in this series. • Stay current with developerWorks technical events and webcasts. Get products and technologies • Download a copy of JUnit from SourceForge so you can independently test your software. • Read more about JUnit and extreme programming. • Download a free trial version of IBM Rational Application Developer. • Build your next development project with IBM trial software, available for download directly from developerWorks. Discuss • Participate in the discussion forum for this content. • Participate in developerWorks blogs and get involved in the developerWorks community. About the author Matthew Stobo Matthew Stobo is a Senior IT Specialist for the IGS Sales Team--East supporting WebSphere Application Server. Previously he was a Senior Instructor with IBM IT Education Services, where he developed and taught courses across the Java and WebSphere curricula. He regularly trained employees of Fortune 500 companies, large banks, and various government agencies in the fundamentals of J2EE development using Rational Application Developer and the administration of WebSphere Application Server. He received his Masters of Information Technology Education from Dalhousie University. Debugging and testing Java applications Page 62 of 62 © Copyright IBM Corporation 1994, 2007. All rights reserved.