Blog




We recently posted that version 0.7.0 of smartics-exceptions has been released. This article motivates the ideas behind smartics Exceptions and introduces its features briefly. You may find evidence to have a closer look at this library. Hopefully … (smile)

We will first show some traditional steps in designing an exception and then show what it feels like to do it with the smartics-exceptions library. If you feel to skip the first part, jump to 64127427.

Developing an Exception in Java

Imaging you want to signal that a component has not been initialized successfully. You may write something like this:

throw new IllegalStateException();

This is quick and fast for the developer. To help our team members in the ops we opt to take some more time:

throw new IllegalStateException(
 String.format("The component '%s'"
     + " has not been initialized properly.", component));

Well, to be honest, we have some context here, we might want to add, since ops is our friend:

throw new IllegalStateException(
  String.format("The component '%s'"
      + " has not been initialized properly."
      + "This is because ... [some details follow]."
      + "The consequences are that ... [some consequences follow]."
      + "To fix this [some advices to take actions follow]."
      + "For further information,"
      + " please refer to"
      + " http://somehost//app/components/a/not-initialized.html", 
      component, some, further, context, info));

Ok, yes, I’m kidding. A developer won’t write all this exception message in the Java source. S/he would create a message bundle and put the text resources there.

Maybe someone wants to catch this exception up the stream. We should create an exception type:

public class NotInitializedException extends FaultException {
  // we have fields for: component, some, further, context, and info
 
  // we construct our message in the constructor ...
  public NotInitializedException(...) {
    super(String.format("The component '%s'"
        + " has not been initialized properly."
        + "This is because ... [some details follow]."
        + "The consequences are that ... [some consequences follow]."
        + "To fix this [some advices to take actions follow]."
        + "For further information,"
        + " please refer to"
        + " http://somehost//app/components/a/not-initialized.html", 
        component, some, further, context, info)));
    this.component = component;
    ...
  }
}

And in return simplified our throwing action:

throw new NotInitializedException(
    component, some, further, context, info);

Then one might think: “I also want those fancy exception codes, I’ve seen by libraries such as Weld!”

WELD-001408 Unsatisfied dependencies for type ...

Therefore:

public class NotInitializedException extends FaultException {
  // we have fields for: component, some, further, context, and info
 
  // we construct our message in the constructor ...
  public NotInitializedException (...) {
    super(String.format("MYCOMP-0001: The component '%s'"
        + ... [all the stuff from above]
        component, some, further, context, info)));
    this.component = component;
    ...
  }
}

Ok, the code should be a constant. So it is more visible to my fellow team members:

public class Codes {
  public static final String MYCOMP_0001 = "MYCOMP-0001";
  ...
}
 
import static ......Codes.MYCOMP_0001;
 
public class NotInitializedException extends FaultException {
  // we have fields for: component, some, further, context, and info
 
  // we construct our message in the constructor ...
  public NotInitializedException (...) {
    super(String.format(MYCOMP_0001 + ": The component '%s'"
        + ... [all the stuff from above]
        component, some, further, context, info)));
    this.component = component;
    ...
  }
}

Well, this should be documented somewhere. Set a reminder:

public class NotInitializedException extends FaultException {
  // we have fields for: component, some, further, context, and info
 
  // we construct our message in the constructor ...
  public NotInitializedException (...) {
    // FIXME: Add code to the manual and add some documentation!!!!
    super(String.format(MYCOMP_0001 + ": The component '%s'"
        + ... [all the stuff from above]
        component, some, further, context, info)));
    this.component = component;
    ...
  }
}

Developing an Exception with smartics-exceptions

Let’s start with the exception code. This time we use an enumeration (may already exist in which case we just add the new code):

public enum ComponentCode ... {
  INITIALIZATION(1),
  ...
}

And then the message bundle (which we place per naming convention in the same package as the code with the name ComponentCodeBundle.propertiessmartics-exceptions does the rest):

1.title=Initialization Problem
1=The component ''{0}'' has not been initialized properly.
1.details=This is because ... [some details follow].
1.implications=The consequences are that ... \
   [some consequences follow].
1.todo=To fix this [some advices to take actions follow].
1.url=http://somehost//app/components/a/not-initialized.html

Again, we define an exception class:

public class NotInitializedException extends FaultException {
 
  @MessageParam("0:name")
  private final Component component;
 
  public NotInitializedException(...) {
   super(..., ComponentCode.INITIALIZATION);
   this.component = component;
   ...
  }
  ...
}

And we are finally ready to throw the exception:

throw new NotInitializedException(
  component, some, further, context, info);

Done.

Reports for free

And what we get for free is this (just an example, showing a couple of codes for three components):

And an directory full of XML documents containing the information on all exception codes to be served as input to the generation process of the handbook for ops (again just an example of one code):

<?xml version="1.0"?>
<appcode>
  <id>Test/My-1000</id>
  <type>error</type>
  <component>Test/My</component>
  <implementation>
    <class>de.smartics.exceptions.sample.MyCode</class>
    <field>ZERO</field>
  </implementation>
  <short-description>The zero code</short-description>
  <package-description>Test codes.</package-description>
  <description>The zero code.</description>
  <messages>
    <message>
      <name>Title</name>
      <text>Test Exception Zero</text>
    </message>
    <message>
      <name>Summary</name>
      <text>The name is set to {name}. URL is '{url:host}:{url:port}': {cause:message}</text>
      <placeholders>
        <placeholder>
          <name>cause:message</name>
          <description>The root cause of the exception.</description>
        </placeholder>
        <placeholder>
          <name>name</name>
          <description>The name of the test exception.</description>
        </placeholder>
        <placeholder>
          <name>url:host</name>
          <description>The test URL.</description>
        </placeholder>
        <placeholder>
          <name>url:port</name>
          <description>The test URL.</description>
        </placeholder>
      </placeholders>
    </message>
    <message>
      <name>Details</name>
      <text>No details for the test.</text>
    </message>
  </messages>
</appcode>

Conclusion

We do not intend to suggest that for every exception we want to raise, we should define an exception type. Sometimes throwing an existing exception with a message text is just enough:

throw new IllegalArgumentException("The value of ... is invalid.");

But if you have to design new exception classes and there are requirements for exception codes and reporting (and some other stuff), you may want to check out the smartics Exceptions library for Java.

Enjoy!

 

 


Link

Link

Posts