Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preconditions library to throw IllegalArgumentException for notNull check

Do you know some nice alternative to Apache Commons Validate or Guava Preconditions that would throw IllegalArgumentException instead of NullPointerException when checking if object is not null (except Spring Assert)?


I'm aware that Javadocs say:

Applications should throw instances of this class [NullPointerException] to indicate other illegal uses of the null object.

Nevertheless, I just don't like it. For me NPE was always meaning I just forgot to secure null reference somewhere. My eyes are so trained, I could spot it browsing logs with a speed of few pages per second and if I do there is always bug alert in my head enabled. Therefore, it would be quite confusing for me to have it thrown where I expect an IllegalArgumentException.

Say I have a bean:

public class Person {
  private String name;
  private String phone;
  //....
}

and a service method:

public void call(Person person) {
  //assert person.getPhone() != null
  //....
}

In some context it may be ok, that a person has no phone (my grandma doesn't own any). But if you'd like to call such person, for me it's calling the call method with an IllegalArgument passed. Look at the hierarchy - NullPointerException is not even a subclass of IllegalArgumentException. It basically tells you - Again you tried to call a getter on null reference.

Besides, there were discussions already and there is this nice answer I fully support. So my question is just - do I need to do ugly things like this:

Validate.isTrue(person.getPhone() != null, "Can't call a person that hasn't got a phone");

to have it my way, or is there a library that would just throw IllegalArgumentException for a notNull check?

like image 711
macias Avatar asked May 04 '15 20:05

macias


4 Answers

Since the topic of this question evolved into "Correct usage of IllegalArgumentException and NullpointerException", I would like to point out the strait forward answer in Effective Java Item 60 (second edition):

Arguably, all erroneous method invocations boil down to an illegal argument or illegal state, but other exceptions are standardly used for certain kinds of illegal arguments and states. If a caller passes null in some parameter for which null values are prohibited, convention dictates that NullPointerException be thrown rather than IllegalArgumentException. Similarly, if a caller passes an out-ofrange value in a parameter representing an index into a sequence, IndexOutOfBoundsException should be thrown rather than IllegalArgumentException.

like image 114
Fritz Duchardt Avatar answered Nov 14 '22 08:11

Fritz Duchardt


What about Preconditions's checkArgument?

public void call(Person person) {
    Preconditions.checkArgument(person.getPhone() != null);
    // cally things...
}

checkArgument throws IllegalArgumentException instead of NullPointerException.

like image 36
Captain Man Avatar answered Nov 14 '22 06:11

Captain Man


You can use valid4j with hamcrest-matchers (found on Maven Central as org.valid4j:valid4j). The 'Validation' class has support for regular input validation (i.e. throwing recoverable exceptions):

import static org.valid4j.Validation.*;

validate(argument, isValid(), otherwiseThrowing(InvalidException.class));

Links:

  • http://www.valid4j.org/
  • https://github.com/valid4j/valid4j

On a side-note: This library also has support for pre- and post-conditions (like assertions really), and it's possible to register your own customized global policy, if needed:

import static org.valid4j.Assertive.*;

require(x, greaterThan(0)); // throws RequireViolation extends AssertionError
...
ensure(r, notNullValue()); // throws EnsureViolation extends AssertionError
like image 1
keyoxy Avatar answered Nov 14 '22 06:11

keyoxy


Take a look at https://github.com/cowwoc/requirements.java/ (I'm the author). You can override the default exception type using withException() as follows:

new Verifiers().withException(IllegalArgumentException.class).requireThat(name, value).isNotNull();
like image 1
Gili Avatar answered Nov 14 '22 07:11

Gili