Return-Path: <env_33831229-769574691@hermes.sun.com>
Received: from po10.mit.edu (po10.mit.edu [18.7.21.66])
	by po10.mit.edu (Cyrus v2.1.5) with LMTP; Tue, 22 Apr 2003 20:53:50 -0400
X-Sieve: CMU Sieve 2.2
Received: from pacific-carrier-annex.mit.edu by po10.mit.edu (8.12.4/4.7) id h3N0rmKB017447; Tue, 22 Apr 2003 20:53:48 -0400 (EDT)
Received: from hermes.sun.com (hermes.sun.com [64.124.140.169])
	by pacific-carrier-annex.mit.edu (8.12.4/8.9.2) with SMTP id h3N0rmFW023857
	for <alexp@mit.edu>; Tue, 22 Apr 2003 20:53:48 -0400 (EDT)
Date: 22 Apr 2003 16:16:44 -0800
From: "JDC Tech Tips" <sunmail@hermes.sun.com>
To: alexp@mit.edu
Message-Id: <33831229-769574691@hermes.sun.com>
Subject: Core Java Technologies Tech Tips, April 22, 2003 (Validating URL Links, Reusing Exceptions)
Mime-Version: 1.0
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
X-Mailer: SunMail 1.0
X-Spam-Score: 2.2
X-Spam-Level: ** (2.2)
X-Spam-Flag: NO
X-Scanned-By: MIMEDefang 2.28 (www . roaringpenguin . com / mimedefang)

<!DOCtype HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Core Java Technologies Technical Tips</title>

<style type="text/css">

