So I have a working example of an advice that should run after an exception is thrown with a specific annotation above it. So ExtendedErrorHandling is the annotation used above a class and/or method. When that method returns a specific error of type ExtendedHttpResponseException, the advice should run.
However, the original idea was to do this without annotations.
AS-IS:
@AfterThrowing(pointcut = "execution(* *(..)) && (extendedThrowingInMethod() || extendedThrowingInClass())", throwing = "ex")
TO-BE:
@AfterThrowing(pointcut = "execution(* *(..))", throwing = "ex")
When we try to achieve this, spring refuses to start, with a very generic error message "tomcat could not startup", but also hinting that the advice isn't ok.
The error:
Caused by: org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:142)
at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.<init>(TomcatWebServer.java:104)
at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getTomcatWebServer(TomcatServletWebServerFactory.java:473)
at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:206)
at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory$$FastClassBySpringCGLIB$$9c83fa9f.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:64)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698)
at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory$$EnhancerBySpringCGLIB$$78134ef1.getWebServer(<generated>)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:182)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:160)
... 78 more
Caused by: java.lang.IllegalStateException: StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[] failed to start
at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.rethrowDeferredStartupExceptions(TomcatWebServer.java:187)
at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:126)
... 96 more
The aspect completely:
@Aspect
@Component
public class ExtendedHttpResponseExceptionCatcherAdvisor {
@Pointcut("@annotation(com.atlascopco.common.dto.handlers.annotations.ExtendedErrorHandling)")
public void extendedThrowingInMethod() {
}
@Pointcut("@within(com.atlascopco.common.dto.handlers.annotations.ExtendedErrorHandling)")
public void extendedThrowingInClass() {
}
@AfterThrowing(pointcut = "execution(* *(..)) && (extendedThrowingInMethod() || extendedThrowingInClass())", throwing = "ex")
public void handleThrownKnownExceptions(ExtendedHttpResponseException ex) {
ResponseContext responseContext = ResponseContextHolder.getResponseContext();
GenericHttpResponseModel responseModel = responseContext.getResponseModel();
responseModel.getErrors().add(ex);
responseContext.setResponseModel(responseModel);
}
}
So the questions here are: Why does spring crash in the TO-BE situation? And is it possible to achieve the TO-BE situation without any problems, or do we run against some limitations?
Thanks for your help in advance!
Thanks to @R.G.
The solution is to be more specific when it comes to class definition. EG:
execution(* com.your.project..*(..))