1502

how to handle multiple return types in groovy Mehods?

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.

Answer1:

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.

Answer2:

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.

Recommend

  • Symfony2 Form is always empty after submitting
  • Grails Packaging and Naming Conventions
  • Single Table Inheritance in Rails 4
  • Using python to determine if a timestamp is under daylight savings time
  • NullpointerException: cannot get property on null object
  • Uploading image using SpringMVC 4.0 Multipart
  • Teradata Database 3130 Response limit exceeded?
  • Gradle test fails with NullPointerException
  • How to retrieve a specific string from a specific list from a file with JSON in Python
  • Express displaying mongodb documents in Jade
  • Passing information to server-side function in a Google Docs Add On
  • How do I check if System::Collections:ArrayList is empty / nullptr / null?
  • Creating a C++ function that calls other Lua function
  • get path to groovy source file at runtime
  • How to use function wrapper in mustache.php?
  • ASP.NET MVC Application won't update some controllers
  • Specifying Castle WCF Integration Facility Endpoint Behavior per Endpoint
  • Assign variable to the value in HTML
  • Bad request using file_get_contents for PUT request in PHP
  • Exception “firebase.functions() takes … no argument …” when specifying a region for a Cloud Function
  • Highlight and Bold text in JTextPane
  • Highlight one bar in a series in highcharts?
  • Read text file and split every line in MSBuild
  • C# - Serializing and deserializing static member
  • Is there a amazon webstore API for customers?
  • Java applet as stand-alone Windows application?
  • Statically linking a C++ library to a C# process using CLI or any other way
  • How to make Safari send if-modified-since header?
  • Calling of Constructors in a Java
  • Circular dependency while pushing http interceptor
  • PHP: When would you need the self:: keyword?
  • Android Studio and gradle
  • SQL merge duplicate rows and join values that are different
  • AngularJs get employee from factory
  • Error creating VM instance in Google Compute Engine
  • Angular 2 constructor injection vs direct access
  • EntityFramework adding new object to nested object collection
  • Checking variable from a different class in C#
  • failed to connect to specific WiFi in android programmatically
  • How can I use threading to 'tick' a timer to be accessed by other threads?