Issue
I have a notification service(I have control of this class).
If there is any unchecked exception, then I do not want to throw it. But instead want to log it in a specific manner.
I can directly have try catch block in each method's implementation but I am in search of some magic here 😄
Is there a common way that this can be handled through Spring?
Update: AOP is also a way to do it. For example: https://dzone.com/articles/handling-exceptions-using-springs-aop Any other direct implementation for this?
This was my requirement but I was not able to find anything with respect to this.
Solution
I faced similar issues when dealing with calling multiple apis from rest service, where i was suppose to provide a fallback implementation when error occured. My Aspect
was more than what i am giving example here.
Service
@Service
public class SuspiciousService {
final Random random = new Random();
public String beSuspicious() {
final boolean value = random.nextBoolean();
if (value) {
throw new IllegalStateException("Exception occured for: " + value);
}
return "I am not suspicious";
}
}
Sample service which randomly throws an error.
Controller
@RestController
@RequestMapping("/is-suspicious")
@AllArgsConstructor
public class SampleController {
private final SuspiciousService suspiciousService;
@GetMapping
public Map<String, String> get() {
return Map.of("isSuspicious", suspiciousService.beSuspicious());
}
}
Controller which invokes this service.
Finally, Around Aspect
catches this exception and provides the sample response.
@Aspect
@Component
@Order(2)
public class AspectAroundSuspiciousService {
@Around("execution(* in.silentsudo.sprintbootresttemplate.SuspiciousService.beSuspicious(..))")
public Object parallelExecuteBeforeAndAfterCompose(ProceedingJoinPoint point) throws Throwable {
try {
return point.proceed();
} catch (RuntimeException re) {
return "Yes, I am suspicious";
}
}
}
The other approach is if you are using ByteBuddy, you can add annotation to the method throwing exception
@Advice.OnMethodExit(onThrowable = RuntimeException.class)
and have an ExceptionHandler to cath this
@ExceptionHandler
private String suspiciousRuntimeException(RuntimeException exception) {
return "Yes, I am suspicious from ex handler, error: " + exception.getMessage();
}
I choose aspect over bytebuddy for simple reason as i was handling ladder of api exception, where as this implementation will catch in general RuntimeException happenning from service#method
Answered By - silentsudo
Answer Checked By - Pedro (JavaFixing Volunteer)