Blog coding and discussion of coding about JavaScript, PHP, CGI, general web building etc.

Friday, January 29, 2016

Preconditions library to throw IllegalArgumentException for notNull check

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?

Answer by Chronio for Preconditions library to throw IllegalArgumentException for notNull check


You can easily do this:

if (person.getPhone() == null) {      throw new IllegalArgumentException("Can't call a person that hasn't got a phone");  }  

It is clear to other programmers what you mean, and does exactly what you want.

Answer by Captain Man for Preconditions library to throw IllegalArgumentException for notNull check


What about Preconditions's checkArgument?

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

checkArgument throws IllegalArgumentException instead of NullPointerException.

Answer by Andrew Janke for Preconditions library to throw IllegalArgumentException for notNull check


Not that I'm aware of. I'd just roll your own to get the behavior you want with a concise invocation, mimicking Guava's implementation but tweaking the exception type.

class Preconditionz {      public static  T checkNotNull(T reference, Object errorMessage) {          if (reference == null) {              throw new IllegalArgumentException(String.valueOf(errorMessage));          }          return reference;      }  }  

I like to go ahead and import static these really frequently used methods, too, so you can call them super concisely.

import static com.whatever.util.Preconditionz.checkNotNull;    // ...    public void call(Person person) {      checkNotNull(person, "person");      checkNotNull(person.getPhone(), "person.phone");      // ...  }  

Depending on your environment, you might want to name it checkNotNull2 so it's easier to add the import via autocompletion in your IDE, or let you use it alongside the standard checkNotNull.

Answer by macias for Preconditions library to throw IllegalArgumentException for notNull check


I guess I learned something again here on SO thanks to great comments by Olivier Grégoire, Louis Wasserman, CollinD and Captain Man. The standards are ussually a strong and sufficient reason as they make the common language programmers will always understand correctly, but in this particular case I had this little doubt, that maybe this rule set around NPE isn't too ok. Java is an old language and some of its features came up to be a bit unlucky (I don't want to say wrong, that's maybe too strong judgment) - like checked exceptions, although you may also disagree. Now I think that this doubt is resolved and I should:

  • Throw an IllegalArgumentException when in the particular context I can tell why the null value is wrong rather from the business perspective. For instance in the service method public void call(Person person) I know what does it mean to the system that the phone number is null.
  • Throw a NullPointerException when I just know that the null value here is wrong and will sooner or later cause a NullPointerException, but in the particular context I'm unaware what does it mean from the business perspective. The example would be Guavas immutable collections. When you build such and try to add an element of a null value it throws you a NPE. It doesn't understand what this value mean for you, it's too generic, but it just knows it's wrong here, so it decides too tell you this immediately, with some more appropriate message, so that you can recognize the problem more effectively.

Having above in mind I would say the best option to make the assertion in the public void call(Person person) example is like Captain Man suggests:

Preconditions.checkArgument(person.getPhone() != null, "msg");  

Check argument is a good name for this method - it's clear that I'm checking the business contract compliance against the person argument and it's clear that I'm expecting IllegalArgumentException if it fails. It's a better name than the Validate.isTrue of Apache Commons. Saying Validate.notNull or Preconditions.checkNotNull on the other hand suggest that I'm checking for a null reference and I'm actually expecting the NPE.

So the final answer would be - there is no such nice library and shouldn't be as this would be confusing. (And Spring Assert should be corrected).

Answer by Fritz Duchardt for Preconditions library to throw IllegalArgumentException for notNull check


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.

Answer by keyoxy for Preconditions library to throw IllegalArgumentException for notNull check


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:

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  


Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72

0 comments:

Post a Comment

Popular Posts

Powered by Blogger.