0

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.

localhost
  • 43
  • 7
  • 2
    you can add an aop "when exception thrown", and handle it like that, I suppose, but then it's still thrown. why not catching it? – Stultuske Jan 26 '22 at 13:59
  • Yes, sorry to not mention it before. Yes AOP is a way to do it. Got something that someone is trying to achieve here: https://stackoverflow.com/questions/63913949/exceptionhandler-not-working-in-a-service-class But is there any simple way that we are missing here? – localhost Jan 26 '22 at 14:00
  • this is a very dumb idea, wrap the whole thing in `try { } catch(Throwable e )`. I repeat, this is extremely dumb and will catch everything, possibly making you unaware of actual issues below – tsamridh86 Jan 26 '22 at 14:07

1 Answers1

0

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

silentsudo
  • 6,730
  • 6
  • 39
  • 81
  • Yeah. This works. Also, there I got a way. I already wanted to make a @Async call to the underlying method. So, that directly works for me. Also, if I require a specific error in my case I can use Aspect. Thanks – localhost Feb 08 '22 at 11:50
  • PLease accept my answer if it solves your question. – silentsudo Feb 08 '22 at 11:54