Exploring JSP Documents (XML Style JSP Pages) By Carl Trusiak, SCJP2, SCWCD Download the war file containing the examples Providing the ability for an XML representation of a JSP page, also called a JSP Document, is not a new concept. The standards for it started as a vision with Specs for JSP 1.0. The intention was to allow JSP editing using XML tools. However, time ran out and it was not included. During the development of JSP 1.1, multiple mapping issues were identified and while standards were started, work was postponed to later revisions. Finally, with the release of JSP 1.2, a complete set of specifications and mappings are now available. The following examples require a JSP 1.2 compliant server to function properly. Tomcat 4 is the reference implementation for JSP 1.2. Every JSP element with the exception of <%-- comment --%> has an XML equivalent or replacement. The syntax for a few are exactly the same in JSP style and XML style. These include :
Why worry about a JSP Document instead of the standard JSP Page? If you are one of those studying for your Sun Certified Web Component Developer Certification, it is part of the objectives. Beyond that, the Specifications for JSP 1.2 give some very valid reasons.
Converting a JSP Page to a JSP document is a fairly simple process. Let's look at a very easy page. <html> <body> <center> <h1>Hello World</h1> </center> </body> </html>Whenever converting a JSP Page to a JSP Document, you need to include a root element which contains the rest of the document. HTML presents it's own issues for an XML Document. To allow HTML inside your JSP Document, it all needs to be wrapped in a jsp:text element. Specifying the element to be of type CDATA eliminates the need to escape special characters. Therefore, the equivalent page becomes. ---simplexml.jsp--- <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="1.2"> <jsp:text><![CDATA[<html> <body> <center> <h1>Hello World</h1> </center> </body> </html>]]></jsp:text> </jsp:root>Not very much of a difference. However, that was an extremely simple page. Things speed up when scriptlets and declarations are added into the mix. This introduces the main elements that are different in a JSP Document and a JSP Page; the page directive, scriptlets, declarations and expressions. ---datetime.jsp--- <%@ page import="java.util.Date, java.text.SimpleDateFormat" %> <% Date d = new Date(); String dateString = getFormattedDate (d); %> <html> <body> <center> <h1>Hello World</h1> The date and time is : <%= dateString %> </center> </body> </html> <%! String getFormattedDate(Date d) { SimpleDateFormat simpleDate = new SimpleDateFormat("dd-MMMM-yyyy hh:mm"); return simpleDate.format(d); } %>The equivalent XML syntax for each of these elements are:
One thing to note, if the scriptlet, declaration or expression contains special characters, be sure to wrap it in a CDATA element to prevent the need for escaping. <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="1.2"> <jsp:directive.page import="java.util.Date, java.text.SimpleDateFormat" /> <jsp:scriptlet> Date d = new Date(); String dateString = getFormattedDate (d); </jsp:scriptlet> <jsp:text><![CDATA[ <html> <body> <center> <h1>Hello World</h1> The date and time is : ]]></jsp:text> <jsp:expression>dateString</jsp:expression> <jsp:text><![CDATA[ </center> </body> </html> ]]></jsp:text> <jsp:declaration> String getFormattedDate(Date d) { SimpleDateFormat simpleDate = new SimpleDateFormat("dd-MMMM-yyyy hh:mm"); return simpleDate.format(d); } </jsp:declaration> </jsp:root>The one other place that JSP Documents differ from JSP Pages is the declaration of TagLibs. On a JSP Page, you would use the syntax: <%@ taglib url="URI" prefix="tagPrefix" %> While a JSP Document declares this as a set of attributes for the root element. For the following example, I'm using the DateTime TagLib available from the Jakarta TagLib Project. The first thing you may notice is how well a custom tag cleans up the appearance of the page. ---datetimetaglib.jsp--- <%@ taglib uri="http://jakarta.apache.org/taglibs/datetime-1.0" prefix="dt" %> <html> <body> <center> <h1>Hello World</h1> The date and time is : <dt:format pattern="dd-MMMM-yyyy hh:mm"> <dt:currentTime/> </dt:format> </center> </body> </html>---datetimetaglibxml.jsp--- <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:dt="http://jakarta.apache.org/taglibs/datetime-1.0" version="1.2"> <jsp:text><![CDATA[ <html> <body> <center> <h1>Hello World</h1> The date and time is : ]]> </jsp:text> <dt:format pattern="dd-MMMM-yyyy hh:mm"> <dt:currentTime/> </dt:format> <jsp:text><![CDATA[ </center> </body> </html> ]]></jsp:text> </jsp:root>While these examples are fairly simple, they demonstrate most of the information you need to effectively convert any JSP Page to a JSP Document. The end result does not have to be html. These methods can be used to genterate an xml output if needed by the system. One final reason I can think of for using JSP Documents, it allows the JSP engine to use a more efficient XML Parser during the translation phase. I included two files that have parse errors on them to show the stack trace. error.jsp and errorxml.jsp |
||||||||||||||||||||||||||||||||||||||||||||
JLS 15.12 (Method Invocation Expressions) in Plain EnglishThis article aims at giving a more understandable description of what a method invocation expression really is. The Java Language Specification is targeted at people having a certain mathematical background. What we are trying to do here is to explain its content to people having a moderate experience in technical English and willing to get to know Java in a more advanced way without coping with pure maths. There are a lot of things going on under the hood when methods are invoked. First of all, a method is to be seen as a service a class provides to itself and/or to other classes. Whenever the compiler encounters a method invocation it has to figure out which method is to be invoked and most importantly where to find its implementation. To get the ball rolling let's just think of some real-life examples. If we want to order a pizza, we have to call a pizza delivery place and not the immigration office or the hospital. If we want to buy a car, we sure don't go to Starbucks or the train station. Put shortly, we have to find the right place where we are sure we are going to get the service we need. "we" stands here for the compiler which is in charge of turning the human-readable Java code you have written into bytecode the Java Virtual Machine (JVM) will understand. And that's exactly how we are going to proceed here, we will try to "think" exactly the same way the compiler does. Trying to figure out what the compiler does and how it works is an excellent exercise not only to gain in-depth knowledge of the compilation process but also to spare development time by recognizing code that will result in compile-time and run-time errors. The following table shows how this article is organized. In order to keep things pretty much organized the same way as in Section 15.12 of the the Java Language Specification (JLS), we decided to keep the same structure. The first part discusses the three steps performed at compile-time while the second focuses on what is achieved at run-time by the linker and interpreter.
Ok, let's go. Below is a slightly modified version of the method invocation expression given in JLS 15.12:
Although those expressions may seem overly complex, they are not. We can see that the part after the left paranthesis, that is ArgumentListopt), is common to all four cases. By investigating the form BEFORE the left paranthesis, we notice that we always find an Identifier which may be qualified or not. To qualify a method means that we have a clue of where the method may reside and we want to specify it (with the dot-notation). So, we will look into those six different cases and explain when they are used and what purposes they serve. Moreover, we are going to illustrate the concepts using the following example which contains at least one sample of each expression given above:
Step 1. Compile-Time Step 1: Determine Class or Interface to SearchThe compiler first has to discover the class --what we called a "place"-- in which the method --what we called a "service"-- we need is defined.
The goal of this first step was to determine the class or interface which contains the method to invoke. Now that we know exactly where to search we have to look for the right method to invoke. This is done in the second step where we will investigate which method signature fits best the invocation expression. In the rest of this article, we will use the same code examples as in the JLS. Step 2. Compile-Time Step 2: Determine Method SignatureThe choice of the right method is based on the method descriptor.
ApplicabilityTwo conditions must be met for a method declaration to be applicable:
The class or interface we found in the previous step as well as all its superclasses and superinterfaces are searched for all method declarations applicable to the method invocation we are trying to resolve. AccessibilityAccessibility depends on what type of access the method has been granted ( To get a better understanding of the applicability and accessibility concepts, let's have a look at the
following code borrowed from
JLS
15.12.2.1 (Find Methods that are Applicable and Accessible):
If we don't manage to find any method declaration that is both applicable and accessible, then an error during the compilation process will result as it is the case on line 9. Locate the Most Specific MethodThe case where several methods are applicable and accessible arises while
overloading methods. What do we do then? We just have to choose the most specific
one. How do we do that? The informal intuition is that one method declaration is more specific than another if any invocation handled by the first method could be passed on to the other one without a compile-time type error. To see how this makes sense, let's take a look at the following code. We have: public void doSomeJob(String s) and public void doSomeJob(Object o) Both methods are overloaded (same name but different parameter types). Now, suppose we have the following invocation expression: doSomeJob("Test"); Both methods are applicable since "Test" is a String but
also an Object (since a String is an Object ).
Always come to think of the most specific method
as the one having its parameter types matching the best the argument types of the invocation.
So, the first method is more specific than the second one because its parameter (String )
can be converted to the second's parameter (Object ) by method invocation conversion
(see JLS
5.3).
As we have seen above, we may end up with several methods being accessible and applicable.
The final goal of this step is to find the maximally specific method. Put simply,
a method is maximally specific if it is applicable and accessible and there is no other applicable
and accessible method that is more specific.
Another important consideration is that the return type of the method is not taken into
account when resolving method declarations. The following example illustrates the problem:
The invocation expression on line 12 will cause a compile-time error. The method on line 4 is the most specific (since it takes a ColoredPoint
argument) but the problem is that the return type, int , is not assignment
compatible with a String . The method on line 7 is also applicable but less
specific than the method on line 4. Moreover, by choosing the method on line 7 the compilation
would succeed because of the return type, String .
Step 3. Compile-Time Step 3: Is The Chosen Method Appropriate?If we managed to get to this step, it means that we have found THE most specific method matching the invocation expression and we call it the compile-time declaration for the method invocation. Now what? Remember the invocation patterns we saw at step 1? We now have to check if the chosen method can be used in the given context, that is, at the place where the invocation occurs. As an example, you certainly already know that you cannot invoke an instance method from within the body of a static method. We have to make sure that such things don't happen. This is what this step is for. If the invocation pattern is:
Moreover, if the return type of the compile-time declaration is void then the
method cannot be used where a value is expected. For instance, suppose we have the following
expression:String s = doSomething(); and doSomething 's return type is void then a compile-time error
occurs.More generally, a method whose return type is void can only be used as an
expression statement, that is, alone on a line, or in the initialization or update part of
a for statement
(see JLS 14.13).
Finally, if the chosen method passes all tests successfully, the compilation will succeeds
and we can proceed to runtime checks. The bytecode of the method invocation now contains
the following information that can be used at runtime by the Java bytecode interpreter:
Step 4. Runtime Step 1: Compute Target Reference (If Necessary)A target reference is a reference to an instance of a class (an object) on which the method
will be invoked. No target references are needed for
Step 5. Runtime Step 2: Evaluate ArgumentsThis step's job is to evaluate the argument expression from left to right. If any argument expression evaluation fails, then no argument expression on its right will be evaluated and the method invocation expression fails for the same reason. Step 6. Runtime Step 3: Check Accessibility of Type and MethodWe now have to determine if the type of the target reference and the method to invoke are accessible. Three different entities are involved here:
Any Java programming language implementation must check during linkage that:
Accessibility is the next issue. Since the invocation of method
Class/interface
Finally, method
If this paragraph seems overly complex to you, rest assured that it wasn't out
original intent. The content is very logical. Just read it once or twice before going on.
Think of these accessibility issues as a sort of labyrinth where not only one but several
paths lead to the exit and some don't. Everything depends on the accessibility modifiers.
The next picture will help you find your way through the labyrinth. If either of the accessibility checks fails, then an Step 7. Runtime Step 4: Locate Method to InvokeWe now have to locate the method to invoke. The invocation mode (step 3)
provides us with that information. After this step we end up with a precise method to invoke.
Don't worry if you feel lost after reading this paragraph, the meaning is not very easy to grasp
and, moreover, this is the most important but also the most difficult step of the whole method
invocation process. Read this section twice or thrice if you feel the need to do so.
For the three remaining invocation modes, overriding may occur. That's why we need a dynamic method lookup process.
The process starts looking for the method in class
The method lookup for
S has a superclass, then this lookup is performed recursively on the
direct superclass of S . The result of this recursion will be the method to
be invoked.
This lookup always succeeds provided that the compilation of the classes has been done in a consistent way or various errors may occur. Step 8. Runtime Step 5: Create Frame, Synchronize, Transfer ControlThis step just handles
administration stuff, like creating a new activation frame, synchronizing data access if
needed and transferring control to the method body.
Written by Valentin Crettaz. |
||||||||||||||||||||||||||||||||||||||||||||
It's where you come to learn Java, and just like the cattle drivers of the old west, you're expected to pull your weight along the way. The Cattle Drive forum is where the drivers get together to complain, uh rather, discuss their assignments and encourage each other. Thanks to the enthusiastic initiative of Johannes de Jong, you can keep track of your progress on the drive with the Assignment Log. If you're tough enough to get through the nitpicking, you'll see your name on the Graduation Log.
And a shiny spur goes to...
Back from being out on the range...
Saddle sore...
Nitpicking is hard work too...
Tips for the Trail
...
Written by Jason Adam and Pauline McNamara |
||||||||||||||||||||||||||||||||||||||||||||
Java Rules by Douglas Dunn
I liked this book a lot yet was uncertain how to evaluate it. A book should be
judged according to the law of its genre and I had difficulty in defining what
the genre is. Finally I found the word: "commentary". Commentary on Java "legal
code" - a set of specifications - JLS, JVM, Inner Classes, Unicode standard,
selected parts from Java API, even JavaSoft tutorial on the Collection
framework, with detailed explanations.
Chosen by Cindy Glass and Madhav Lakkapragada |
||||||||||||||||||||||||||||||||||||||||||||
For more information on JavaRanch's Giveaways see Book Promotion Page.
|
||||||||||||||||||||||||||||||||||||||||||||
JavaRanch has added a new forum to better assist people in their hunt for information. January was a month of planning. Th new BunkHouse is in the process of moving from the planning stages to development. Discussions are on going to add a JSP Section to the Cattle Drive. Upgrades of background process to fully use the New UBB were completed. As always JavaRanch is dedicated to providing you with the best source of information on Java Programming and Engineering. |
Managing Editor: Carl Trusiak
Comments or suggestions for JavaRanch's NewsLetter can be sent to the NewsLetter Staff
For advertising opportunities contact NewsLetter Advertising Staff