Создатель этой ошибки не указал reason что это

Уровень сложности
Простой

Время на прочтение
7 мин

Количество просмотров 3.9K

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

Статья может быть полезна для новичков или тем, кто не так давно в мире Java. В ней мы не касаемся типов исключений, а рассматриваем создание собственных.

Зачем нужны собственные исключения?

Этот вопрос может возникнуть у тех кто только входит в ИТ, и вопрос даже вполне корректный, ведь имеется масса своих исключений, но собственные исключения позволяют разработчикам более гибко управлять ошибками и обрабатывать их в соответствии с требованиями конкретного приложения. Вот несколько причин, по которым собственные исключения в Java могут быть полезны:

1. Отражение специфических ситуаций: Собственные исключения могут быть созданы для отображения конкретных ошибок или ситуаций, которые могут возникнуть в приложении. Например, вы можете создать исключение InvalidInputException, чтобы указать, что получен недопустимый ввод от пользователя.

2. Локализация и обработка ошибок: Собственные исключения позволяют локализовать и обрабатывать ошибки на определенном уровне в коде. Каждое исключение может быть обработано отдельно, что упрощает отладку и обработку ошибок.

3. Гибкая обработка и восстановление: При использовании собственных исключений вы можете предоставить гибкую обработку ошибок, включая восстановление после ошибки или выполнение альтернативных действий. Например, вы можете перехватить исключение FileNotFoundException и попробовать открыть альтернативный файл.

4. Инкапсуляция ошибок: Собственные исключения позволяют инкапсулировать информацию об ошибке и передавать ее на более высокий уровень в коде. Это помогает упростить код и улучшить его читаемость, так как обработка ошибок может быть сосредоточена в одном месте.

5. Расширение стандартных исключений: Собственные исключения могут расширять стандартные исключения Java, такие как Exception или RuntimeException, чтобы добавить дополнительную информацию или функциональность при обработке ошибок. Например, вы можете создать исключение DatabaseException, которое расширяет Exception и содержит дополнительные методы для работы с базой данных.

Примеры создания собственных исключений

Пример 1

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

public class InvalidInputException extends Exception {
    public InvalidInputException(String message) {
        super(message);
    }
}

В этом примере класс InvalidInputException расширяет класс Exception и имеет конструктор, который принимает сообщение об ошибке в качестве параметра. В конструкторе вызывается конструктор суперкласса Exception, передавая ему сообщение.

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

public class Example {
    public static void main(String[] args) {
        try {
            validateInput("abc");
        } catch (InvalidInputException e) {
            System.out.println("Invalid input: " + e.getMessage());
        }
    }

    public static void validateInput(String input) throws InvalidInputException {
        if (input == null || input.isEmpty()) {
            throw new InvalidInputException("Input cannot be null or empty");
        }
    }
}

В этом примере метод validateInput() проверяет, является ли входная строка пустой или равной null. Если это так, то метод выбрасывает исключение InvalidInputException с сообщением. В методе main() мы вызываем validateInput() с недопустимым вводом и перехватываем исключение с помощью блока catch, где выводим сообщение об ошибке.

Пример 2

// Создаем собственное исключение
class CustomException extends Exception {
    public CustomException(String message) {
        super(message);
    }
}

// Класс, который использует собственное исключение
class Example {
    // Метод, который может выбросить собственное исключение
    public static void doSomething(int value) throws CustomException {
        if (value < 0) {
            throw new CustomException("Значение должно быть больше или равно нулю");
        }
    }

    public static void main(String[] args) {
        try {
            // Вызываем метод, который может выбросить исключение
            doSomething(-5);
        } catch (CustomException e) {
            // Обрабатываем исключение
            System.out.println("Ошибка: " + e.getMessage());
        }
    }
}

В этом примере у нас есть метод doSomething, который может выбросить собственное исключение CustomException, если значение аргумента меньше нуля. В методе main мы вызываем этот метод с отрицательным значением и перехватываем исключение с помощью блока catch. Затем мы выводим сообщение об ошибке.

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

Пример 3

// Создаем собственное исключение
class InvalidEmailException extends Exception {
    public InvalidEmailException(String message) {
        super(message);
    }
}

