Download (direct link):
01 //This is a very bad idea!
02 PrintWriter pw;
03 ServletOutputStream out;
06 //get binary data
07 out = response.getOutputStream();
08 //now write the binary data with out
10 catch (Exception e)
12 pw = response.getWriter();
13 pw.println("There was an error: " + e.getMessage())
Listing 33.2 Using control flow to determine output
Listing 33.2 is simple enough, but if the servlet is changed to include more and more conditionals, code management could be a nightmare as time goes on. What if more processing goes on after that segment of code? You would have to keep track of which one is used, and that is a bad idea. It is a lot easier to simply use the ServletOutputStream object alone, if there is a case where you are printing binary data.
The important thing to remember is that if you are sending different types of data to the client, make sure to set the content type with the HttpServletResponse object, as shown in Listing 33.1 on lines 51 and 61. Since our "Poll of the Day" servlet example
296 Item 33
prints either binary or character-based data, we should simply ask for the ServletOutputStream. Listing 33.3 shows the good example.
01 import java.io.*;
02 import java.text.*;
03 import java.util.*;
04 import javax.servlet.*;
05 import javax.servlet.http.*;
07 /* Good Voter Servlet Example */
08 public class GoodVoterServlet extends HttpServlet
11 public void doGet(HttpServletRequest request,
12 HttpServletResponse response)
13 throws IOException, ServletException
19 public void doPost(HttpServletRequest request,
20 HttpServletResponse response)
21 throws IOException, ServletException
23 String vote = request.getParameter("vote");
25 ServletOutputStream out = response.getOutputStream();
27 VoterApp voter = VoterApp.getInstance();
29 if ( vote == null )
31 //Let's print out the Poll of the Day!
33 out.println("<TITLE>Poll of the Day!</TITLE>");
34 out.println("<FORM METHOD='POST' ACTION='" +
35 request.getRequestURI() + "'>");
39 out.println("<INPUT TYPE='SUBMIT' VALUE='Vote Now!'>");
44 //Have our voter object tally up the results
Listing 33.3 GoodVoterServlet.java
The Mysterious File Protocol 297
47: //Get the generated poll results graph
48: byte generatedGraph = voter.generateImageBytes();
49: if ( generatedGraph == null )
52: out.println("<B>Technical difficulties.. Please see " +
53: "your administrator for details.</B>");
61: out.write(generatedGraph, 0, generatedGraph.length);
Listing 33.3 (continued)
As you can see in Listing 33.3, we get the ServletOutputStream on line 25. We use the println() methods for character-based data in lines 32 to 40 after setting the content-type to "text/html" on line 32. When there is an error in getting the binary image, we use the same mechanism for printing binary data on lines 49 to 55. Finally, when we have binary data to produce, we set the content-type to "image/gif", and write the binary data (or the graphed poll results in this example) to the user's browser with the methods inherited from java.io.OutputStream on lines 59 to 62.
This item showed the possible pitfalls that may lurk in your code when you try to use PrintWriter and ServletOutputStream together in a servlet. We showed you how to determine which object to use and showed how to eliminate this problem from your code.
Item 34: The Mysterious File Protocol
Many developers have built applications that read files from both the Internet and the local filesystem. Invariably, as developers get more seasoned, they discover that they are able to use the "file protocol" to reference local files as URLs. Because of this, a growing number of tools and APIs are beginning to simply accept URLs as references for files.
298 Item 34
A lot of Java classes are overloaded to handle both the conventional local file syntax and also the URL syntax for files. Figure 34.1 shows an example of a simple Web browser, built with one of those classes, JEditorPane. Observe that it is a simple JFrame with a JTextField and a JScrollPane containing the JEditorPane. A URL is typed into the JTextField, which is then browsed by calling the set-Page(String url) method on the JEditorPane.
With the exception of the HTML rendering being more primitive than the average Web browser user expects, it works quite well as a basic Web browser. However, when the user tries to take advantage of the "file protocol" to browse the local filesystem, he or she needs to be careful. If the user simply substitutes the file protocol for the HTTP protocol, thus creating a URL that starts with "file://" instead of the usual "http://", then the user will be surprised to find the error shown in Figure 34.2 popping up.