1

So in my Service layer I have some logic that does some stuff. Sometimes it has to check to see if something is possible before it does it OR it just has to get some OK from the front end ("Are you sure you want to do this?" kind of stuff). The front end, of course, sends a transaction to the screen to get the info.

In the past I have used RuntimeExceptions for this. I will throw a

new MessageException("are.you.sure");

and then the controller level will do a

try{
        theService.doSomething();
    }catch(MessageException me) {
        model.addAttribute(me.getMessageKey());
        result.addError(new ObjectError());
    }

In another application I made a PostOffice object and would put letters and such in it for messages. It was quite elaborate and very nice, but my new app is much smaller and I don't want all that.

So I am looking for some best practices. How do you guys send messages from the service layer to the front end? And keep in mind, I am NOT talking about Exceptions! I am just talking about messages from the service layer.

markthegrea
  • 3,731
  • 7
  • 55
  • 78
  • Just as a note: When exceptions are appropriate (and I'm not saying they are in this case), you should prefer checked to runtime, bad Spring habits notwithstanding, whenever the exception indicates a situation that is an error but is expected to happen occasionally in normal operation (that is, it's not the result of a bug like an NPE is). – chrylis -cautiouslyoptimistic- Aug 29 '13 at 15:08

1 Answers1

0

One beautiful thing about Spring MVC is the Exception handling. Since the DispatcherServlet has a try-catch(Exception) wrapping the handler method (ie. your controller method), it can catch all exceptions thrown and handle them with @ExceptionHandler methods or some other construct (there are alternatives).

What I've started doing is making my Service methods only throw RuntimeException instances (works well with @Transactional) and define all my @ExceptionHandler methods in a @ControllerAdvice annotated class. Something like:

@ControllerAdvice
public class ControllerHandler {
    private static final Logger logger = LoggerFactory.getLogger(ControllerHandler.class);

    @ExceptionHandler(value = AuthenticationException.class) 
    public String handleAuthenticationException(AuthenticationException e) {
        if (logger.isInfoEnabled()) {
            logger.info("An AuthenticationException occurred: {}", e.getMessage());
        }

        return "redirect:/";
    }

    ...more
}

@ExceptionHandler annotated methods have a few rules, but are very customizable. You can see all possibilities in the javadoc here. You should also take a look at ResponseStatus.

Personally, I rarely throw checked exceptions from my service layer. The only one that often appears is IOException (parsing JSON, opening files) and even that I like to wrap in a RuntimeException, because it's not like I can do anything special about it at that level.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • @markthegrea Before `@ControllerAdvice`, you need to put the `@ExceptionHandler` methods in the `@Controller` class where they can appear. If an exception can occur in two classes, then both classes need to declare such an `@ExceptionHandler`. – Sotirios Delimanolis Aug 29 '13 at 15:28
  • Sorry, but let me ask one more question. So you would use this architecture for things like "Are you sure?" type of interaction and not just NullPointerExceptions and such? – markthegrea Aug 29 '13 at 17:07
  • @markthegrea I wouldn't use this for `Are you sure?` because that wouldn't throw an exception. I would just use an `if-else`, returning a different page depending. – Sotirios Delimanolis Aug 29 '13 at 17:11