// Класс, который использует собственное исключение
class EmailValidator {
    // Метод, который может выбросить собственное исключение
    public static void validateEmail(String email) throws InvalidEmailException {
        if (!email.contains("@")) {
            throw new InvalidEmailException("Некорректный адрес электронной почты");
        }
    }

    public static void main(String[] args) {
        try {
            // Вызываем метод, который может выбросить исключение
            validateEmail("example.com");
        } catch (InvalidEmailException e) {
            // Обрабатываем исключение
            System.out.println("Ошибка: " + e.getMessage());
        }
    }
}

В этом примере у нас есть метод validateEmail, который может выбросить собственное исключение InvalidEmailException, если переданный адрес электронной почты не содержит символа «@». В конструкторе исключения мы передаем сообщение об ошибке. В методе main мы вызываем этот метод с некорректным адресом электронной почты и перехватываем исключение с помощью блока catch. Затем мы выводим сообщение об ошибке.

Вот вроде бы и все, достаточно легко и просто, как всегда, есть одно большое но! можно создать исключения, которые только усложнят жизнь разработку

Пример 4 (некорректное создание исключений)

// Некорректное создание собственного исключения
class MyException extends Exception {
    public MyException() {
        super();
    }
}

В этом примере мы создаем собственное исключение MyException, но не передаем ему сообщение об ошибке через конструктор. Это может привести к непонятным или неинформативным сообщениям об ошибках при перехвате исключения.

Корректным подходом будет передача сообщения об ошибке через конструктор, как показано в предыдущем примере:

class MyException extends Exception {
    public MyException(String message) {
        super(message);
    }
}

Таким образом, при выбрасывании и перехвате исключения MyException будет доступно информативное сообщение об ошибке.

Пример 5 (некорректное использование)

Примером неправильного использования собственного исключения может быть его применение без реальной необходимости или создание избыточных иерархий исключений.

public class MyCustomException extends Exception {
    // ...
}

public class Example {
    public static void main(String[] args) {
        try {
            throw new MyCustomException();
        } catch (MyCustomException e) {
            System.out.println("Caught MyCustomException");
        } catch (Exception e) {
            System.out.println("Caught Exception");
        }
    }
}

В этом примере мы создаем собственное исключение MyCustomException, но в блоке catch обрабатываем его так же, как и любое другое исключение Exception. Такое использование собственного исключения делает его бессмысленным, поскольку нет никакой разницы между обработкой MyCustomException и обработкой любого другого исключения.

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

Плюсы создания собственных исключений:

1. Отражение специфических ситуаций: Собственные исключения позволяют точно отражать конкретные ошибки или ситуации, которые могут возникнуть в вашем приложении. Это упрощает понимание и обработку ошибок другими разработчиками, которые работают с вашим кодом.

2. Гибкая обработка и восстановление: Использование собственных исключений позволяет предоставить гибкую обработку ошибок, включая восстановление после ошибки или выполнение альтернативных действий. Это помогает повысить надежность и стабильность вашего приложения.

3. Инкапсуляция информации об ошибке: Собственные исключения позволяют инкапсулировать информацию об ошибке, включая дополнительные детали или контекст ошибки. Это помогает упростить код и улучшить его читаемость, так как обработка ошибок может быть сосредоточена в одном месте.

4. Расширение стандартных исключений: Вы можете расширять стандартные исключения Java, такие как Exception или RuntimeException, с добавлением дополнительной функциональности или информации для обработки ошибок. Это позволяет вам более точно определить тип ошибки и предоставить дополнительные методы для работы с ней.

Минусы создания собственных исключений:

1. Усложнение кода: Создание собственных исключений может привести к усложнению кода, особенно если их необходимо обрабатывать на разных уровнях в приложении. Слишком много разных исключений может сделать код сложным для чтения и понимания.

2. Переусиление иерархии исключений: Если неправильно спроектировать иерархию собственных исключений, это может привести к избыточности или неправильной обработке ошибок. Следует тщательно продумать, какие исключения создавать и как они связаны между собой.

