Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 4 of 6
Listing 5.2 BadURLPost1.java
package com.javaworld.jpitfalls.article3;
import java.net.*;
import java.io.*;
public class BadURLPost1
{
public static void main(String args[])
{
// ...
try
{
// ...
System.out.println("Getting an output stream...");
OutputStream os = con.getOutputStream();
System.out.println("Getting an input stream...");
InputStream is = con.getInputStream();
// ...
} catch (Throwable t)
{
t.printStackTrace();
}
}
}
A run of Listing 5.2 produces:
E:\classes\com\javaworld\jpitfalls\article3>java -Djava.compiler=NONE com.javaworld.jpitfalls.article3.BadURLPost1 http://localhost/cgi-bin/echocgi.exe Received a : sun.net.www.protocol.http.HttpURLConnection Getting an output stream... Getting an input stream... After flushing output stream. line: <HEAD> line: <TITLE> Echo CGI program </TITLE> line: </HEAD> line: <BODY BGCOLOR='#ebebeb'><CENTER> line: <H2> Echo </H2> line: </CENTER> line: No content! ERROR! line: </BODY> line: </HTML>
Although the program compiles and runs, the CGI program reports that no data was sent! Why? The side effects of getInputStream() bite us again, causing the POST request to be sent before anything is placed in the post's output buffer, thus sending an empty POST request.
After failing twice, we understand that getInputStream() is the key method that actually writes the requests to the server. Therefore we must perform the operations serially (open
output, write, open input, read) as we do in Listing 5.3, GoodURLPost.
Listing 5.3 GoodURLPost.java
package com.javaworld.jpitfalls.article3;
import java.net.*;
import java.io.*;
public class GoodURLPost
{
public static void main(String args[])
{
// get an HTTP connection to POST to
if (args.length < 1)
{
System.out.println("USAGE: java
GOV.dia.mditds.util.GoodURLPost url");
System.exit(1);
}
try
{
// get the url as a string
String surl = args[0];
URL url = new URL(surl);
URLConnection con = url.openConnection();
System.out.println("Received a : " + con.getClass().getName());
con.setDoInput(true);
con.setDoOutput(true);
con.setUseCaches(false);
String msg = "Hi HTTP SERVER! Just a quick hello!";
con.setRequestProperty("CONTENT_LENGTH", "" + msg.length());
// Not checked
System.out.println("Msg Length: " + msg.length());
System.out.println("Getting an output stream...");
OutputStream os = con.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
osw.write(msg);
osw.flush();
osw.close();
System.out.println("After flushing output stream. ");
System.out.println("Getting an input stream...");
InputStream is = con.getInputStream();
// any response?
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ( (line = br.readLine()) != null)
{
System.out.println("line: " + line);
}
} catch (Throwable t)
{
t.printStackTrace();
}
}
}
A run of Listing 5.3 produces:
E:\classes\com\javaworld\jpitfalls\article3>java -Djava.compiler=NONE com.javaworld.jpitfalls.article3.GoodURLPost http://localhost/cgi-bin/echocgi.exe Received a : sun.net.www.protocol.http.HttpURLConnection Msg Length: 35 Getting an output stream... After flushing output stream. Getting an input stream... line: <HEAD> line: <TITLE> Echo CGI program </TITLE> line: </HEAD> line: <BODY BGCOLOR='#ebebeb'><CENTER> line: <H2> Echo </H2> line: </CENTER> line: Length of content: 35 line: Content: Hi HTTP SERVER! Just a quick hello! line: </BODY> line: </HTML>
Finally, success! We can now post data to a CGI program running on a Web server. To avoid the HTTP post pitfall, do not assume
that the methods behave as they do for a Socket. Rather, the getInputStream() method has the side effect of writing the requests to the Web server. Therefore, you must observe the proper sequence.