Download (direct link):
I IK) A Java survey - Netscape
> 1 > > 1
| if) t Ä Java survey
A Silly Java Survey
Please enter your name and answer the question.
L Use submit to send your results.
NAME: |BiH Gates
Do you love Java prograiitmiiig? <• Yes Ñ No
Submit your vote | Clear form |
@ Î Ä Document: Done (0.12 secs)
Figure 17.2 HTML Form to test echocgi.exe.
When Posting to a URL Won't 131
I® Echo CGI program - Netscape ØØØ1
> I» Li
t?) 1 Echo CGI program ?
11 Length of content 32 Content: theName=BiU+Gates&questionl=Yes
© Q Ë Document: Done (0.2 secs)
Figure 17.3 HTML response from echocgi.exe.
01 /** BadURLPost.java */
02 03 package org.javapitfalls.item17;
04 import java.net.*;
05 06 import java.io.*;
07 public class BadURLPost
09 public static void main(String args)
11 // get an HTTP connection to POST to
12 if (args.length < 1)
14 System.out.println("USAGE: java 2
16 17 }
20 // get the url as a string
21 String surl = args;
22 URL url = new URL(surl);
24 URLConnection con = url.openConnection();
25 System.out.println("Received a : " + 2
Listing 17.2 BadURLPost.java (continued)
132 Item 17
31 String msg = "Hi HTTP SERVER! Just a quick hello!";
32 con.setRequestProperty("CONTENT_LENGTH", "5"); // Not 2
33 con.setRequestProperty("Stupid", "Nonsense");
35 System.out.println("Getting an input stream...");
36 InputStream is = con.getInputStream();
38 System.out.println("Getting an output stream...");
39 OutputStream os = con.getOutputStream();
42 con.setRequestProperty("CONTENT_LENGTH", "" + 2
43 Illegal access error - can't reset method.
46 OutputStreamWriter osw = new OutputStreamWriter(os);
48 /** REMEMBER THIS osw.flush(); **/
52 System.out.println("After flushing output stream. ");
54 // any response?
55 InputStreamReader isr = new InputStreamReader(is);
56 BufferedReader br = new BufferedReader(isr);
57 String line = null;
59 while ( (line = br.readLine()) != null)
61 System.out.println("line: " + line);
63 } catch (Throwable t)
Listing 17.2 (continued)
When Posting to a URL Won't 133
A run of Listing 17.2 produces the following:
org.javapitfalls.item17.BadURLPost http://localhost/cgi-bin/echocgi.exe ^
Received a : sun.net.www.protocol.http.HttpURLConnection
Getting an input stream...
Getting an output stream...
java.net.ProtocolException: Cannot write output after reading input.
When trying to get the output stream of the HttpURLConnection class, the program informed me that I cannot write output after reading input. The strange thing about this error message is that we have not tried to read any data yet. Of course, that assumes the getInputStream()method behaves in the same manner as in other IO classes. Specifically, there are three problems with the above code:
¦¦ The setRequestProperty() method parameters are not checked. This is demonstrated by setting a property called "stupid" with a value of "nonsense." Since these properties actually go into the HTTP request and they are not validated by the method (as they should be), you must be extra careful to ensure the parameter names and values are correct.
¦¦ The getOutputStream() method causes the program to throw a
ProtocolException with the error message "Can't write output after reading input." By examining the JDK source code, we find that this is due to the getInputStream() method having the side effect of sending the request (whose default request method is "GET") to the Web server. As an aside, this is similar to a side effect in the ObjectInputStream and ObjectOutput-Stream constructors that are detailed in my first pitfalls book. So, the pitfall is the assumption that the getInputStream() and getOutputStream() methods behave just like they do for a Socket connection. Since the underlying mechanism for communicating to the Web server actually is a socket, this is not an unreasonable assumption. A better implementation of HttpURLConnection would be to postpone the side effects until the initial read or write to the respective input or output stream. This could be done by creating an HttpInputStream and HttpOutputStream. That would keep the socket metaphor intact. One could argue that HTTP is a request/response stateless protocol and the socket metaphor does not fit. The answer to that is that the API should fit the conceptual model. If the current model is identical to a socket connection, it should behave as such. If it does not, you have stretched the bounds of abstraction too far.