Reputation: 1002
I have a need to have a method to return Id in case of success and list of errors in case of fail. ex code snippet:
def save = {
def errors = []
if(Employee.save(flush:true)){
return Employee.id
}else{
errors.add("Can't be saved")
return errors.
}
}
In Service class ICalling Employee.save() - .. so how to check if it is error or id that save method returns
Any suggestions around would be appreciated.
Upvotes: 2
Views: 3158
Reputation: 943
I agree with Burk not to return different types, it can lead to unexpected errors. Another solution to the problem is using Java's exception handling mechanism. You can add a context field to the Exception which will hold the list of validation errors.After catching the exception you can extract the errors.
void save(Employee employee) {
// do save
// ...
// on error:
def errors = [ "terrible error nr. 5" ]
throw new ValidationException(errors)
}
try {
fooService.save(employee)
} catch(ValidationException e) {
def errors = e.erorrs
// do stuff with the errors
}
An additional advantage: When no validation error is expected, the try-catch block can be ommited in Groovy, which makes the code cleaner because you don't have to care about any validation error fields.
Upvotes: 2
Reputation: 75681
Don't do this - even if you can make it somewhat more usable with Groovy, it's a bad idea. In this case though, there are a few simple solutions. If you're just passing the Employee instance and saving it in the service method, you don't need to return anything:
void save(Employee employee) {
employee.save(flush:true)
}
This is because if it's successful, the id will be set on the instance you passed in, and if not there will be one or more validation errors in the errors
property (there's no need for you to return a generic error message when there are actually useful error messages available).
For example this would be the code you'd have in a controller calling the service:
def employee = new Employee(...)
fooService.save(employee)
if (employee.hasErrors()) {
// do something with employee.errors
}
else {
// success - use the id if you need via employee.id
}
If you want to pass in the data to create and save the new instance and return an Employee (this is the approach I usually take), it's similar:
Employee save(String name, int foo, boolean bar, ...) {
Employee employee = new Employee(name: name, foo: foo, bar: bar, ...)
employee.save(flush:true)
return employee
}
In this second case it's important to separate the save
call and the return
, since if there is a validation error save
returns null
and you want to always return a non-null instance. So do not do this:
return employee.save(flush:true)
If you separate them you can check the errors and/or the id.
Also, make sure that you do not use closures in services like you have in your code (def save = { ...
). Only methods will be transactional since the Spring transaction handling doesn't know about Groovy closures - they're just fields that Groovy calls as if they were methods, but they're not.
Upvotes: 1