I’ve learned from the latest Java developments, that throwing a RuntimeException and handling it the aspect-oriented ways is the current trend in error handling on the service layer. That means, if anything goes wrong, you just throw a RuntimeException or even better, let the Bean Validation do the magic.
Advantage is: You don’t clog up your code with try-catch and if(entity.getName() == nil) checks. Everything is checked in the background which makes your code much more readable.
So I’m wondering, how this would be done in Grails? Sure, if I use .save(failOnError:true), I get a nice ValidationException. But this leads to a very unpleasant default error page which does not improve the usability of the web application at all.
Do I still have to put it in a try-catch block on Controller level? Let’s say the EntityService has a method, which looks like this:
def toggleSomething(String entityId) = {
if(!someOtherPrerequisite) {
throw new EntityException("SomeOtherPrerequisite was not satisfied") // extends RuntimeException
}
Entity entity = Entity.get(entityId)
entity.someProperty = somePropertyValue
entity.save(failOnError:true) // throws a ValidationException
}
Then the controller would do call it like so:
def toggle = {
try {
entityService.toggleSomething(params.id)
}
catch(e) {
flashHelper.error 'I'm sorry, something went wrong.'
}
}
But this seems to be pretty old school when Grails is so new school in so many things. Isn’t there a way to handle RuntimeExceptions a little nicer without clogging up the code with try-catch?
The pattern I follow is:
If the errors can be wrapped up inside a Grails Domain, then don’t deal directly with exception handling. If your service method is primarily dealing with your grails domains, then when there is an error, they wind up in the domain.errors collection. In the controller, just check for those errors (hasErrors()). Since under the covers a RuntimeException is thrown anyway, your transaction is rolled back, no harm, no foul.
If you’re dealing with a 3rd party library (possibly an external web service or such) then don’t be scared of exceptions. Just because Grails (Groovy) doesn’t require you to handle them, they are still good to have / use.
Sometimes neither of the above apply and maybe your service method should just return some true or false flag as to the result of some logic. To take your example, for example:
Service
Controller
Unfortunately, there is probably no solid right or wrong way to approach this. So expect different answers than mine.