Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should Java POJO have field validation and throw exceptions in setter methods?

Let's say we have tens of java POJOs which represent my domain, that is, my data in the system which flows as objects between different layers of my system. The system may be a web application, or a simple desktop application. What the domain consists of doesn't really matter.

When designing my system, I am confused where I should put any validation logic. My POJOs ( domain objects ) represent my data, and some of the fields inside of those objects must adhere to certain criteria, but if I put a lot of validation logic inside my setter-methods, then the only way to tell the calling client is to throw an exception. And If I don't want the system to crash, the exception must be a checked exception which must be caught and handled. The consequence of that is that each and every time I create a new object using setter-methods (or even constructors), I have do either re-throw that exception or use try-catch block. It doesn't feel right to be forced to use try-catch on many setter-methods.

So the question is where I should put my validation logic, so that I don't clutter the my code with a lot of boilerplate try-catch blocks and rethrows. The finest JAVA byte eaters are welcome to join the discussion.

I have researched and googled, but not found any specific discussion on this topic, so I waiting with great enthusiasm to get some deeper insight into how things really should be done.

like image 942
Gogi Avatar asked Apr 14 '15 19:04

Gogi


People also ask

How do you validate POJO?

Suppose we have a POJO class User we need to validate. public String registerUser(@Valid User user, BindingResult result); Let's extend the User with a nested POJO Address we also need to validate. Just add @Valid annotation on address field to run validation of nested POJOs.

What is the advantage of POJO class?

The POJO class is created to use the objects in other Java Programs. The major advantage of the POJO class is that we will not have to create objects every time in other Java programs. Simply we can access the objects by using the get() and set() methods.

Can POJO class be abstract?

POJO class: This is “Plain Old Java Object” containing only private member variables and getter setter methods to access these variables. Abstract class: This class has one or more abstract methods.


3 Answers

You might have answered your own question when you said

some of the fields inside of those objects must adhere to certain criteria

It always helps to think about the invariants in your system, i.e. the things you want to maintain at all cost or the rules that must always be followed.
Your POJOs are the "last line of defence" for such invariants on your data objects and thus an appropriate - or even necessary - place to put validation logic. Without such validation, an object might no longer represent something that makes sense in your domain.

These system invariants form a contract between your objects (or methods) and their "clients". If someone is trying to use them contrary to the (hopefully well-documented) contract, throwing an exception is the right thing to do, since it is the client's responsibility to use the individual parts of the system correctly.

Over time, I've started favoring unchecked exceptions over checked ones for any instances of contract violations, partly because of the reason you mention, namely to avoid try-catch blocks everywhere.
Java's standard unchecked exceptions include:

  • NullPointerException
  • IllegalArgumentException
  • IllegalStateException
  • UnsupportedOperationException

A best practice guideline is to use checked exceptions when an error is considered recoverable and unchecked exceptions otherwise.

Chapter 9 of Joshua Bloch's "Effective Java, 2nd ed." provides more wisdom on this topic:

  • Item 57: Use exceptions only for exceptional conditions
  • Item 58: Use checked exceptions for recoverable conditions and runtime exceptions for programming errors
  • Item 59: Avoid unnecessary use of checked exceptions
  • Item 60: Favor the use of standard exceptions

None of the above should deter you from using any appropriate validation logic at higher levels, especially to enforce any context-specific business rules or constraints.

like image 177
fspinnenhirn Avatar answered Dec 05 '22 01:12

fspinnenhirn


All in all I also don't don't think there's a unique solution to fit every need, and it just comes down to your scenario and preference.

From an encapsulation point of view, I believe the setter validation is just the right way to go as it's the logical place to decide whether the provided information is correct and offer a detailed explanation on what may be wrong. However I'm not sure what you mean by:

And If I don't want the system to crash, the exception must be a checked exception...

Why would the system crash? Unchecked exceptions can be very well caught like checked ones. You need to figure out how your program should behave when such an event occurs, so you can decide where to catch them and what to do.

Checked vs unchecked has long been, and still is, debated in various ways and beliefs, but I see no reason why you should not throw an unchecked exception. Just make a common ConfigurationException (or use the already present IllegalArgumentException) or whatever floats your boat, mark your method signatures accordingly and add proper java-docs so whoever calls them knows what to expect, and throw it when required.

Depending on you object relations and hierarchy, another solution could be some builders which run you custom validations just when creating the instances. But like I said it really depends on the scenario, and you may not be able to prevent other people from manually instantiating and incorrectly populating some objects.

like image 41
Morfic Avatar answered Dec 05 '22 00:12

Morfic


In some situations the solution is to make all setters private and provide a single point of entry for initializing the objects. Then all the validation and exception handling is in that initialization method.
This also ensures that no object can be partially initialized.
Object state change can be handled this way too, by making the object immutable except through a constructor / initialization method, thou this can become wasteful if abused.

like image 37
Richard Avatar answered Dec 05 '22 02:12

Richard