3. Неоднозначность исключений: Если вы создаете собственные исключения, которые перекрывают или имеют схожие имена с существующими стандартными исключениями, это может вызывать путаницу при обработке ошибок. Разработчики могут испытывать трудности в определении, какое исключение выбрать для обработки конкретной ситуации.

4. Проблемы совместимости: Если вы используете собственные исключения в библиотеке или API, это может создать проблемы совместимости, если другие разработчики не знакомы с вашими исключениями или не знают, как с ними работать.

Заключение

Собственные исключения в Java предоставляют разработчикам возможность более гибко управлять ошибками и исключительными ситуациями в своих приложениях или библиотеках. Они позволяют отразить специфические ситуации, локализовать и обработать ошибки, предоставить гибкую обработку и восстановление, инкапсулировать ошибки и расширить стандартные исключения.

У меня есть следующий код в службе WCF, чтобы вызвать пользовательскую ошибку, основанную на определенных ситуациях. Я получаю исключение «Создатель этой ошибки не определял причину». Что я делаю неправильно?

//source code
if(!DidItPass)
{
    InvalidRoutingCodeFault fault = new InvalidRoutingCodeFault("Invalid Routing Code - No Approval Started");
    throw new FaultException<InvalidRoutingCodeFault>(fault);
}

//operation contract
[OperationContract]
[FaultContract(typeof(InvalidRoutingCodeFault))]
bool MyMethod();

//data contract
[DataContract(Namespace="http://myuri.org/Simple")]
public class InvalidRoutingCodeFault
{
    private string m_ErrorMessage = string.Empty;

    public InvalidRoutingCodeFault(string message)
    {
        this.m_ErrorMessage = message;
    }

    [DataMember]
    public string ErrorMessage
    {
        get { return this.m_ErrorMessage; }
        set { this.m_ErrorMessage = value; }
    }
}

4b9b3361

Ответ 1

После некоторых дополнительных исследований работал следующий модифицированный код:

if(!DidItPass)
{    
    InvalidRoutingCodeFault fault = new InvalidRoutingCodeFault("Invalid Routing Code - No Approval Started");    
    throw new FaultException<InvalidRoutingCodeFault>(fault, new FaultReason("Invalid Routing Code - No Approval Started"));
}

Ответ 2

Короткий ответ: вы ничего не делаете неправильно, просто неправильно читаете результаты.

На стороне клиента, когда вы поймаете ошибку, то, что поймано, имеет тип System.ServiceModel.FaultException<InvalidRoutingCodeFault>.
Ваш объект InvalidRoutingCodeFault фактически находится в свойстве .detail исключения FaultException. SO….

//код клиента

private static void InvokeMyMethod() 
{ 
    ServiceClient service = new MyService.ServiceClient(); 

    try 
    { 
        service.MyMethod(); 
    } 
    catch (System.ServiceModel.FaultException<InvalidRoutingCodeFault> ex) 
    { 
        // This will output the "Message" property of the System.ServiceModel.FaultException
        // 'The creator of this fault did not specify a Reason' if not specified when thrown
        Console.WriteLine("faultException Message: " + ex.Message);    
        // This will output the ErrorMessage property of your InvalidRoutingCodeFault type
        Console.WriteLine("InvalidRoutingCodeFault Message: " + ex.Detail.ErrorMessage);    
    } 
}

Свойство Message для FaultException — это то, что отображается на странице ошибки, поэтому, если оно не заполнено, как в столбце Джона Эгертона, вы увидите сообщение «Создатель этой ошибки не указал сообщение» Причина «. Чтобы легко заполнить его, используйте два конструктора параметров при вызове ошибки в службе следующим образом, передав сообщение об ошибке из вашего типа ошибки:

InvalidRoutingCodeFault fault = new InvalidRoutingCodeFault("Invalid Routing Code - No Approval Started");                                          
throw new FaultException<InvalidRoutingCodeFault>(fault, new FaultReason(fault.ErrorMessage));                                      

Ответ 3

serviceDebug includeExceptionDetailInFaults="true"

НЕ является решением

Следующий код работает даже с serviceDebug includeExceptionDetailInFaults="false"

// data contract 

[DataContract]
public class FormatFault
{
    private string additionalDetails;

