Difference between revisions of "Java Exception Handling"

From MPDLMediaWiki
Jump to navigation Jump to search
Line 53: Line 53:
== Conclusion ==
== Conclusion ==
=== Distinguish between repairable exceptions and errors ===
=== Distinguish between repairable exceptions and errors ===
Decide whether your module is able to fix the exception (take default values, look somewhere else, try again, ...) or not.
Decide whether your module is able to fix the exception (take default values, look somewhere else, try again, ...) or not.


=== Prefer unchecked exceptions inside a module ===
=== Only catch repairable exceptions ===
* If an exception is somehow repairable, try this in the catch-block
* If the repairing is critical in some respect, at least log a warning message (e.g. logger.warn("Value for xyz not found, taking default value"))
* If repairing fails treat the exception as an error


=== Only catch repairable exceptions ===
=== Inside a module, prefer unchecked exceptions ===
Turn checked exceptions from third-party modules into unchecked exceptions, e.g.
<code>
    private void myMethod()
        try
        {
            connection.executeStatement(sql);
        }
        catch (SQLException sqle)
        {
            throw new RuntimeException("Error executing statement '" + sql + "'", sqle);
        }
    }
</code>


=== Inside a module, always throw errors up as they are ===
=== Inside a module, always throw errors up as they are (alternatively) ===
Do not care for exceptions at all, just declare them to be thrown, e.g.
<code>
    private void myMethod() throws SQLException
        connection.executeStatement(sql);
    }
</code>


=== When catching exceptions, log appropriately ===
=== When catching exceptions, log appropriately ===

Revision as of 10:13, 3 November 2008

Problem description[edit]

Modules need dependencies of other modules only because of their exception classes[edit]

From validation/ItemValidating:

   String validateItemXml(final String itemXml) throws
           ValidationSchemaNotFoundException,
           TechnicalException;

From importmanager/ImportHandler:

   byte[] doFetch(String sourceName, String identifier) throws FileNotFoundException, 
           IdentifierNotRecognisedException, 
           SourceNotAvailableException, 
           TechnicalException,
           FormatNotRecognizedException;

Stacktraces are sometimes swallowed[edit]

   try 
   {
       ...					
   } 
   catch (MalformedURLException e) 
   {LOGGER.error("Error when replacing regex in fetching URL"); e.printStackTrace(); }
   catch(UnsupportedEncodingException e)
   {e.printStackTrace();}

   try 
   {
       ...					
   } 
   catch (JiBXException e) 
   {
       e.getCause();
   }

Sometimes, excessive stacktraces are shown, even without useful information[edit]

Example from coreservices: File:Exception1.txt

Logger.error, System.out and e.printStackTrace are mixed up happily[edit]

see above

No distinction between exceptions and errors/checked and unchecked exceptions[edit]

Compare Exception and Error

Conclusion[edit]

Distinguish between repairable exceptions and errors[edit]

Decide whether your module is able to fix the exception (take default values, look somewhere else, try again, ...) or not.

Only catch repairable exceptions[edit]

  • If an exception is somehow repairable, try this in the catch-block
  • If the repairing is critical in some respect, at least log a warning message (e.g. logger.warn("Value for xyz not found, taking default value"))
  • If repairing fails treat the exception as an error

Inside a module, prefer unchecked exceptions[edit]

Turn checked exceptions from third-party modules into unchecked exceptions, e.g.

   private void myMethod()
       try
       {
           connection.executeStatement(sql);
       }
       catch (SQLException sqle)
       {
           throw new RuntimeException("Error executing statement '" + sql + "'", sqle);
       }
   }

Inside a module, always throw errors up as they are (alternatively)[edit]

Do not care for exceptions at all, just declare them to be thrown, e.g.

   private void myMethod() throws SQLException
       connection.executeStatement(sql);
   }

When catching exceptions, log appropriately[edit]

  • use log4j, not System.out
  • use the two-argument methods:
    • logger.error("Error geting server.name property", ex);
    • logger.error("Error geting server.name property"); --> Exception information is lost
    • logger.error(ex); --> Only ex.toString() is logged, other exception information is lost

Do not throw self-defined exceptions without a surplus[edit]

If the exception name is the only gain a self-defined exception brings (e.g. IncorrectArxivIdException), a generic Exception given an appropriate message is better (e.g. new IllegalArgumentException("Incorrect arXiv id " + arxivId))

Between modules, throw only generic exceptions[edit]

e.g. IllegalArgumentException, IllegalStateException, RuntimeException

Links[edit]