When handling a caught exception, two mandatory informations should be either logged, or present in a rethrown exception:

The following code snippet illustrates this rule:

try { /* ... */ } catch (Exception e) { LOGGER.info("context"); }         // Non-Compliant - exception is lost
try { /* ... */ } catch (Exception e) { LOGGER.info(e); }                 // Non-Compliant - context is required
try { /* ... */ } catch (Exception e) { LOGGER.info(e.getMessage()); }    // Non-Compliant - exception is lost (only message is preserved)

try { /* ... */ } catch (Exception e) { LOGGER.info("context", e); }      // Compliant

try {
  /* ... */
} catch (Exception e) {                                                   // Non-Compliant - exception is lost
  throw new RuntimeException("context");
}

try {
  /* ... */
} catch (Exception e) {                                                   // Compliant
  throw new RuntimeException("context", e);
}

When all instances of a general exception must be handled, but some specific ones not, propagation must be used. Propagation is allowed by this rule.

For example, the following code logs all Exception exceptions which are not RuntimeException. All RuntimeException exceptions are propagated.

try {
  /* ... */
} catch (RuntimeException e) {            // Compliant - propagation of the specific exception
  throw e;
} catch (Exception e) {                   // Compliant - catching of the general exception
  LOGGER.error("...", e);
}

Conversion of checked exceptions into unchecked exceptions to ease propagation of checked exceptions is also allowed by this rule.

try {
  /* ... */
} catch (IOException e) {            // Compliant - propagation of checked exception by encapsulating it into an unchecked exception
  throw new MyRuntimeException(e);
}