NetBeans: WebApps
JSP Compilation, Breakpoint Support and Validation User View
$Revision: 1.1 $
Changes: available in
CVS
Author: Petr Jiricka, Sun Microsystems/NetBeans
- Abstract:
- This document proposes a new user model for JSP compilation, supporting JSP breakpoints and related user tasks.
It does so by revisiting the current user model, its motivations, and justifying the new user model by
stating new motivations and emerging user needs.
- Contents:
JSP development introduces several user problems, which can appropriately be solved by an IDE.
Firstly, when editing JSP pages by hand, the user wants to be guarded against making syntax mistakes, and the tool should help discover such mistakes. There are two subcategories of these errors: errors which cause the JSP-to-Java translation to fail, and errors which break the Java-to-class compilation. It is desirable to discover both kinds of these mistakes before deploying to the server, because the IDE can automatically set the editor cursor to the line containing the error, but for other reasons too.
The second problem is that the user often needs to look at the servlet generated from the JSP page, as a way to discover errors that can not be discovered by the syntax checker. There should be a simple action which allows showing the servlet code for a given JSP page.
A third requirement is the ability to debug JSP pages by stepping through JSP code line by line, and also by stepping through the code of the generated servlet. This process should allow incremental debugging, i.e. the ability to debug a new version of a JSP without having to restart the server.
Currently the above requirements are met in the following way. There is an action
Compile on each JSP, as well as on the Web Module as a whole. This action is dependent on the server that is currently selected as the default for the particular web module. If the server plugin does not support JSP compilation, the action is disabled (this is currently considered a usability bug). If the plugin supports JSP compilation, the server's compiler is called to produce the servlet for the JSP. Subsequently, the IDE's Java compiler (provided by the Java module) is called to compile the generated servlet into a
.class file. (This design is the cause of P2 bug 23135.)
In the case the JSP page contains errors, the compilation step fails. The compilation errors are displayed in the IDE's output window. Upon clicking the error description in the output window, the user is (or should be, in theory) brought to the place in the editor which contains the error. Without the compilation feature, the JSP page would be compiled by the server, and potential errors would be displayed in the web browser in a rather cryptic and hard to read form. It would not be possible to step into the editor to the line containing the error.
When the page has been compiled, the View Servlet action on a JSP is enabled. This action displays the generated servlet in the code editor in the read-only mode.
Since the IDE has access to the generated servlet, it can manipulate breakpoints in its source. It can also create a mapping between the lines in the Java code and lines in the JSP code, which allows the user to set breakpoints directly in the JSP source, and these are then correctly interpreted by the debugger.
When the server then executes the page, it does not compile it, as it normally would (without the compilation feature). Rather, it reuses the compiled class produced by the IDE's compilation.
During the period when the compilation feature was present in the IDE (Forte for Java 1.0 to SunONE Studio 4.0), many disadvantages and additional requirements were discovered.
First and foremost, it proved quite hard to write server plugins which support JSP compilation. Currently, only the Tomcat plugin fully supports the compilation feature. Furthermore, non-existence of standard interfaces between the IDE and the server caused that compilation had to be significantly reworked with each new version of the Tomcat server (JSWDK 1.0.1 in FFJ 1.0, Tomcat 3.2 in FFJ 2.0 and 3.0, and Tomcat 4.0.x in S1S 4.0). Also, supporting compilation requires changes to the running server (so it uses the classes compiled by the IDE, rather than compiling its own).
A second (related) motivation for changing the behavior is to support the emerging standards in the area of compilation and debugging. Some APIs for compilation of pages by tools will be a part of the JSP 2.0 specification. Standard APIs for JSP debugging are defined by JSR 45 - Debugging Support for Other Languages. The use of standard APIs will make the process of producing server plugins easier.
Another huge disadvantage of the current approach it its poor performance. The difference between running a JSP page in the Full IDE integration mode (in which compilation is enabled) and the Minimum IDE integration mode (which disables compilation) is very significant.
An additional requirement is to support checking for errors in the page even in the case when the plugin currently selected for the page does not support JSP compilation. Recall that if the plugin does not support compilation, error detection is not user-friendly.
Next, error checking should be more immediate than when the user attempts to compile (or run) the page - syntax errors should be discovered sooner in the development cycle. For this purpose, it would be desirable to implement in-place error detection (when the syntax checker underlines incorrect syntax as the user types), as is currently implemented for .java files.
Finally, a future (post-2.0) version of the JSP specification may define a way to compile pages by the tool, package the compiled servlets/classes into a .war file and deploy them to the server. This would be useful as it reduces the initialization time of the web application in a live deployed environment, and improves the scalability and predictability of the server right after startup. We may decide to support this feature in the IDE in the future, but it is probably not necessary to support this before the mechanism is standardized (and servers provide pre-compilation capabilities using own server-specific ways).
We now explore all the possible solutions to the requirements above, and point out the advantages and disadvantages of each of them.
There are several possible ways to accomplish validation of JSP pages after editing.
- Compile the page using the current server's JSP compiler. This is the approach currently used in the IDE. The server plugin
for the current server must support JSP compilation using IDE's compilation APIs. The page is translated to
a (server-specific) Java servlet, and that is compiled using the Java compiler to the
.class file. Any errors encountered
during the process are reported to the user.
The one thing that would be different is that the plugin would be responsible for all stages of the
compilation, unlike now, when it is only responsible for the JSP to Java traslation, but not for the Java to class translation.
Benefits of this change in the API contract would be easier integration with servers, better readiness for
standard compilation APIs (which will also presumably assume that the plugin is responsible for the Java to class compilation),
and the ability to fix bug 23135
(although this bug could be fixed by other means too).
- Compile the page using a server-independent JSP compiler. This approach is a variation of the previous approach,
the difference being that now the same compiler is used regardless of the target server setting.
- Do a partial syntax check using a server-independent JSP parser. For this, the JSP parser would be used regardless of the
default server setting. It only reports errors discovered during parsing of a page, not errors that would be discovered during the
Java to class translation.
The following table summarizes the advantages and disadvantages of the individual approaches:
| Compile the page using the current server's JSP compiler |
Compile the page using a server-independent JSP compiler |
Do a partial syntax check using a server-independent JSP parser |
+ |
All errors in the page are discovered. |
+ |
Will be very easy to do after the JSP compilation APIs are standardized. |
- |
Difficult integration with (most) servers until the compilation APIs are standardized. |
- |
Requires a temporary "throwaway" solution for the period of time until the compilation APIs are standardized. |
- |
Slower than just checking the page syntax. |
|
+ |
All errors in the page are discovered. |
+ |
Requires integration with one JSP compiler only (this will presumably be the Tomcat compiler). |
- |
When there is an error in the generated servlet, the servlet source that will be shown by the error reporting mechanism
will not be the one that will actually be used by the current server. |
- |
Slower than just checking the page syntax. |
|
+ |
Can reuse the integration with the JSP parser, which has to be done anyhow. Relatively easy integration. |
+ |
Significantly faster than doing a full compile. |
- |
Only some errors on pages containing scriptlets are discovered. (For scriptless pages, all errors are discovered.) |
|
There may be some additional considerations, such as: should we provide the same level of validation for pages containing scriptlets as
for scriptless pages ? We let the reader answer this and other questions for each particular solution for themselves.
Sophisticated users will often need to look the servlet generated from the JSP. Often they will need to set a breakpoint in the servlet.
There are a few possible ways how viewing the generated servlet can be accomplished.
- Compile the page using the current server's JSP compiler. This is the approach currently used in the IDE. The server plugin
for the current server must support JSP compilation using IDE's compilation APIs. The servlet produced by the compiler is shown to the user.
We are assuming that the JSP compilation APIs proposed for standardization will provide means to retrieve the generated servlet. This option
basically assumes that the servlet has been produced by the IDE.
- Use the server process compiler and implement an interface to return the location of the generated servlet. The server provides an interface
which allows to check for modification of the page.
- Combination of the above approaches.
We are proposing a new user view, which addresses both the original requirements (which are still valid and desirable) and the new requirements.
JSP Compilation will not be an explicit user action in the IDE any more. Rather, it will be performed by the server, as is usual in IDE-less environments. So both the JSP-Java transtlation and the Java-class compilation steps will be the responsibility of the server.
The IDE will continue to support the View Servlet action. This action will show the servlet code generated by the server, which is currently set as default for the page. If the page has not been compiled by the server yet, the action will be disabled. This means that in order for the View Servlet to be enabled, the server must have run.
The implementation of this action will rely on standard APIs - we need to work on defining these for the JSP 2.0 specification - which allow the IDE to find out the location of the generated servlet file. These APIs will be implemented by the server plugin. In addition to this, the IDE will need to be notified by the server to find out that the page has been recompiled by the server, and consequently the servlet has changed. For this, the running server will need to be modified to perform this notification.
The support for JSP breakpoints needs to do three main tasks. First, it has to create a mapping between JSP file lines and servlet file lines. Secondly, it needs to allow the user to set the breakpoint in both the JSP and the generated servlet, and map this breakpoint to the corresponding Java file (and JSP file, respectively). Lastly, it needs to regenerate the mapping and remap the breakpoints whenever the JSP page has been recompiled by the server.
This mechanism will be changed in the following way: The mapping is produced by any JSR 45-compliant server, and a mechanism specified by the JSR 45 is used to pass this mapping from the server to the tool.
The second part will from the user's perspective be done in the same way as is done currently, although there may be changes in the implementation relevant to the core debugger module and the JSP debugging module.
Remapping the breakpoints will occur when the server notifies the IDE (using the IDE-inserted component running in the server) about the change and recompilation of the JSP page.
JSP Validation is a new mechanism which serves the purpose of detecting syntax errors in the JSP. It is implemented in two principal ways: the
Validate action for a JSP file, and error detection and underlining in the editor.
The Validate action parses the JSP file and prints any validation errors into the IDE's Output Window. These are clickable, so the user is brought to the place in the page where the error occurred. The action does not produce any Java output, nor it compiles the servlet. Consequently, it may not discover some errors that JSP compilation would. However, errors that occur during the Java to class translation are usually errors in the user's scriptlets embedded in the page, and the growing trend is to discourage the use of scriptlets and replace them by tag libraries and the JSP expression language. So it can be argued that this disadvantage does not pose a significant problem.
The Validate action is independent of the server that is currently set as the default for the JSP page (in the sense that it would not benefit in any way from using multiple servers' implementations) and is implemented using the IDE's JSP parser, which uses Tomcat code. It is expected to be significantly faster than the current Compile action.
It will be configurable whether validation is to be run before execution/packaging/deployment, with the default being yes.
An icon badge on the JSP file node will indicate whether the page is valid, or whether it needs to be validated.
The error underlining in the editor is similar to validation in that it detects syntax errors in JSP pages, but differs from it in the following ways: it is not invoked explicitly by the user, but works on the background as the user types in the editor. Secondly, it does not produce output in the IDE's Output Window, but underlines the parts of JSP code which contain errors.
When the page is run in the server, it is in general impossible to find out in the IDE whether it has compiled successfully. However, for some servers (Tomcat) we may be able to find this out by running IDE-inserted code component in the server, which would notify the IDE about the compilation error.
The JSP 2.0 specification will define a way to compile JSP pages by tools, and then deploy the compiled classes with the web application to the server. This will work at the granularity of a Web Module. It is not clear whether it is necessary to provide compilation for deployment as a separate user action. One way to provide this functionality could be to have an option on the
.war archive representation (the war recipe in the Project's build configuration) saying whether the JSPs should be compiled before packaging or not, or a similar mechanism which utilizes the build system in the IDE.
There are three disadvantages of the proposed user view.
First, JSP validation as proposed in section 5.3 may not discover all syntax errors in the JSP page, and in this sense is less capable than the JSP compilation.
Secondly, in order to view the servlet generated from a JSP, the user must first execute the page in the server. Hopefully this is not a concern, as the View Servlet action is mainly used to diagnose problems after they occur, e.g. after the page has been executed.
Lastly, in order to implement viewing the generated servlet, and debugging, for cases when the page has been recompiled on the server, the IDE needs to smuggle its code into the running server. This is not a degradation compared to the current situation, since this has to be done currently as well, in order to support JSP compilation, debugging or HTTP monitoring. The likelyhood of standardization of this mechanism is small, so we will have to continue to rely on ad-hoc mechanisms implemented on a per-server basis, possibly in cooperation with the server makers.