Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: fixed compilation problems that came up as a result of last few edits and explained further

...

This noncompliant code example defines the ExceptionReporter interface:

Code Block

public interface ExceptionReporter {
  public void setExceptionReporter(ExceptionReporter er);
  public void report(Throwable exception);
}

that is implemented by the class DefaultExceptionReporter. This class is useful for reporting exceptions after filtering out any sensitive information (EXC01-J. Use a class dedicated to reporting exceptions).

The DefaultExceptionReporter constructor, prematurely publishes the this reference before construction of the object has concluded. This occurs in the last statement of the constructor (er.setExceptionReporter(this)) which sets the exception reporter. Because it is the last statement of the constructor, this may be misconstrued as benign.

Code Block
bgColor#FFcccc
// InterfaceClass ExceptionReporterDefaultExceptionReporter
public class DefaultExceptionReporter interfaceimplements ExceptionReporter {
  public void setExceptionReporter(ExceptionReporter er);
  public void report(Throwable exception);
}

// Class DefaultExceptionReporter
public class DefaultExceptionReporter implements ExceptionReporter {
  public DefaultExceptionReporter(ExceptionReporter DefaultExceptionReporter(ExceptionReporter er) {
    // Carry out initialization 
    // Incorrectly publishes the "this" reference
    er.setExceptionReporter(this);
  }

  public void report(Throwable exception) { /* default implementation */ }
}

...

Compliant Solution

Instead of publishing the this reference from the DefaultExceptionReporter constructor, this compliant solution adds a setExceptionReporter() method to DefaultExceptionReporter that is expected to can be called from a subclass, after its initialization has concluded.

Code Block
bgColor#ccccff
// Class DefaultExceptionReporter
public class DefaultExceptionReporter implements ExceptionReporter {
  public DefaultExceptionReporter(ExceptionReporter er) {
    // Carry out initialization ...
  }

  // Registers this exception reporter 
  // Should be called after constructingsubclass's ainitialization newis ExceptionReporter objectover
  public final void setExceptionReporter(ExceptionReporter er) {
    er.setExceptionReporter(this); // Registers this exception reporter 
  }

  // Implementation of report()
}

The subclass uses a setReporter() method to set the exception reporter:

Code Block
bgColor#ccccff

// Class MyExceptionReporter derives from DefaultExceptionReporter
public class MyExceptionReporter extends DefaultExceptionReporter {
  private final Logger logger;
  
  public MyExceptionReporter(ExceptionReporter er) {
    super(er); // Calls superclass's constructor
    logger = Logger.getLogger("com.organization.Log");
  }

  public void setReporter() { // Sets the exception reporter
    super.setExceptionReporter(); 
  }
}

This ensures that the reporter cannot be set before the constructor has fully initialized the subclass.

Noncompliant Code Example (inner class)

...