user1007895
user1007895

Reputation: 3965

Best way to handle errors and messages in Grails service

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

Answers (1)

Gene Golovchinsky
Gene Golovchinsky

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

Related Questions