Book Image

Java EE 5 Development with NetBeans 6

Book Image

Java EE 5 Development with NetBeans 6

Overview of this book

Table of Contents (17 chapters)
Java EE 5 Development with NetBeans 6
Credits
About the Author
About the Reviewers
Preface
Identifying Performance Issues with NetBeans Profiler

Debugging Enterprise Applications


Typically debugging enterprise Java EE applications is somewhat a complicated process, and our application server needs to be started in "debug mode". The procedure for doing this is different depending on the application server, but typically involves passing some command line parameters to the shell script or executable that starts the application server. Our code must also be compiled with debugging enabled. This is usually done either setting a parameter on the IDE or passing some arguments to the javac executable. Also, our debugger must be "attached" to the application server so that it can see the code running in a separate JVM.

Thankfully, all of the steps described in the previous paragraph are automated when using NetBeans with the bundled GlassFish application server. When using this combination, all we need to do is open our Enterprise Application Project then right-click on it and select Debug. At this point the application server is started in debug mode (or restarted in debug mode if it was already running in standard mode), the application is deployed and the debugger is automatically attached to the application server.

We will use the application we developed in Chapter 10 to illustrate NetBeans debugging capabilities. In order to illustrate such capabilities, we will make one slight modification to the application in order for it to break under certain circumstances. Recall that all JPA entities were generated for that application. When generating JPA entities with NetBeans, we either need to set the primary key explicitly when inserting a new row in the database, or we need to set automatic primary key generation using the @GeneratedValue annotation. In our example we used the second approach. In order to "force" our application to break when inserting new rows, we will remove this annotation from the Customer JPA entity.

After clicking the Add New button in our application, entering some data and clicking the Save button, we are now greeted with the following page.

Looking closely at the Stack Trace displayed on the above page, we can see the following line:

com.ensode.customermanagement.managedbean.EditCustomer.saveButton_action(EditCustomer.java:147)

The above line is telling us that the exception occurred on line 147 of EditCustomer.java, therefore we need to pause our application’s execution just before that line is executed, so that we can inspect the values of all relevant variables at that point.

One central feature of debuggers is the ability to pause execution of the application being debugged by adding breakpoints to it. When a line of code where a breakpoint has been placed is about to be executed, the application pauses, allowing us to inspect the values of all instance and method scoped variables in the class where the breakpoint was placed. In NetBeans, placing a breakpoint in a line is very simple; all we need to do is click on the left margin of the source editor right next to the line where the breakpoint will be added. At this point the line will be highlighted in red plus a red square icon will be placed in the left margin.

Note

To make the left margin display line numbers, we need to right-click on it and click on the checkbox labeled Show Line Numbers.

At this point we are ready to debug our application, which we can do by simply right-clicking on our project and selecting Debug. Doing this causes our application to be deployed and executed as in debug mode.

We need to test our application as usual in order to get to the point where it is failing. In our example we would simply click on the Add New button in the Customer list page, then enter some data for a new customer and click on the Submit button. At this point the line containing the breakpoint will be reached, and our application execution will be paused.

Looking at the editor, we will see that the line containing the breakpoint is now highlighted in green, plus an arrow has been placed on the left side margin.

These changes indicate the current line in the execution path. Once the execution has been paused, we can execute the code line-by-line in order to pinpoint exactly where the problem is happening. There are two ways we can execute each line: we can either step over the line, or step into it. The difference being when we step over, we will not go "into" any method calls, simply going "over" the line; when we step into, we actually navigate inside any method calls that are being invoked in the current line.

In our example, stepping into the current line would take us to the getCustomerId() method of the Customer class, which we are certain works correctly. Therefore the most appropriate course of action is to step over the current line.

In NetBeans, we can step over the current line by pressing F8 or clicking on the icon. Doing so will take us to the next line to be executed in the current file, which will be highlighted in green, and an arrow will be placed next to it in the left margin.

At this point we haven’t reached the failure point of our application yet, and it seems unlikely that the problem will be in the current file. Therefore we need to step into the current line to navigate to the code in the create() method of the customerDAO object. In NetBeans, we step into code by clicking on the icon or pressing F7.

Since there is only one executable line in this method, we know that stepping over this line will cause the exception. We can inspect any local variables in the current class and method by looking at the Local Variables window.

Note

The Local Variables window can be opened by going to Window | Debugging | Local Variables or by pressing Alt+Shift+1 on windows and Linux systems, and Ctrl+Shift+1 on Mac OS X systems.

By expanding the node corresponding to our customer object, we can see the values of all of its properties. At this point we should notice that the customerId property is null, which results in the code attempting to insert a new row with a null primary key. We have discovered the problem. Now that the problem is known, fixing the code is trivial. In our example, the easiest way to fix it is to add the @GeneratedValue annotation to the customerId property of our entity bean.