code {color: #333333; font-family: verdana, courier, monospace; font-size: 10pt}
pre {color: #333333; font-family: verdana, courier, monospace; font-size: 10pt}
body, div, span {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
td, th {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
tr {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
table {font-family: arial, helvetica, sans-serif; font-size: 10pt}
p {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
li {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
br {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
div {color: #666699; font-family: arial, helvetica, sans-serif; font-size: 10pt}
sup {font-family: arial, helvetica, sans-serif; font-size: 5pt}
h3 {color: #666699; font-family: arial, helvetica, sans-serif; font-size: 11pt}
h4, b {color: #666699; font-family: arial, helvetica, sans-serif; font-size: 10pt}
blockquote, input, select {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
ul, ol {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
a:link {font-size: 10pt; font-family: arial, helvetica, sans-serif; color:#666699 }
span.purple {font-weight: bold; color: #666699; font-family: arial, helvetica, sans-serif; font-size: 10pt}
span.small {font-size: 8pt; font-family: arial, helvetica, sans-serif; color:#333333 }
span.link {font-size: 8pt; font-family: arial, helvetica, sans-serif; color:#666699 }
</style>

</head>

<body bgcolor="#ffffff">
<a name="top"></a>
<table border="0" cellpadding="0" cellspacing="0" width="611">
<tr>
<td colspan="3" bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt="."></td>
</tr>

<tr>
<td bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt="."></td>

<td>
<table border="0" cellpadding="0" cellspacing="0" width="611">
<tr>
<td colspan="2"><a href="http://developer.java.sun.com"><img src="http://developer.java.sun.com/images/headers/core_ttips_hdr.jpg" width="611" height="160" alt="Core Java Technologies Technical Tips" border="0"></a></td>
</tr>

<tr>
<td colspan="2" bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt="."></td>
</tr>

<!-- ================== -->
<!-- Start Main Content -->
<!-- ================== -->

<tr>
<td height="20">&nbsp;&nbsp;&nbsp;<a href="http://bulkmail2.sun.com/CTServlet?id=1051052892269" style="text-decoration:none;">View this issue as simple text</a></td>
<td align="right" height="20"><span class="purple">April 22, 2003</span>&nbsp;&nbsp;&nbsp;&nbsp;</td>
</tr>

<tr><td colspan="2">

<table border="0" cellpadding="10" cellspacing="0" width="100%">
<tr>
<td>
     
<form method="get" action="http://search.java.sun.com/search/java/">   
<table border="0" cellpadding="3" cellspacing="0" width="100%">
<tr> 
<td align="left" valign="middle" width="20%"><h3>In this Issue</h3></td>
              
<td valign="middle" align="right" width="70%">
<font size="2">
<input type="text" size="15" maxlength="128" name="qt"></font></td>
            
<td valign="middle" width="55">
<input type="image" src="http://developer.java.sun.com/images/v4a_search.gif" alt="Search" value="search" border="0" width="55"></td>
</tr>
</table>
</form>

<p>
Welcome to the Core Java Technologies Tech Tips, April 22, 2003. Here you'll get tips on using core Java technologies and APIs, such as those in Java 2 Platform, Standard Edition (J2SE).
</p>

<p>
This issue covers:
</p>

<p>
<a href="#1"><img src="http://developer.java.sun.com/images/anchor.gif" border="0" alt=".">Validating URL Links</a>
<br>    
<a href="#2"><img src="http://developer.java.sun.com/images/anchor.gif" border="0" alt=".">Reusing Exceptions</a>
</p>

<p>
These tips were developed using Java 2 SDK, Standard Edition, v 1.4. 
</p>

<p>
This issue of the Core Java Technologies Tech Tips is written by John Zukowski, president of <a href="http://www.jzventures.com">JZ Ventures, Inc.</a>
</p>

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>
</table> 

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>
</table> 

<!-- Grey Horizontal Line ends Here -->

<a name="1"></a>

<h3>VALIDATING URL LINKS</h3>

<p>
A frequent problem that web site maintainers have is making sure that links on a site remain valid. Sometimes a resource that is the target of a link is removed. For example, consider links to technical articles. Over time, these articles can get out of date, and so are sometimes removed. After a resource like this is dropped, any link to it is no longer valid. Validating these links, especially links to resources on other sites, can keep an entire team of people busy, so automating the process can save a lot of time. The following tip presents a programmatic technique for validating URL links. Specifically, it presents a program that checks the response codes for all the foreign URLs on a web page, and then generates a report. The report has more information than simply the status of a link. It also include things like what a redirected URL actually points to, so you can use the report to update the web page.
</p>

<p>
If you've used the Web at all, it's likely that you've encountered the dreaded 404 error. This means that the target of a link on a web page, that is, a destination page, is not found. The 404 in the error is a response code, one of the many response codes covered in the HTTP protocol defined by the <a href="http://www.w3.org/Protocols/">World Wide Web Consortium (W3C)</a>. Page 40 of <a href="ftp://ftp.isi.edu/in-notes/rfc2616.txt">RFC 2616</a> shows the complete list of response codes.
</p>

<p>    
There are three classes in the <code>java.net</code> package that are useful in checking the response code for a URL link: <code>URL</code>, <code>URLConnection</code>, and <code>HttpURLConnection</code>. The <code>URL</code> class allows you to create a <code>URL</code> object for an <code>http/https</code> string. (You can create <code>URL</code>s for other protocols such as ftp, but the response code is only valid for HTTP connections). The <code>URLConnection</code> class gives you a way to find out the response code associated with a specific <code>URL</code>. The <code>HttpURLConnection</code> class is a <code>URLConnection</code> for HTTP requests (a sister class, <code>HttpsURLConnection</code> is for HTTPS requests).
</p>

<p>
To get a <code>URLConnection</code> for a URL, you open a connection on a <code>URL</code> object using the <code>openConnection</code> method. This gives you the connection object, but it doesn't yet make the connection to the <code>URL</code>. This gives you the option to configure the connection in some special way, for instance, you can set any special header fields. To make the connection to the object associated with the URL, you call the <code>connect</code> method. To check the response code you, have to call the <code>getResponseCode()</code> method. By default, <code>HttpURLConnection</code> uses the <code>HTTP</code> <code>GET</code> method when retrieving an object. This means the actual contents of the object are returned. You should read the data from the input stream, and then close the stream when finished. This avoids the possibility of leaving the connection hanging, with the data only partially read.
</p>

<p>
Here's what a simple check for the response code associated with a URL looks like:
</p>

<pre>
    import java.net.*;
    import java.io.*;

    public class SimpleURLCheck {

      public static void main(String args[]) {
        if (args.length == 0) {
          System.err.println
            (&quot;Please provide a URL to check&quot;);
        } else {
          String urlString = args[0];
          try {
            URL url = new URL(urlString);
            URLConnection connection = 
            url.openConnection();
            if (connection instanceof HttpURLConnection) {
              HttpURLConnection httpConnection = 
                 (HttpURLConnection)connection;
              httpConnection.connect();
              int response = 
                 httpConnection.getResponseCode();
              System.out.println(
                 &quot;Response: &quot; + response);
              InputStream is = 
                httpConnection.getInputStream();
              byte[] buffer = new byte [256];
              while (is.read (buffer) != -1) {}
              is.close();
            }
          } catch (IOException e) {
            e.printStackTrace();
          }
        }
      }
   }
</pre>

<p>
If you run the program with the URL <code>http://java.sun.com/jdc/</code>: 
</p>

<pre>
	java SimpleURLCheck http://java.sun.com/jdc/
</pre>

<p>
it should return a response code of 200. 
</p>

<p>
Note that if you're behind a firewall, you need to set the <code>proxyHost</code> and <code>proxyPort</code> properties as appropriate for your proxy. In other words, you need to add code in the program that looks something like this:
</p>

<pre>
    Properties prop = System.getProperties(); 
    prop.put(&quot;http.proxyHost&quot;,&quot;your-proxy-host-name&quot;);
    prop.put(&quot;http.proxyPort&quot;,&quot;your-proxy-port-number&quot;);
</pre>

<p>
There's a specific reason why <code>http://java.sun.com/jdc/</code> was picked as the URL. If you enter that URL in the browser you'll notice that the browser gets redirected to <code>http://developer.java.sun.com/developer/</code>. The browser then loads the page to which it is redirected. It is that page that loads without problem, and so the browser sends back a response code of 200 (or <code>HttpURLConnection.HTTP_OK</code>).
</p>

<p>
Why doesn't <code>HttpURLConnection</code> report that this is a redirected URL? By default, <code>HttpURLConnection</code> will follow redirected URLs. If you want to find out if a URL redirects, you have to turn off the default behavior. You can do this either for all <code>HttpURLConnection</code> objects by using the <code>setFollowRedirects</code> method. Or you can turn off the default behavior for a specific <code>HttpURLConnection</code> by using the <code>setInstanceFollowRedirects</code> method. In either case, providing an argument of false turns off the automatic redirect behavior. You can test this, by adding the line:
</p>

<pre>
    HttpURLConnection.setFollowRedirects(false);
</pre>

<p>
to the <code>SimpleURLCheck</code> program. If you rerun the program:
</p>

<pre>
    java SimpleURLCheck http://java.sun.com/jdc/
</pre>

<p> 
the response code should be 301.
</p>

<p>
The 301 error code means that the URL has moved permanently (by comparison, a response code of 302 represents a temporary redirect). That means that if the original URL was saved, a smart application could update the saved URL by getting the target of the URL redirect. To get that redirected URL, you need to retrieve the <code>Location</code> header of the <code>HttpURLConnection</code>. You do this with the <code>getHeaderField</code> method.
</p>

<p>
Here's the <code>SimpleURLCheck</code> program with <code>setFollowRedirects</code> and <code>getHeaderField</code> methods added:
</p>

<pre>
    import java.net.*;
    import java.io.*;

    public class SimpleURLCheck {

      public static void main(String args[]) {
        if (args.length == 0) {
          System.err.println(
              &quot;Please provide a URL to check&quot;);
        } else {
          HttpURLConnection.setFollowRedirects(false);
          String urlString = args[0];
          try {
            URL url = new URL(urlString);
            URLConnection connection = 
              url.openConnection();
            if (connection instanceof HttpURLConnection) {
              HttpURLConnection httpConnection = 
               (HttpURLConnection)connection;
              httpConnection.connect();
              int response = 
               httpConnection.getResponseCode();
              System.out.println(&quot;Response: &quot; + response);
              String location =          
               httpConnection.getHeaderField(&quot;Location&quot;);
              if (location != null) {
                System.out.println(
                 &quot;Location: &quot; + location);
              }
              InputStream is = 
                httpConnection.getInputStream();
              byte[] buffer = new byte [256];
              while (is.read (buffer) != -1) {}
              is.close();
            }
          } catch (IOException e) {
            e.printStackTrace();
          }
        }
      }
    }
</pre>

<p>
Now, when you run the application with a URL of <code>http://java.sun.com/jdc/:</code>
</p>

<pre>
    java SimpleURLCheck http://java.sun.com/jdc/
</pre>

<p>
it should produce the following results:
</p>

<pre>
    Response: 301
    Location: http://developer.java.sun.com/developer/
</pre>

<p>
The check even works for https URLs (the following command should be entered on one line):
</p>

<pre>
   java SimpleURLCheck 
   https://www.madonotcall.govconnect.com/
</pre>

<p>    
should produce the following results:
</p>

<pre> 
   Response: 302
   Location: cookiestest.asp  
</pre>

<p>
Remember to add proxy settings if you're behind a firewall, that is, for <code>https.proxyHost</code> and <code>https.proxyPort</code>.
</p>

<p>
Notice that this particular site runs a quick cookie test. If you rerun the program with the new URL, appending <code>cookiestest.asp</code> to end of first URL, you would see the redirection (again, the following command goes on one line):
</p>

<pre>
    java SimpleURLCheck 
    https://www.madonotcall.govconnect.com/cookiestest.asp
    
    Response: 302
    Location: cookies_error.htm
</pre>

<p>
Of course, this little command-line program doesn't support cookies, so the web site redirects to an error page. Had the URL been entered into a browser, the response would have been a redirect to <code>https://www.madonotcall.govconnect.com/Welcome.asp</code>.
</p>

<p>
Yet another thing to add to the link checker program is a smarter way to check status codes. Because the program doesn't care what the content actually is, you can set the request method to <code>HEAD</code> in the request. This setting specifies that the request is only for the heading of the response, not the actual data. By default, an <code>HTTP</code> request is a <code>GET</code> request -- in this case, everything is embedded in the URL. You can make a <code>HEAD</code> request for the <code>HttpURLConnection</code> by specifying <code>setRequestMethod(&quot;HEAD&quot;)</code>. For example, you can add the following line to the <code>SimpleURLCheck</code> program:
</p>

<pre>
   httpConnection.setRequestMethod(&quot;HEAD&quot;);
</pre>

<p>
Instead of showing the full program again here, you'll see the <code>setRequestMethod</code> method in use in the enhanced URL check report 
later.
</p>

<p>
Unlike <code>setFollowsRedirects</code>, which you can specify to cover all connections, <code>setRequestMethod</code> needs to be specified for each connection.  
</p>

<p>
With the <code>SimpleURLCheck</code> program, you are able to check a single URL at a time. By moving the checking code to a method, and automating the scanning for URLs from a web page, you can generate a report on the validity of the URLs. The report can also track redirects, in other words, to where the URLs have been pointed. In this case, it is not necessary to have code that gets the <code>InputStream</code>, reads the data, and then closes the stream. However, there is no problem if you leave that code in the program -- the read returns -1 immediately.
</p>

<p>
An earlier Tech Tip tip titled &quot;<a href="http://bulkmail2.sun.com/CTServlet?id=1051052892130">Extracting Links from an HTML File</a>&quot; presented a program that fetches URLs from a web page. You can combine that program with the <code>SimpleURLCheck</code> program to generate the link check report.
</p>

<p>
For a simple report, let's just print out error codes for each page (and redirect URLs for those that have one). To understand the report, you need to understand the range of response codes for HTTP requests. Going back to RFC 2616, you'll notice the following categories of response codes:
</p>

<pre>
    1xx - informational
    2xx - successful
    3xx - redirection
    4xx - error
    5xx - server error
</pre>

<p>
If you were to generate a smarter report, you could ignore the web pages that generate error codes in the 100 and 200 range. You could report the rest as errors. Another way to make the report smarter is to also check internal links, not just external ones. And, if you want the program to be truly smart, you might want to ignore errors like redirecting <code>http://sun.com</code> to <code>http://www.sun.com/</code>, or at least flag them differently. Another enhancement, though a tricky one, is automating the tagging of URLs with session information, such as when you visit a URL like <code>http://www.networksolutions.com/</code>.
</p>

<p>
Here's what the enhanced URL check program looks like. 
</p>

<pre>
    import java.io.*;
    import java.net.*;
    import javax.swing.text.*;
    import javax.swing.text.html.*;

    class EnhancedURLCheck {
      public static void main(String[] args) {
        HttpURLConnection.setFollowRedirects(false);
        EditorKit kit = new HTMLEditorKit();
        Document doc = kit.createDefaultDocument();

        // The Document class does not yet 
        // handle charset's properly.
        doc.putProperty(&quot;IgnoreCharsetDirective&quot;, 
          Boolean.TRUE);

        try {

          // Create a reader on the HTML content.
          Reader rd = getReader(args[0]);

          // Parse the HTML.
          kit.read(rd, doc, 0);

          // Iterate through the elements 
          // of the HTML document.
          ElementIterator it = new ElementIterator(doc);
          javax.swing.text.Element elem;
          while ((elem = it.next()) != null) {
            SimpleAttributeSet s = (SimpleAttributeSet)
              elem.getAttributes().getAttribute(
                HTML.Tag.A);
            if (s != null) {
              validateHref(
                (String)s.getAttribute(
                  HTML.Attribute.HREF));
            }
          }
        } catch (Exception e) {
          e.printStackTrace();
        }
        System.exit(1);
      }
   
    // Returns a reader on the HTML data. If 'uri' begins
    // with &quot;http:&quot;, it's treated as a URL; otherwise,
    // it's assumed to be a local filename.
      static Reader getReader(String uri) 
        throws IOException {
        if (uri.startsWith(&quot;http:&quot;)) {

    // Retrieve from Internet.
          URLConnection conn = 
            new URL(uri).openConnection();
          return new 
            InputStreamReader(conn.getInputStream());
        } else {

    // Retrieve from file.
          return new FileReader(uri);
    }
  }

      private static void validateHref(String urlString) {
        if ((urlString != null) &amp;&amp; 
         urlString.startsWith(&quot;http://&quot;)) {
          try {
            URL url = new URL(urlString);
            URLConnection connection = 
              url.openConnection();
            if (connection instanceof HttpURLConnection) {
              HttpURLConnection httpConnection = 
                (HttpURLConnection)connection;
              httpConnection.setRequestMethod(&quot;HEAD&quot;);
              httpConnection.connect();
              int response = 
                httpConnection.getResponseCode();
              System.out.println(&quot;[&quot; + response + &quot;]&quot; + 
                urlString);
              String location = 
                httpConnection.getHeaderField(&quot;Location&quot;);
              if (location != null) {
                System.out.println(
                  &quot;Location: &quot; + location);
              }
          System.out.println();
            }
          } catch (IOException e) {
            e.printStackTrace();
          }
        }
      }
    }
</pre>

<p>
If you run the report on the <code>http://java.sun page:</code> 
</p>

<pre>
    java EnhancedURLCheck http://java.sun.com
</pre>

<p>
it should produce output similar to the following (only the first few lines of the output are shown):
</p>

<pre>
    [200]http://java.sun.com/

    [200]http://search.java.sun.com/search/java/
    advanced.jsp

    [200]http://java.sun.com/

    [302]http://servlet.java.sun.com/logRedirect/
    frontpage-nav/http://java.sun.com/products/
    Location: http://java.sun.com/products/

    [302]http://servlet.java.sun.com/logRedirect/
    frontpage-nav/http://java.sun.com/j2ee/Location: 
    http://java.sun.com/j2ee/
</pre>

<p>    
For more information about using URLs, see the lesson &quot;<a href="http://bulkmail2.sun.com/CTServlet?id=1051052892152">Working with URLs</a>&quot; in the Java Tutorial. Also see the lesson &quot;<a href="http://bulkmail2.sun.com/CTServlet?id=1051052892163">Reading from and Writing to a URLConnection</a>&quot;. 
</p>

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">
<tr>
<td>
<div align="right">
<a href="#top">back to top<img src="http://developer.java.sun.com/images/back_to_top.gif" border="0" alt="image"></a>
</div>
</td>
</tr>

<tr>
<td bgcolor="#ffffff" height="2"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>
</table> 

<!-- Grey Horizontal Line ends Here -->

<a name="2"></a>

<h3>REUSING EXCEPTIONS</h3>

<p>
When an exceptional condition occurs in a program, it's typical to throw an exception. The syntax for throwing an exception often looks something like this:
</p>

<pre>
  throw new MyException(&quot;String&quot;);
</pre> 

<p>  
Literally, you create the exception when the exceptional condition happens, and immediately throw it to the caller (or to some enclosing try-catch block).
</p>

<p>
If you print a stack trace at that point with <code>printStackTrace()</code>,
the information you see is filled with the details of the stack at the time the exception was created. This might sound obvious. However, if you want to avoid creating new objects when an exception occurs, you can create the exception once, and reuse it when the exceptional condition reoccurs. A common design pattern for this is called a Singleton. You can create the object the first time you need it, and then keep reusing the same object. For example:
</p>

<pre>
    MyObject myObject = null;

    private synchronized MyObject getMyObject() {
      if (myObject == null) {
        myObject = new MyObject();
      }
      return myObject;
    }     
</pre>

<p>
What happens if you use a pattern similar to this with an <code>Exception</code> object (or in fact anything that subclasses <code>java.lang.Throwable</code>)? In this case, the stack trace is filled with the trace from when the exception was created. Typically, that isn't what you want because you probably want to see the exact trace for each exception, that is, when each exception happened. In order to share exception objects in this way, you have to refill the stack trace for the new stack when the exception happens. The method of <code>Throwable</code> to do this is <code>fillInStackTrace</code>.
</p>

<p>
Here's what the <code>getMyObject</code> pattern looks like after adjusting it to work with exception objects:
</p>

<pre>
    MyExceptionObject myExceptionObject = null;
  
    private synchronized MyExceptionObject 
      getMyExceptionObject() {
      if (myExceptionObject == null) {
        myExceptionObject = new MyExceptionObject();
      } else {
        myExceptionObject.fillInStackTrace();
      }
      return myExceptionObject;
    }
</pre>

<p>  
Notice that you don't have to fill in the stack manually the first time. It's done for you. You only have to fill in the stack for subsequent occurrences.
</p>

<p>
At this point, you might ask why you would want to reuse exception objects. One reason to reuse (or even just pre-create) exception objects is to minimize the number of objects created when an exception actually happens. Of course, filling the stack does take resources, so this isn't completely free of the need for memory resources. And, if you truly don't need the stack trace, this pattern allows you to not bother filling it.
</p>

<p>
To demonstrate this behavior, the following program shows two ways of reusing exception objects. For each approach, the exception is printed three times. In the first case, the same stack is shown three times, even though three different methods print the trace. The latter case demonstrates the difference in each stack when you refill the stack trace with each call.
</p>

<pre>
    import java.io.*;

    public class ReuseException {

        IOException exception1 = null;

        private synchronized IOException 
          getException1() {
            if (exception1 == null) {
                exception1 = new IOException();
            }
            return exception1;
        }

        IOException exception2 = null;

        private synchronized IOException 
          getException2() {
            if (exception2 == null) {
                exception2 = new IOException();
            } else {
                exception2.fillInStackTrace();
            }
            return exception2;
        }

        void exception1Method1() {
            getException1().printStackTrace();
        }

        void exception1Method2() {
            getException1().printStackTrace();
        }

        void exception1Method3() {
            getException1().printStackTrace();
        }

        void exception2Method1() {
            getException2().printStackTrace();
        }

        void exception2Method2() {
            getException2().printStackTrace();
        }

        void exception2Method3() {
            getException2().printStackTrace();
        }

        public static void main(String[] args) {
            ReuseException reuse = 
              new ReuseException();
            reuse.exception1Method1();
            reuse.exception1Method2();
            reuse.exception1Method3();
            System.out.println(&quot;---&quot;);
            reuse.exception2Method1();
            reuse.exception2Method2();
            reuse.exception2Method3();
        }
    }
</pre>

<p>
When you run the program, your output should look something like this:
</p>

<pre>
    java.io.IOException
        at ReuseException.getException1
        (ReuseException.java:9)
        at ReuseException.exception1Method1
        (ReuseException.java:26)
        at ReuseException.main
        (ReuseException.java:51)
    java.io.IOException
        at ReuseException.getException1
        (ReuseException.java:9)
        at ReuseException.exception1Method1
        (ReuseException.java:26)
        at ReuseException.main
        (ReuseException.java:51)
    java.io.IOException
        at ReuseException.getException1
        (ReuseException.java:9)
        at ReuseException.exception1Method1
        (ReuseException.java:26)
        at ReuseException.main
        (ReuseException.java:51)
---
    java.io.IOException
        at ReuseException.getException2
        (ReuseException.java:18)
        at ReuseException.exception2Method1
        (ReuseException.java:38)
        at ReuseException.main
        (ReuseException.java:55)
    java.io.IOException
        at ReuseException.getException2
        (ReuseException.java:20)
        at ReuseException.exception2Method2
        (ReuseException.java:42)
        at ReuseException.main
        (ReuseException.java:56)
    java.io.IOException
        at ReuseException.getException2
        (ReuseException.java:20)
        at ReuseException.exception2Method3
        (ReuseException.java:46)
        at ReuseException.main
        (ReuseException.java:57)        
</pre>

<p>
For more information about working with exceptions, see the lesson &quot;<a href="http://bulkmail2.sun.com/CTServlet?id=1051052892179">Handling Errors with Exceptions</a>&quot; in the Java Tutorial. Also see the documentation for the <a href="http://bulkmail2.sun.com/CTServlet?id=1051052892192">Throwable class</a>.
</p>

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">

<tr>
<td>
<div align="right">
<a href="#top">back to top<img src="http://developer.java.sun.com/images/back_to_top.gif" border="0" alt="image"></a>
</div>
</td></tr>

<tr><td bgcolor="#ffffff" height="2"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td></tr>

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>
</table> 

<!-- Grey Horizontal Line ends Here -->

<form method="POST" action="http://developer.java.sun.com/servlet/jdc.survey.TabulationServlet">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td bgcolor="#ffffff" height="2"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td></tr>

<tr><td>
<h3>Reader Feedback</h3> 

<input type="hidden" name="survey_id" value="2600">
<input type="hidden" name="anonymous" value="True">
<input type="hidden" name="answer_count" value="3">
<input type="hidden" name="answer1" value="MarCore_tt042203">
<input name="answer2" type="radio" value="2">&nbsp; Very worth reading&nbsp; 
<input name="answer2" type="radio" value="1">&nbsp; Worth reading&nbsp; 
<input name="answer2" type="radio" value="0">&nbsp; Not worth reading&nbsp; 
 
<p>
If you have other comments or ideas for future technical tips, please type them  here: 
</p>
 
<p>
<textarea name="answer3" rows="6" cols="50"></textarea> 
</p>
 
<p>
<input type="Submit" value="Submit"> &nbsp; <input type="Reset"> 
</p>

<p> 
Have a question about Java programming? Use  
<a href="http://bulkmail2.sun.com/CTServlet?id=1051052892285">Java Online Support.</a> 
</p>

</td></tr></table>
</form> 

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">
<tr>
<td>
<div align="right">
<a href="#top">back to top<img src="http://developer.java.sun.com/images/back_to_top.gif" border="0" alt="image"></a>
</div>
</td></tr>

<tr><td bgcolor="#ffffff" height="2"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td></tr>

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>
</table> 

<!-- Grey Horizontal Line ends Here -->

<br>

<span class="small">IMPORTANT: Please read our Terms of Use, Privacy, and Licensing policies:<br>
<a href="http://www.sun.com/share/text/termsofuse.html"><span class="link">http://www.sun.com/share/text/termsofuse.html</span></a><br>
<a href="http://www.sun.com/privacy/"><span class="link">http://www.sun.com/privacy/</span></a><br> 
<a href="http://developer.java.sun.com/berkeley_license.html"><span class="link">http://developer.java.sun.com/berkeley_license.html</span></a>
</span><br><br>


<span class="small">
Comments? Send your feedback on the Core Java Technologies Tech Tips to: <a href="mailto:jdc-webmaster@sun.com"><span class="link">jdc-webmaster@sun.com</span></a>
</span><br><br>

<span class="small">
Subscribe to other Java developer Tech Tips:
</span><br><br>

<span class="small">
- Enterprise Java Technologies Tech Tips. Get tips on using enterprise Java technologies and APIs, such as those in the Java 2 Platform, Enterprise Edition (J2EE).<br>
- Wireless Developer Tech Tips. Get tips on using wireless Java technologies and APIs, such as those in the Java 2 Platform, Micro Edition (J2ME).<br><br>
</span>
   
<span class="small">
To subscribe to these and other JDC publications:<br>
- Go to the JDC Newsletters and Publications page, choose the newsletters you want to <a href="http://bulkmail2.sun.com/CTServlet?id=1051052892205"><span class="link">subscribe</span></a> to and click &quot;Update&quot;.<br>
  - To unsubscribe, go to the <a href="http://bulkmail2.sun.com/CTServlet?id=1051052892205"><span class="link">subscriptions page</span></a>, uncheck the appropriate checkbox, and click &quot;Update&quot;.
</span><br><br>

<span class="small">ARCHIVES: You'll find the Core Java Technologies Tech Tips archives at:<br>
<a href="http://bulkmail2.sun.com/CTServlet?id=1051052892298"><span class="link">http://java.sun.com/jdc/TechTips/index.html</span></a>
</span><br><br>

<span class="small">Copyright 2003 <a href="http://www.sun.com"><span class="link">Sun Microsystems, Inc.</span></a> All rights reserved.
<br>4150 Network Circle, Santa Clara, CA 95054 USA.
</span><br><br>

<span class="small">This document is protected by copyright. For more information, see:
<br><a href="http://java.sun.com/jdc/copyright.html"><span class="link">http://java.sun.com/jdc/copyright.html</span></a>
</span><br><br>

<span class="small">Java, J2SE, J2EE, J2ME, and all Java-based marks are trademarks or registered trademarks (<a href="http://bulkmail2.sun.com/CTServlet?id=1051052892239"><span class="link">http://www.sun.com/suntrademarks/</span></a>) of Sun Microsystems, Inc. in the United States and other countries.<br><br>

<!-- ================ -->
<!-- End Main Content -->
<!-- ================ -->

<center>
<a href="http://www.sun.com"><img src="http://developer.java.sun.com/images/lgsun.gif" border="0" alt="Sun Microsystems, Inc."></a>
</center>

</td>
</tr>
</table>

</td></tr>
</table>
</td>

<td bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt="."></td>
</tr>
<tr>
<td colspan="3" bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt="."></td>
</tr>
</table>

<table bgcolor = "#efefef"><tr><td><a href="http://subscriptions.sun.com/unsubscribe?33831229-769574691">Please unsubscribe me from this newsletter.</a><img src="http://bulkmail2.sun.com/OTServlet?id=33831229-769574691" width=1 height=1></td></tr></table></body>
</html>

