Возникновение ошибок из хранимых процедур Java без «вызова Java ORA-29532, прерванного из-за неперехваченного исключения Java» - PullRequest
4 голосов
/ 31 августа 2011

Предположим, у вас есть класс Java, который определяет метод copyFile(String, String):

public class FileSystem {

    public static void copyFile(String sourcePath, String destinationPath)
        throws IOException
    {
        // ignore the fact that I'm not properly managing resources...
        FileInputStream source = new FileInputStream(sourcePath);
        FileOutputStream destination = new FileOutputStream(destinationPath);

        copyStream(source, destination);

        source.close();
        destination.close();
    }

    private static void copyStream(InputStream source, OutputStream destination)
        throws IOException
    {
        byte[] buffer = new byte[1024];

        int length;
        while ( (length = source.read(buffer)) != -1 ) {
            destination.write(buffer, 0, length);
        }
    }

}

И, предположим, вы заключили это в хранимую процедуру Java:

CREATE PROCEDURE copy_file (source_path VARCHAR2, destination_path VARCHAR2)
AS LANGUAGE JAVA
NAME 'FileSystem.copyFile(String, String)';

Теперь предположим, что вы вызываете хранимую процедуру copy_file и выдается Java IOException:

BEGIN
  copy_file( '/some/file/that/does/not/exist.txt', '/path/to/destination.txt' );
END;

В блоке PL / SQL возникает ошибка:

ORA-29532 Java call terminated by uncaught Java exception

Сообщение об ошибке также содержит описание неперехваченного Exception, но оно все равно ORA-29532. Есть ли способ выбросить Exception из Java, который определяет как код ошибки, так и сообщение об ошибке, возникающее в PL / SQL?

Ответы [ 2 ]

4 голосов
/ 31 августа 2011

Как я знаю, Oracle не может напрямую отлавливать ошибки Java. И примечание к документации Oracle ORA-29532 подтверждает эту идею:

ORA-29532: Вызов Java завершен из-за неперехваченного исключения Java: строка

Причина: об исключении или ошибке Java было сообщено и не может быть разрешено кодом Java.

Действие: измените код Java, если это поведение не предусмотрено.

Согласно этому тексту, я думаю, вы должны обработать исключение в коде Java.

Вы можете решить это с помощью этих вещей:

  1. Возвращаемое значение функции Java может быть String - не void, и вы можете отправить описание ошибки в возвращаемой переменной.
  2. Вы можете сохранить ошибку в таблице Oracle в коде Java и прочитать ее в коде PL / SQL.
  3. Вы просто отправляете ошибку в файл дампа пользователя Oracle с System.out.println();.

Редактировать: окончательное решение Адама

Это примерно то, что я реализовал, основываясь на ответе:

package mypackage;

public class MyClass {

    public static final int SUCCESS = 1;
    public static final int FAILURE = 0;

    /**
     * This method actually performs the business logic.
     */
    public static void doSomething(String arg1, String arg2) throws SQLException {
        // Actually do something...
    }

    /**
     * This method is called from PL/SQL.
     */
    public static int doSomething(String arg1, String arg2, int[] errorCode, String[] errorMessage) {
        try {
            doSomething(arg1, arg2);
            return success();
        } catch (SQLException e) {
            return failure(e, errorCode, errorMessage);
        }
    }

    private static int success() {
        return SUCCESS;
    }

    private static int failure(SQLException e, int[] errorCode, String[] errorMessage) {
        errorCode[0] = e.getErrorCode();
        errorMessage[0] = e.getMessage();
        return FAILURE;
    }

}

Затем в PL / SQL:

SUCCESS CONSTANT BINARY_INTEGER := 1;
FAILURE CONSTANT BINARY_INTEGER := 0;

SUBTYPE error_code_type  IS BINARY_INTEGER;
SUBTYPE error_message_type IS VARCHAR2(1000);

PROCEDURE
  raise_error_if_failure
  (
    status        BINARY_INTEGER,
    error_code    ERROR_CODE_TYPE,
    error_message ERROR_MESSAGE_TYPE
  )
  IS
BEGIN
  IF status = FAILURE THEN
    raise_application_error(error_code, error_message);
  END IF;
END;


FUNCTION
  do_something_in_java
  (
    arg1          VARCHAR2,
    arg2          VARCHAR2,
    error_code    OUT ERROR_CODE_TYPE,
    error_message OUT ERROR_MESSAGE_TYPE
  )
  RETURN BINARY_INTEGER
    AS LANGUAGE JAVA
    NAME 'mypackage.MyClass.doSomething(java.lang.String, java.lang.String, int[], java.lang.String[]) return int';


PROCEDURE
  do_something
  (
    arg1 VARCHAR2,
    arg2 VARCHAR2
  )
IS
  error_code    ERROR_CODE_TYPE;
  error_message ERROR_MESSAGE_TYPE;
BEGIN
  raise_error_if_failure(
      do_something_in_java(arg1, arg2, error_code, error_message),
      error_code,
      error_message
    );
END;
0 голосов
/ 14 июня 2015

Мы добавили DBMS_JAVA.endsession_and_related_state() в процедуру оракула, чтобы зафиксировать исключение, решившее проблему.Также согласен с решением Адама выше.

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