Как централизовать обработку исключений в нескольких методах API - PullRequest
5 голосов
/ 08 мая 2019

Это простой вопрос по Java 8+, фреймворки не используются.

Мы производим API для более высокого уровня, который относится к уровню представления среди других видов деятельности. У нас есть интерфейс и интерфейс, согласованный с приглашающим, поэтому они рады получить некоторые исключения, которые мы выбрасываем.

В то же время мы также используем другие API по тому же соглашению, поэтому мы можем сами что-то делать и генерировать исключения, или мы можем вызывать другие API, которые генерируют согласованные исключения. В настоящее время мы ничего не делаем с исключениями, которые вызываются вызываемыми нами API.

Дело в том, что в этой инфраструктуре мы находимся в лучшем положении, чтобы справляться с промежуточными действиями, в то время как создаются исключения, поэтому нам необходимо зафиксировать как наши исключения, так и исключения, предоставляемые теми, кого мы вызываем; в основном, сообщая о проблеме, поднимая системные элементы управления и т. д., а затем повторно выбрасывая исходное исключение, чтобы верхний слой оставался прежним.

У нас есть около 300 методов в классе точки входа нашего API:

public void method1 (arguments for method 1) {
...
}

...

public void method300 (arguments for method 300) {
...
}

Я четко понимаю, что могу создать метод для централизации действий, которые необходимо выполнить в управлении исключениями, что-то вроде:

public void myExceptionHandler (Exception e) {
    if (e instanceOf X) {
    } else if ...
    ...
    throw particularExceptionAccordingTheCase 
}

Но я бы также не стал изменять эти 300 методов.

Есть идеи, как внедрить try-catch в этих 300 методах, чтобы отправить исключение myExceptionHandler, не добавляя try-catch в каждый из них?

Любые комментарии и идеи очень ценятся!

----------- После предложения mprev0 -------------------------------

Я попробовал этот подход. Это действительно перехватывает исключение и так далее, но я не могу повторно вызвать исключение: я вынужден его перехватить, но это противоречит требованию пересылки исключения обратно на верхний уровень. Хотя я могу выдать ошибку, я получил ошибку компилятора в строке throw new FileNotFoundException ();

public class myExceptionHandler implements Thread.UncaughtExceptionHandler {

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        System.out.println("gotcha!");
        if (e instanceof java.lang.Error) {
            System.out.println("AAT-CORE: Fatal Error");
            throw new java.lang.Error(e.getCause());

        } else if (e instanceof java.lang.Exception) {
            System.out.println("AAT-CORE: Exception Error");
            throw new FileNotFoundException();
        }
    }

}

Есть идеи?

------------ После еще нескольких копаний, исправлено с помощью шаблона декоратора -------

Предыдущая реализация класса не работает, так как я не могу изменить сигнатуру метода, и мне нужно повторно выдать исключение java.lang.Exception.

Использование декоратора и обработка интерфейса делает свое дело. Как итог:

Класс верхнего слоя:

public class TopLayer {
    public static void main (String[] args) {
        MiddleLayer m = new MiddleLayer();
        m.method1();
    }
}

Класс нижнего слоя содержит определенные API и некоторую реализацию, единственное, что интересно, это то, что он содержит неконтролируемые java.lang.Exception, ожидая, что верхний слой выполнит эту работу. Но мы работаем в середине, и мы сделаем эту работу:

public class MiddleLayer extends BottomLayer {

    public MiddleLayer () {
        final UncaughtExceptionHandler subclass = Thread.currentThread().getUncaughtExceptionHandler();
        Thread.currentThread().setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread thread, Throwable ex) {

                System.out.println("gotcha2!");
                // carry on with prior flow
                subclass.uncaughtException(thread, ex);
            }
        });

    }

}

Таким образом, я могу получить system.out, а исключение java.lang.Exception распространяется на верхний слой.

Отсюда пришло вдохновение декоратора: Rethrow UncaughtExceptionHandler Исключение после регистрации

Дополнительные комментарии приветствуются!

Ответы [ 3 ]

4 голосов
/ 08 мая 2019

Вы можете решить эту проблему с помощью интерфейса java.lang.Thread.UncaughtExceptionHandler :

public class MyExceptionHandler implements Thread.UncaughtExceptionHandler {

    @Overrides
    public void uncaughtException(Thread t, Throwable e) {
            if (e instanceOf X) {
            } else if ...
            ...
            throw particularExceptionAccordingTheCase 
    }
}

Затем вы связываете его со всеми потоками следующим образом:

Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler())

Это настроит обработчик исключений для обработки всех необработанных исключений в всех потоках вашего приложения.

Обратите внимание, что это будет работать только для исключений, которые еще не были явно обработаны где-то в вашем коде, и если нет никакого другого обработчика, настроенного для какого-то конкретного потока (обработчик необработанных исключений также может быть установлен для некоторого определенного потока).

РЕДАКТИРОВАТЬ: Как обнаружил @JBC, вышеупомянутый подход не будет работать для проверенных исключений , так как мы вынуждены явно их ловить в нашем методе uncaughtException (обратите внимание, что мы не может добавить предложение throws в переопределенный метод ). Хотя он будет работать без проблем, если мы только хотим перебросить подтипы RuntimeException и Ошибка , требуется небольшая адаптация, если мы хотим, чтобы это работало - вы можете найти это объяснил в вопросе @ JBC.

0 голосов
/ 12 мая 2019

Как видно из обновлений вопросов, окончательное решение представляет собой комбинацию двух разных подходов, с одной стороны, с использованием подхода mprev0 для реализации java.lang.Thread.UncaughtExceptionHandler и, кроме того, добавленияШаблон декорации, чтобы можно было повторно генерировать исключение во время выполнения.

Дополнительных подходов пока не было, поэтому я закрываю вопрос и приведу его как наиболее полный ответ.

Более подробную информацию о UncaughtExceptionHandler можно найти в документации по Java, но, как всегда, здесь мало примеров, и здесь: Расширенная обработка исключений Thread.UncaughtExceptionHandler Example

Дополнительную информацию об использовании шаблонов Decorator можно найти здесь: Шаблон проектирования Decorator в Java Шаблоны проектирования - Pattern Decorator

А как использовать для управления исключениями здесь: Rethrow UncaughtExceptionHandler Исключение после регистрации

0 голосов
/ 09 мая 2019

Вы также можете создать прокси-API поверх вашего текущего API, иметь метод обработчика вызова в прокси и поместить этот метод в блок try try.

https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/proxy.html

https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Proxy.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...