    [DataMember]
    public string AdditionalDetails
    {
        get { return additionalDetails; }
        set { additionalDetails = value; }
    }
}

// interface method declaration

    [OperationContract]
    [FaultContract(typeof(FormatFault))]
    void DoWork2();

// service method implementation

    public void DoWork2()
    {
        try
        {
            int i = int.Parse("Abcd");
        }
        catch (FormatException ex)
        {
            FormatFault fault = new FormatFault();
            fault.AdditionalDetails = ex.Message;
            throw new FaultException<FormatFault>(fault);
        }
    }

// client calling code

    private static void InvokeWCF2()
    {
        ServiceClient service = new ServiceClient();

        try
        {
            service.DoWork2();
        }
        catch (FaultException<FormatFault> e)
        {
            // This is a strongly typed try catch instead of the weakly typed where we need to do -- if (e.Code.Name == "Format_Error")
            Console.WriteLine("Handling format exception: " + e.Detail.AdditionalDetails);   
        }
    }

Нет необходимости добавлять причину ошибки, если она не требуется. Просто убедитесь, что атрибут FaultContract верен.

Ответ 4

Я решил эту проблему, используя два конструктора параметров.

// service method implementation

 throw new FaultException<FormatFault>(fault,new FaultReason(fault.CustomFaultMassage)); 

CustomFaultMassage является свойством из контракта данных.

Ответ 5

Можно также встретить это исключение, если не указать атрибут FaultContract (typeof (className)) для метода

Ответ 6

У меня есть код, точно такой же, как у Rashmi, и я получил ошибку «Создатель этой ошибки….». Это происходило, когда я отлаживался в VS2010. Я нашел этот пост:

