phil_20686
phil_20686

Reputation: 4080

Some Confusion over throwing exceptions

I have a class called Handle, which essentially manages an embedded (graph) database for a server. High up in the enterprise bean framework, there is a bean which manages this object, and exposes web services which can be called by various users/beans etc.

One of the things that this class does is validate submissions against a schema. There are a lot of possible checks. For example, if you want to create a graph in the database, it will validate your submission against the schema, and check that it is internally consistent, and do all these checks before it attempts to access the database.

Now, this validation method is ostensibly a boolean function, but in practice it never returns false, it either returns true, or throws an exception which details exactly how it failed the validation.

Now this seems like a classic case where you wouldn't usually throw an exception, because it is entirely predictable that some will fail the validation, in fact, its almost the point of doing validation.

On the other hand, if you don't throw an exception, there is no way to inform the bean calling the function, and from there, the end user, exactly why his submission failed validation. He just gets "false" back. At the moment the bean handles the exceptions and depending which one is thrown returns a short message to the user explaining exactly how it failed.

Is this a valid use of exceptions? Is there some other pattern that I should be using here?

It all works fine, but it seems like it is violating the general principals of exceptions, which is that they should be rare and refer to unpredictable behaviour.

Upvotes: 2

Views: 86

Answers (3)

Ralf Wagner
Ralf Wagner

Reputation: 1517

I wouldn't use exceptions for this situation, as a failing validation is an excepted outcome.

As you need to transport more information than a simple ok/not ok, I'd use a validate method that returns an Enumeration ValidationStatus where each enum value corresponds to one of the Exceptions that are currently thrown or an object ValidationResult consisting of the enumeration and additional information to fix the problem:

public enum ValidationStatus {
  SUCCESS, ERROR1, ERROR2
}

public class ValidationResult {

    private ValidationStatus status;
    private String errorMessage;

    public ValidationResult(ValidationStatus status, String errorMessage) {
        this.status = status;
        this.errorMessage = errorMessage;
    }

    public boolean isValid() {
        return status == ValidationStatus.SUCCESS;
    }

    public ValidationStatus getStatus() {
        return status;
    }

    public String getErrorMessage() {
        return errorMessage;
    }
}

I suppose that creating these ValidationResults can occur at the same places as the exceptions are currently thrown.

Upvotes: 1

Kraiss
Kraiss

Reputation: 999

I think it depends on how you want to treat a "failure" :

  1. If you just want to know if something is valid, then you better use a method that just return true or false (like Pattern.matches or Object.equals)

  2. If the end user 'knows' how works the method (or the system), you better use an enum, an object representing the result, or even a special attribute in the object you return. As instance :

    • Product getProduct(Integer id) {} that return null if the product dosen't exist
    • The HTTP header that contain a code representing the answer of the request (200, 404, ...)
  3. If your end user don't 'know' the system and you want to force him to treat the problem because it can lead to an unsafe state, you better use a method like you use currently. It isn't classy but it's safe.

    Boolean myMethod () throws ExceptionFailure1, ExceptionFailure2, ... {...}
    

Upvotes: 1

Eran
Eran

Reputation: 393821

We have two validation methods for each class :

One throws an exception if the instance is invalid, but doesn't have a return value :

void validate () throws SomeException;

The other returns a boolean that indicates if the instance is valid, and doesn't throw any exception.

boolean isValid ();

I suggest you use one of these schemes. Either one makes more sense than a method that returns boolean and throws an exception when the instance is invalid.

Upvotes: 1

Related Questions