2

I am using Spring's AOP feature. I have class called

class UserService {
    public User insertUserService(User user) throws PersistenceLayerException {
        System.out.println("UserServiceImpl_Two called: insertUserService method");

        if (user.id == 1) 
            throw new PersistenceLayerException();

        return null;
    }
}

Now, the calls to this method insertUserService are intercepted by an interceptor which does some validation. This validation interceptor throws a checked exception called BusinessException. Now, when this exception is thrown, Java throws an UndeclaredThrowableException because BusinessExcepetion is not declared in the throws of insertUserService. Is there a way to get around this UndeclaredThrowableException without having to declare the BusinessException in the throws clause.

The reason being there in nothing in insertUserService itself that throws a BusinessException, so its appear there should be way around.

stealthjong
  • 10,858
  • 13
  • 45
  • 84
TimeToCodeTheRoad
  • 7,032
  • 16
  • 57
  • 70

3 Answers3

1

One idea, if it's feasible, would be to make BusinessException a subclass of RuntimeException, which is more in line with Spring philosophy anyway.

EDIT:

You also asked if there's a way to do this with checked exceptions. One approach you might take is based on rethinking your UserService contract. "Services" (in the service bean sense) are usually higher level domain concepts, so it might actually be more appropriate to declare BusinessException from your UserService contract anyway. Then when there's a lower-level persistence issue, you can either wrap that with the BusinessException (if BusinessException means something generic like "the call to the business service failed"), or else just declare both BusinessException and PersistenceLayerException if you want BusinessException to have a narrow meaning (e.g. validation issues and the like).

In this case, you might be using UserService as a Spring Security UserDetailsService, which really is more persistence-oriented. If so then the thoughts above may not apply. But otherwise consider that an option.

Having said all that, making BusinessException a RuntimeException is the most consistent with Spring practice, and arguably a best practice for reasons I describe here.

Community
  • 1
  • 1
  • 1
    Agreed. Having an interceptor that throws a checked exception is probably not a good idea. Kind of defeats the idea of transparency. – NilsH Jun 25 '14 at 06:42
  • 1
    @Willie: hey, I acutaly was reading your blog Willie. I agree making it a subclass of Runtime Exception is one way, but is there any way to deal with checked exceptions? – TimeToCodeTheRoad Jun 25 '14 at 06:45
  • 1
    Small world. :-) If there is, I'm not aware of it. But I'm not an AOP expert so don't take my ignorance on the matter too seriously. :-D –  Jun 25 '14 at 06:46
  • Thanks Willie. I decided to declare both excpetions: BusinessException and Persistence Exception. I cannot make Business Exception a subclass of RuntimeException cuz its used at other places in the application and I dont want to change a core exception. – TimeToCodeTheRoad Jun 25 '14 at 07:21
1

One way I can think of (since you are saying BusinessException is checked exception), wrap your exception with the actual exception being thrown. Like below and handle it in your caller appropriately. Anyhow Wrapping Business Exception under a PersistenceException is not advisable ( Thanks to Wille for pointing it out)

throw new PersistenceLayerException(new BusinessException(..));
vinayknl
  • 1,242
  • 8
  • 18
  • -1 As this validation is happening *above* the persistence layer. It is therefore misleading to wrap it in a PersistenceLayerException. –  Jun 25 '14 at 06:44
  • Then it is not even advisable to throw any BusinessException in the first place. The answer is given based on assumption that he needs to do a Business Validation in a persistence layer. – vinayknl Jun 25 '14 at 06:46
  • You could still throw a BusinessException and then have some global handler process it (e.g. like @ControllerAdvice) that reports on the invalid object. A PersistenceLayerException ought to signify a problem coming from the persistence layer. What you are describing is really just tunneling a validation request through the declared exception. –  Jun 25 '14 at 06:49
  • Hm, thinking about your last statement more, I see your point. It's not how I would do it, but I'll remove the downvote since I can see your logic. –  Jun 25 '14 at 06:50
0

I am not familiar with Spring interceptors, but I believe the logic behind it will be pretty the same as the standard Java EE javax.interceptor.AroundInvoke:

Defines an interceptor method that interposes on business methods... AroundInvoke methods may throw any exceptions that are allowed by the throws clause of the method on which they are interposing.

So it says you should not throw a checked exception not declared by the business method that you are decorating with your interceptor.

Actually, not combining checked exceptions and AOP is quite a common practice. I perceive exception handling using AOP as a kind of an alternative paradigm to using checked exceptions.

Honza Zidek
  • 9,204
  • 4
  • 72
  • 118