System.ServiceModel.FaultException`1 was unhandled by user code

который объяснил пару параметров отладки, которые мне нужно было отключить. Проблема решена.

Ответ 7

Если вы не хотите получать уведомления об этих исключениях, перейдите в «Отладка» → «Исключения» и снимите флажок «Пользовательский необработанный» для «Исключения на время обычного языка» или для определенных исключений.

Ответ 8

Вы можете попробовать это в настройках сервера (поведение → serviceBehaviors → ):

<serviceDebug includeExceptionDetailInFaults="true" />

Ответ 9

Используя сильно типизированный try catch, я смог обойтись с ошибкой «Создатель этой ошибки не определил причину».

Ответ 10

Обновление справочной службы в клиенте решило проблему. То же самое может сработать для вас.

Автор оригинала: Dhananjay Singh.

Обзор

В этой статье мы рассмотрим процесс создания пользовательских как проверенных, так и непроверенных исключений в Java.

Если вы хотите узнать больше об исключениях и обработке исключений в Java, мы подробно рассмотрели это в разделе Обработка исключений в Java: Полное руководство с лучшими и наихудшими практиками

Зачем Использовать Пользовательские Исключения?

Хотя исключения Java, как они есть, охватывают почти все исключительные случаи и условия, ваше приложение может создать специальное пользовательское исключение, уникальное для вашего кода и логики.

Иногда нам необходимо создать свой собственный для представления исключений бизнес-логики, т. Е. исключений, специфичных для нашей бизнес-логики или рабочего процесса. Например Исключение электронной почты NotUniqueException , Недопустимое исключение состояния пользователя и т.д.

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

Если определение пользовательского исключения не дает преимуществ по сравнению с использованием обычного исключения в Java, нет необходимости определять пользовательские исключения, и вам следует просто придерживаться тех, которые уже доступны – нет необходимости снова изобретать горячую воду.

Исключение С Пользовательской Проверкой

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

Мы хотим проверить, действительно ли это или нет. Теперь мы могли бы использовать встроенный в Java Исключение IllegalArgumentException , что нормально, если мы просто проверяем одну вещь, например, соответствует ли она предопределенному регулярному выражению или нет.

Но предположим, что у нас также есть бизнес-условие, чтобы проверить, что все электронные письма в нашей системе должны быть уникальными. Теперь мы должны выполнить вторую проверку (вызов БД/сети). Мы можем, конечно, использовать то же самое Исключение IllegalArgumentException , но будет неясно, какова точная причина – не прошла ли проверка регулярного выражения по электронной почте или электронное письмо уже существует в базе данных.

Давайте создадим пользовательское исключение, чтобы справиться с этой ситуацией. Чтобы создать исключение, как и любое другое исключение, мы должны расширить java.lang.Исключение класс:

public class EmailNotUniqueException extends Exception {

    public EmailNotUniqueException(String message) {
        super(message);
    }
}

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

Вызывая super(сообщение) , мы инициализируем сообщение об ошибке исключения, и базовый класс позаботится о настройке пользовательского сообщения в соответствии с сообщением .

Теперь давайте используем это пользовательское исключение в нашем коде. Поскольку мы определяем метод, который может вызывать исключение на уровне сервиса, мы пометим его ключевым словом throws .

Если входное электронное письмо уже существует в нашей базе данных (в данном случае список), мы создаем наше пользовательское исключение:

public class RegistrationService {  
    List registeredEmails = Arrays.asList("[email protected]", "[email protected]");

    public void validateEmail(String email) throws EmailNotUniqueException {
        if (registeredEmails.contains(email)) {
            throw new EmailNotUniqueException("Email Already Registered");
        }
    }
}

Теперь давайте напишем клиента для нашего сервиса. Поскольку это проверенное исключение, мы должны придерживаться правила обработки или объявления. В следующем примере мы решили “разобраться” с этим:

public class RegistrationServiceClient {  
    public static void main(String[] args) {
        RegistrationService service = new RegistrationService();
        try {
            service.validateEmail("[email protected]");
        } catch (EmailNotUniqueException e) {
            // logging and handling the situation
        }
    }
}

Запуск этого фрагмента кода приведет к:

mynotes.custom.checked.exception.EmailNotUniqueException: Email Already Registered  
    at mynotes.custom.checked.exception.RegistrationService.validateEmail(RegistrationService.java:12)
    at mynotes.custom.checked.exception.RegistrationServiceClient.main(RegistrationServiceClient.java:9)

Примечание: Процесс обработки исключений опущен для краткости, но, тем не менее, является важным процессом.

Пользовательское Непроверенное Исключение

Это прекрасно работает, но наш код стал немного запутанным. Кроме того, мы заставляем клиента фиксировать наше исключение в блоке try-catch . В некоторых случаях это может привести к тому, что разработчики будут вынуждены писать шаблонный код.

В этом случае вместо этого может быть полезно создать пользовательское исключение во время выполнения. Чтобы создать пользовательское непроверенное исключение, мы должны расширить класс java.lang.RuntimeException .

Давайте рассмотрим ситуацию, когда мы должны проверить, имеет ли электронное письмо действительное доменное имя или нет:

public class DomainNotValidException extends RuntimeException {

    public DomainNotValidException(String message) {
        super(message);
    }
}

Git Essentials

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

Теперь позвольте использовать его в нашем сервисе:

public class RegistrationService {

    public void validateEmail(String email) {
        if (!isDomainValid(email)) {
            throw new DomainNotValidException("Invalid domain");
        }
    }

    private boolean isDomainValid(String email) {
        List validDomains = Arrays.asList("gmail.com", "yahoo.com", "outlook.com");
        if (validDomains.contains(email.substring(email.indexOf("@") + 1))) {
            return true;
        }
        return false;
    }
}

Обратите внимание, что нам не нужно было использовать ключевые слова throws в подписи метода, поскольку это непроверенное исключение.

Теперь давайте напишем клиента для нашего сервиса. На этот раз нам не нужно использовать try-catch блок:

public class RegistrationServiceClient {

    public static void main(String[] args) {
        RegistrationService service = new RegistrationService();
        service.validateEmail("[email protected]");
    }
}

Запуск этого фрагмента кода приведет к:

Exception in thread "main" mynotes.custom.unchecked.exception.DomainNotValidException: Invalid domain  
    at mynotes.custom.unchecked.exception.RegistrationService.validateEmail(RegistrationService.java:10)
    at mynotes.custom.unchecked.exception.RegistrationServiceClient.main(RegistrationServiceClient.java:7)

Примечание: Конечно, вы можете окружить свой код блоком try-catch , чтобы зафиксировать возникающее исключение, но теперь компилятор не заставляет его выполнять.

Создание исключения, Заключенного в пользовательское исключение

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

Предположим, что ваше приложение имеет стандартный Коды ошибок класс:

public enum ErrorCodes {  
    VALIDATION_PARSE_ERROR(422);

    private int code;

    ErrorCodes(int code) {
        this.code = code;
    }

    public int getCode() {
        return code;
    }
}

Давайте создадим наше пользовательское исключение:

public class InvalidCurrencyDataException extends RuntimeException {

    private Integer errorCode;

    public InvalidCurrencyDataException(String message) {
        super(message);
    }

    public InvalidCurrencyDataException(String message, Throwable cause) {
        super(message, cause);
    }

    public InvalidCurrencyDataException(String message, Throwable cause, ErrorCodes errorCode) {
        super(message, cause);
        this.errorCode = errorCode.getCode();
    }

    public Integer getErrorCode() {
        return errorCode;
    }
}

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

Мы также фиксируем код ошибки в одном из конструкторов и устанавливаем код ошибки в самом исключении. Код ошибки может быть использован клиентом для ведения журнала или в любых других целях. Это помогает в более централизованном стандарте обработки исключений.

Давайте напишем наш класс обслуживания:

public class CurrencyService {  
    public String convertDollarsToEuros(String value) {
        try {
        int x = Integer.parseInt(value);
    } catch (NumberFormatException e) {
        throw new InvalidCurrencyDataException("Invalid data", e, ErrorCodes.VALIDATION_PARSE_ERROR);
        }
        return value;
    }
}

Поэтому мы поймали стандартное Исключение NumberFormatException и выбросили наше собственное Исключение Недопустимых Валютных данных . Мы передали родительское исключение нашему пользовательскому исключению, чтобы не потерять первопричину, из-за которой они произошли.

Давайте напишем тестовый клиент для этой службы:

public class CurrencyClient {  
    public static void main(String[] args) {
        CurrencyService service = new CurrencyService();
    service.convertDollarsToEuros("asd");
    }
}

Выход:

Exception in thread "main" mynotes.custom.unchecked.exception.InvalidCurrencyDataException: Invalid data  
    at mynotes.custom.unchecked.exception.CurrencyService.convertDollarsToEuro(CurrencyService.java:10)
    at mynotes.custom.unchecked.exception.CurrencyClient.main(CurrencyClient.java:8)
Caused by: java.lang.NumberFormatException: For input string: "asd"  
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Integer.parseInt(Integer.java:580)
    at java.lang.Integer.parseInt(Integer.java:615)
    at mynotes.custom.unchecked.exception.CurrencyService.convertDollarsToEuro(CurrencyService.java:8)
    ... 1 more

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

Рекомендации по использованию пользовательских исключений

  • Придерживайтесь общего соглашения об именовании во всей экосистеме Java – Все имена пользовательских классов исключений должны заканчиваться на “Исключение”
  • Избегайте создания пользовательских исключений, если стандартные исключения из самого JDK могут служить этой цели. В большинстве случаев нет необходимости определять пользовательские исключения.
  • Предпочитайте исключения во время выполнения проверенным исключениям. Фреймворки, такие как Spring , заключили все проверенные исключения в исключения времени выполнения, поэтому не заставляют клиента писать стандартный код, который им не нужен или не нужен.
  • Предоставьте множество перегруженных конструкторов, основанных на том, как будет создаваться пользовательское исключение. Если он используется для повторного создания существующего исключения, то обязательно предоставьте конструктор, который устанавливает причину.

Вывод

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

Код для примеров, используемых в этой статье, можно найти на Github .

To define a checked exception you create a subclass (or hierarchy of subclasses) of java.lang.Exception. For example:

public class FooException extends Exception {
  public FooException() { super(); }
  public FooException(String message) { super(message); }
  public FooException(String message, Throwable cause) { super(message, cause); }
  public FooException(Throwable cause) { super(cause); }
}

Methods that can potentially throw or propagate this exception must declare it:

public void calculate(int i) throws FooException, IOException;

… and code calling this method must either handle or propagate this exception (or both):

try {
  int i = 5;
  myObject.calculate(5);
} catch(FooException ex) {
  // Print error and terminate application.
  ex.printStackTrace();
  System.exit(1);
} catch(IOException ex) {
  // Rethrow as FooException.
  throw new FooException(ex);
}

You’ll notice in the above example that IOException is caught and rethrown as FooException. This is a common technique used to encapsulate exceptions (typically when implementing an API).

Sometimes there will be situations where you don’t want to force every method to declare your exception implementation in its throws clause. In this case you can create an unchecked exception. An unchecked exception is any exception that extends java.lang.RuntimeException (which itself is a subclass of java.lang.Exception):

public class FooRuntimeException extends RuntimeException {
  ...
}

Methods can throw or propagate FooRuntimeException exception without declaring it; e.g.

public void calculate(int i) {
  if (i < 0) {
    throw new FooRuntimeException("i < 0: " + i);
  }
}

Unchecked exceptions are typically used to denote a programmer error, for example passing an invalid argument to a method or attempting to breach an array index bounds.

The java.lang.Throwable class is the root of all errors and exceptions that can be thrown within Java. java.lang.Exception and java.lang.Error are both subclasses of Throwable. Anything that subclasses Throwable may be thrown or caught. However, it is typically bad practice to catch or throw Error as this is used to denote errors internal to the JVM that cannot usually be «handled» by the programmer (e.g. OutOfMemoryError). Likewise you should avoid catching Throwable, which could result in you catching Errors in addition to Exceptions.

I have the following code in WCF service to throw a custom fault based on certain situations. I am getting a «The creator of this fault did not specify a Reason» exception. What am I doing wrong?

//source code
if(!DidItPass)
{
    InvalidRoutingCodeFault fault = new InvalidRoutingCodeFault("Invalid Routing Code - No Approval Started");
    throw new FaultException<InvalidRoutingCodeFault>(fault);
}

//operation contract
[OperationContract]
[FaultContract(typeof(InvalidRoutingCodeFault))]
bool MyMethod();

//data contract
[DataContract(Namespace="http://myuri.org/Simple")]
public class InvalidRoutingCodeFault
{
    private string m_ErrorMessage = string.Empty;

    public InvalidRoutingCodeFault(string message)
    {
        this.m_ErrorMessage = message;
    }

    [DataMember]
    public string ErrorMessage
    {
        get { return this.m_ErrorMessage; }
        set { this.m_ErrorMessage = value; }
    }
}

asked Dec 4, 2008 at 17:49

Michael Kniskern's user avatar

Michael KniskernMichael Kniskern

24.8k68 gold badges164 silver badges231 bronze badges

3

After some addtional research, the following modified code worked:

if(!DidItPass)
{    
    InvalidRoutingCodeFault fault = new InvalidRoutingCodeFault("Invalid Routing Code - No Approval Started");    
    throw new FaultException<InvalidRoutingCodeFault>(fault, new FaultReason("Invalid Routing Code - No Approval Started"));
}

answered Dec 4, 2008 at 19:07

Michael Kniskern's user avatar

Michael KniskernMichael Kniskern

24.8k68 gold badges164 silver badges231 bronze badges

2

The short answer is you are doing nothing wrong, just reading the results incorrectly.

On the client side when you catch the error, what is caught is of the type System.ServiceModel.FaultException<InvalidRoutingCodeFault>.
Your InvalidRoutingCodeFault object is actually in the .detail property of the FaultException. SO….

// client code

private static void InvokeMyMethod() 
{ 
    ServiceClient service = new MyService.ServiceClient(); 

    try 
    { 
        service.MyMethod(); 
    } 
    catch (System.ServiceModel.FaultException<InvalidRoutingCodeFault> ex) 
    { 
        // This will output the "Message" property of the System.ServiceModel.FaultException
        // 'The creator of this fault did not specify a Reason' if not specified when thrown
        Console.WriteLine("faultException Message: " + ex.Message);    
        // This will output the ErrorMessage property of your InvalidRoutingCodeFault type
        Console.WriteLine("InvalidRoutingCodeFault Message: " + ex.Detail.ErrorMessage);    
    } 
}

The Message property of the FaultException is what is displayed on the error page so if it’s not populated like in John Egerton’s post, you will see the ‘The creator of this fault did not specify a Reason’ message. To easily populate it, use the two parameter constructor when throwing the fault in the service as follows, passing your error message from your fault type:

InvalidRoutingCodeFault fault = new InvalidRoutingCodeFault("Invalid Routing Code - No Approval Started");                                          
throw new FaultException<InvalidRoutingCodeFault>(fault, new FaultReason(fault.ErrorMessage));                                      

answered Sep 10, 2012 at 20:12

Daniel Davis's user avatar

serviceDebug includeExceptionDetailInFaults="true"

is NOT the solution

The following code works even with serviceDebug includeExceptionDetailInFaults="false"

// data contract 

[DataContract]
public class FormatFault
{
    private string additionalDetails;

    [DataMember]
    public string AdditionalDetails
    {
        get { return additionalDetails; }
        set { additionalDetails = value; }
    }
}

// interface method declaration

    [OperationContract]
    [FaultContract(typeof(FormatFault))]
    void DoWork2();

// service method implementation

    public void DoWork2()
    {
        try
        {
            int i = int.Parse("Abcd");
        }
        catch (FormatException ex)
        {
            FormatFault fault = new FormatFault();
            fault.AdditionalDetails = ex.Message;
            throw new FaultException<FormatFault>(fault);
        }
    }

// client calling code

    private static void InvokeWCF2()
    {
        ServiceClient service = new ServiceClient();

        try
        {
            service.DoWork2();
        }
        catch (FaultException<FormatFault> e)
        {
            // This is a strongly typed try catch instead of the weakly typed where we need to do -- if (e.Code.Name == "Format_Error")
            Console.WriteLine("Handling format exception: " + e.Detail.AdditionalDetails);   
        }
    }

There is no need to add fault reason if its not required. Just make sure the FaultContract attribute is correct

Coral Doe's user avatar

Coral Doe

1,9253 gold badges19 silver badges36 bronze badges

answered Jan 28, 2009 at 11:33

Rashmi Pandit's user avatar

Rashmi PanditRashmi Pandit

23.3k17 gold badges71 silver badges111 bronze badges

1

I solved this problem using a two parameter constructer.

// service method implementation

 throw new FaultException<FormatFault>(fault,new FaultReason(fault.CustomFaultMassage)); 

CustomFaultMassage is property from data contract.

Jon Egerton's user avatar

Jon Egerton

40.5k11 gold badges97 silver badges129 bronze badges

answered Jul 8, 2010 at 9:17

user386451's user avatar

user386451user386451

511 silver badge1 bronze badge

One can also encounter this exception if one does not specify the FaultContract(typeof(className)) attribute for the method

answered Jan 28, 2009 at 11:21

Rashmi Pandit's user avatar

Rashmi PanditRashmi Pandit

23.3k17 gold badges71 silver badges111 bronze badges

If you do not want to be notified of such exceptions go to Debug -> Exceptions and uncheck «User-unhandled» for «Common Language Runtime Exceptions» or for specific exceptions.

answered Apr 14, 2010 at 9:39

sandeep patil's user avatar

You might try this in the server config (behaviors -> serviceBehaviors -> behavior):

<serviceDebug includeExceptionDetailInFaults="true" />

answered Dec 4, 2008 at 18:12

Chris Porter's user avatar

Chris PorterChris Porter

3,62726 silver badges28 bronze badges

3

By using strongly typed try catch, I was able get around with the error «The creator of this fault did not specify a Reason».

answered Apr 15, 2009 at 0:43

Updating the service reference in the client solved the problem. Same could work for you.

answered Sep 21, 2010 at 22:50

pencilslate's user avatar

pencilslatepencilslate

13k18 gold badges59 silver badges73 bronze badges

Понравилась статья? Поделить с друзьями:
  • Содержание фильма роковая ошибка 2021 чем закончится
  • Согласно приказа какая ошибка
  • Создатель этой ошибки не указал reason еиас мониторинг
  • Создал неоднозначную реакцию ошибка
  • Содержание фильма врачебная ошибка полное