The result of using Java Server Pages (JSP) to generate Web output (usually, but not exclusively, HTML) nearly always contains extra blank lines and spaces. Depending upon the exact nature of the page, there can be hundreds of them.
Now, you may think so what ?
Well, consider a page on a popular web-site. Let's say the page gets a modest number of hits, 1 every 5 seconds on average. That's 17280 in a 24 hour period. If the page is written in the usual nicely formatted way and has 30 JSP tags in it, 3 of which are iterative, this would produce a total of 30 blank lines (for the tags), plus at least 1 blank line per loop of the iterative tags, plus whatever padding was used on the tag lines. So, let's say 5 bytes per blank line (including the padding and newline), then 40 similar lines for the iterative tags, giving a total of 350 garbage bytes per request. Doing the math gives about 6 Mb of nothing per day, just for this one simple page alone. Now, imagine how many extra non-content bytes of data would be sent for the whole site, 50 pages perhaps of similar complexity. In a day that's now 300 Mb, a considerable chunk of nothing.
How the blanks get there
When using JSP the inclusion of non-markup tags is inevitable, otherwise why use a JSP ? The tags in the page may be a home-grown part of the Web application being developed, part of the Java Standard Tag Library (JSTL) or from a third-party library, such as Struts. Where they come from does not matter, what does matter is the effect they have on the generated stream of output.
The JSP code you write is not used directly, it is translated into Java code and compiled to make a servlet that is attached and invoked against the URL for the JSP page. The process of translating the JSP into Java statements is where the blank lines get introduced.
The translater replaces the non-JSP contents with print statements, and the JSP tags with indirect calls to the appropriate tag library methods. On the lines where the tags appear, the translater simply removes the the tags and emits the remainder in the print statements. Therefore, if a line contains nothing but format padding, a tag (open, close or both) and a newline, then the result is a print statement with just the padding and newline, the offending blank line.
Iterative or simple body content tags are worse, as the way they are normally used in JSP generates multiple blank lines. One for the open tag, one for the close tag, and some for each tag in the enclosed body. In the case of iterative tags, the body content blank lines are generated on each iteration, not just once.
However, they can be eliminated completely and trivially.
Getting rid of them
Getting rid of the blank lines is all down to how the original JSP page is written and formatted. To do this you will need complete control of how the JSP- and non-JSP tags are included in the page, therefore an IDE or HTML editor will probably not do, unless it enables you to modify the generated text.
When using the JSP tags, they must be formatted in such a way so as to remove all the padding and newlines that you do not want to appear in the output. Sounds obvious, but this means that normal formatting goes out the window, to be replaced with something that is more difficult to read, and therefore maintain, but gets rid of the blank lines.
The simplest case for illustrating this in the page tags at the top of a JSP that include the tag libraries and so on. Normal style would look something like that shown below.
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%> <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic"%> <%@ taglib uri="/WEB-INF/gws-utils.tld" prefix="utils"%> <%@ page import="app.Constants"%> <%@ page import="java.util.HashMap"%> <jsp:useBean id="reportDetails" scope="request" type="app.reports.Report"/> <bean:define id="pagebanner" toScope="request" type="java.lang.String"> Report - <bean:write name="reportDetails" property="title"/> </bean:define> <bean:define id="paramPrefix" toScope="page" name="reportDetails" property="urlParamPrefix"/> <html> ...
As can be seen, each tag is on a line of its own. When the translater processes these lines it simply removes the tag text from the line, inserts code into the associated servlet appropriate to the tag, then outputs the remainder using a print statement. The JSP snippet above would result in 11 blank lines appearing prior to the <html> tag.
To remove them the lines would need to be rewritten as below, removing all the newlines (and thus the blank lines). Notice how the tags now run in to each other.
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %><%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %><%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %><%@ taglib uri="/WEB-INF/gws-utils.tld" prefix="utils" %><%@ page import="app.Constants" %><%@ page import="java.util.HashMap" %><jsp:useBean id="reportDetails" scope="request" type="app.reports.Report" /><bean:define id="pagebanner" toScope="request" type="java.lang.String" >Report - <bean:write name="reportDetails" property="title" /></bean:define>< bean:define id="paramPrefix" toScope="page" name="reportDetails" property="urlParamPrefix" /><html>
Effectively there are no newlines in the snippet prior to the <html> tag. When the translater removes the JSP tag text, it removes everything between the first < and the last >, including any whitespace and newline characters.
Running the tags together like this works for any type of JSP tag, including those with body content. Special care must be taken with the close-tag of iterative tags. These must be written </closetag> for them to be properly picked up by the translater. So, even though a start-tag name can be split away from it's <, the close-tag name cannot be split away from it's </, so be careful. It is possible to separate the /> close-tag portion of a unary tag though, as shown in the above example.
Content of this page Copyright © Robert Quince 1996 - 2005.