Как избавиться от требования обработки исключения в Project Reactor?
В альтернативной реактивной либе RxJava обработка исключений помимо RuntimeException происходит в самом блоке, но в Project Reactor такого нет, неужели есть только один вариант это обрабатывать с поощью try/catch внутри каждого блока что бы избежать Unhandled exceptions? ниже привёл пример кода
private @NotNull Mono<JsonObject> invoke(Channel channel, Class<?> clazz, Method method, Object... args) { return Mono.fromCallable(() -> clazz.getDeclaredConstructor(Server.class, Channel.class)) .map(constructor -> constructor.newInstance(this.manager.getServer(), channel)) .flatMap(obj -> new GenericData<JsonObject>().invoke(method, obj, args)) .onErrorResume(Mono::error); } |
private @NotNull Mono<JsonObject> invoke(Channel channel, Class<?> clazz, Method method, Object... args) { return Mono.fromCallable(() -> clazz.getDeclaredConstructor(Server.class, Channel.class)) .map(constructor -> constructor.newInstance(this.manager.getServer(), channel)) .flatMap(obj -> new GenericData<JsonObject>().invoke(method, obj, args)) .onErrorResume(Mono::error); }
error: unreported exception InstantiationException; must be caught or declared to be thrown .map(constructor -> constructor.newInstance(this.manager.getServer(), channel)) |
error: unreported exception InstantiationException; must be caught or declared to be thrown .map(constructor -> constructor.newInstance(this.manager.getServer(), channel))
Дополнительно:
Тут проблема скорее в инстанцировании объекта, а не в реакторе
Ответы:
неужели есть только один вариант это обрабатывать с поощью try/catch внутри каждого блока что бы избежать Unhandled exceptions?
Вобщем-то да. Можно вынести try/catch в отдельный универсальный метод, который оборачивает исключение в RuntimeException:
private @NotNull Mono<JsonObject> invoke(Channel channel, Class<?> clazz, Method method, Object... args) { return Mono.fromCallable(() -> clazz.getDeclaredConstructor(Server.class, Channel.class)) .map(constructor -> ex(() -> constructor.newInstance(this.manager.getServer(), channel))) .flatMap(obj -> new GenericData<JsonObject>().invoke(method, obj, args)) .onErrorResume(Mono::error); } private <T> T ex(Callable<T> code) { try { return code.call(); } catch (Exception e) { throw new RuntimeException(e); } } |
private @NotNull Mono<JsonObject> invoke(Channel channel, Class<?> clazz, Method method, Object... args) { return Mono.fromCallable(() -> clazz.getDeclaredConstructor(Server.class, Channel.class)) .map(constructor -> ex(() -> constructor.newInstance(this.manager.getServer(), channel))) .flatMap(obj -> new GenericData<JsonObject>().invoke(method, obj, args)) .onErrorResume(Mono::error); } private <T> T ex(Callable<T> code) { try { return code.call(); } catch (Exception e) { throw new RuntimeException(e); } }
Конкретно в вашем примере можно вызов конструктора переместить в callable, из которого делается Mono, так как из Callable разрешено стрелять проверяемыми исключениями, в отличии от Function, который принимает map:
private @NotNull Mono<JsonObject> invoke(Channel channel, Class<?> clazz, Method method, Object... args) { return Mono.fromCallable(() -> { var constructor = clazz.getDeclaredConstructor(Server.class, Channel.class); return constructor.newInstance(this.manager.getServer(), channel); }) .flatMap(obj -> new GenericData<JsonObject>().invoke(method, obj, args)) .onErrorResume(Mono::error); } |
private @NotNull Mono<JsonObject> invoke(Channel channel, Class<?> clazz, Method method, Object... args) { return Mono.fromCallable(() -> { var constructor = clazz.getDeclaredConstructor(Server.class, Channel.class); return constructor.newInstance(this.manager.getServer(), channel); }) .flatMap(obj -> new GenericData<JsonObject>().invoke(method, obj, args)) .onErrorResume(Mono::error); }
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
Для того чтобы избавиться от требования обработки исключения в Project Reactor, можно воспользоваться методом onErrorResume(), который позволяет обработать исключение и вернуть значение по умолчанию в случае ошибки.
Пример использования метода onErrorResume() в Reactor:
Flux.just(1, 2, 3) .map(i -> { if (i == 2) { throw new RuntimeException("Oops! Something went wrong"); } return i; }) .onErrorResume(e -> Flux.just(100, 200, 300)) // обработка исключения и возврат значений по умолчанию .subscribe(System.out::println);
В данном примере, если при выполнении операции map() возникает исключение, то метод onErrorResume() обрабатывает это исключение и возвращает новый Flux с указанными значениями (100, 200, 300) вместо ошибочного значения.
Таким образом, использование метода onErrorResume() позволяет избежать необходимости обработки исключений в каждом операторе Flux'а и обеспечивает более гибкое управление ошибками в Reactor.