Reputation: 3965
I have a Grails app, and I want to know the best way to pass errors and messages from my service layer to my controller. For example, say I click a link in my app that calls a service and brings me to a new page. On that new page in my application, I want to see a list of messages like so:
Information: 10 files processed successfully.
Warning: FileA is missing CreationDate
Error: FileB failed processing
Error: FileC failed processing
Error: FileD failed processing
I know that I can create a custom object like "ServiceReturnObject" with properties like:
def data
def errors
def warnings
def information
And have all of my services return this object.
I also know that I can use exceptions, but I am not sure if that is the right solution with multiple exceptions and multiple types of exceptions.
What is the best practice here? Examples would be helpful, thanks.
Upvotes: 2
Views: 1768
Reputation: 6131
To return errors, I would create a custom exception class, and use it to wrap all other errors that a service can generate. That way, you only need to catch a limited number of exceptions. If you have more than one controller method/closure that needs to return errors, I would factor the code like this:
First, create your exception class and put it in src/java in the right namespace:
class MyException extends Exception {
protected String code; // you could make this an int if you want
public String getCode() { return code; }
public MyException(String code, String message) {
super(message);
this.code = code;
}
}
Now, in your controller, create an error-handling method and wrap all calls in it
class MyController {
def myService;
def executeSafely(Closure c) {
Map resp = [:]
try {
resp.data = c();
}
catch(MyException myEx) {
resp.error = myEx.getMessage();
resp.code = myEx.getCode();
}
catch(Exception ex) {
resp.error = 'Unexpected error: ' + ex.getMessage();
resp.code = 'foo';
}
return resp;
}
def action1 = {
def resp = executeSafely {
myService.doSomething(params);
}
render resp as JSON;
}
def action2 = {
def resp = executeSafely {
myService.doSomethingElse(params);
}
render resp as JSON;
}
}
Alternatively, you can have executeSafely
convert the response to JSON and just render that directly.
Upvotes: 1