ABAP Objects: Tutorial para implementar "exceptions" En este Tutorial de ABAP Objects conoceremos qué es una excepción ("exception") y veremos en qué situaciones conviene usarlas. Además, aprenderemos a implementarlas en ABAP Objects, y probaremos su uso mediante dos ejemplos, paso a paso. Una Excepción ("Exception") es un evento que ocurre durante la ejecución de un programa, que interrumpe el flujo normal de las instrucciones del mismo, cambiando su normal comportamiento. Cuando se produce una excepción (usualmente asociada a una condición de error), el programa termina inmediatamente, por lo tanto, es importante que esas situaciones puedan ser manejadas de alguna manera dentro del programa y evitar la cancelación del mismo. Mencionamos anteriormente que las excepciones usualmente indican una condición de error. Por ejemplo, la operación de división no es posible cuando el divisor es cero. En tal caso va a ocurrir un error en tiempo de ejecución, y cancelaría el programa. Un modo de "manejar" una excepción dentro del programa y presentar la interrupción al usuario de manera "más amigable", podría mostrar en este caso un cartel indicando el error del por qué no se puede realizar tal operación, y permitir al usuario un nuevo ingreso de datos. En este tip veremos cómo se manejan las excepciones ("exceptions") en ABAP Objects y dos ejemplos donde se codifica su uso. Excepciones en ABAP objects Cuando se programa en ABAP estructurado, las excepciones se manejan de manera genérica con el bloque CATCH - ENDCATCH. En particular, si se trata de un error aritmético (por ejemplo la división por cero), el error puede ser manejado en ABAP mediante el grupo de excepciones ARITHMETIC_ERRORS. En este caso la instrucción a usar sería: CATCH SYSTEM-EXCEPTIONS arithmetic-errors. En ABAP OO, las excepciones son representadas por una instancia de una clase excepción. Los atributos de ese objeto van a contener información acerca de la situación ocurrida. Una excepción puede ser “levantada” con la sentencia RAISE EXCEPTION. Cuando esto ocurre, el sistema busca un manejador adecuado que se haga cargo, y en el caso de no encontrarlo, se produce un error en tiempo de ejecución. Este manejo se puede llevar únicamente a cabo si la sentencia que podría ocasionar que se levante la excepción, se encuentra encerrada por el bloque TRY-ENDTRY. El manejo de la excepción se realiza específicamente con la instrucción CATCH que se encuentra dentro del bloque. El siguiente es un código genérico que muestra la estrcutura del TRY-ENDTRY conteniendo la CATCH que maneja la excepción. Más adelante se mostrarán ejemplos concretos donde que utilizan estas sentencias para el manejo de excepciones. TRY. SENTENCIA_X. CATCH cx_exc_1 INTO ref_exc_1. … CATCH cx_exc_2 INTO ref_ex_2. … CLEANUP. … ENDTRY. donde: un módulo de función. volver a levantarla. un método u otro objeto que pueda lanzar una o más excepciones. Como ejemplo. *&---------------------------------------------------------------------* *& Report Z_EXCEPCION_PRUEBA *& . se produce cuando el sistema no encuentra un manejador para la excepción que fue levantada (no existe CATCH) y se usa en general para "propagar" la excepción. Tener en cuenta que se puede utilizar el mismo manejador (CATCH) para dos excepciones diferentes. Ejemplos de manejo de excepciones en ABAP Objects: A continuación mostraremos dos ejemplos de manejo de excepciones. Entonces. . ref_exc_i es una instancia de la clase “cx_exc_i" o de alguna superclase ( “cx_root" por ejemplo. ejecutará las instrucciones que se encuentren en el bloque CLEANUP siempre y cuando se cumplan ciertas condiciones: . pa_num2 TYPE ty_numero. “SENTENCIA_X” puede ser una subrutina. DATA: resultado TYPE ty_numero. ref_exc TYPE REF TO cx_root. TYPES ty_numero TYPE p LENGTH 4 DECIMALS 2. En el primero se va autilizar y manejar una excepción definida por SAP. como se va a ver más adelante). si la “SENTENCIA_X” levanta la excepción cx_exc_3 y no existe un CATCH para la misma. En el segundo se creará una nueva clase excepción y se van a definir algunos atributos. PARAMETERS: pa_num1 TYPE ty_numero. Ejemplo 1: División por cero Código del programa de prueba: *&---------------------------------------------------------------------* *& Include Z_EXCEPCION_PRUEBA_TOP Report Z_EXCEPCION_PRUEBA *& *&---------------------------------------------------------------------* REPORT z_excepcion_prueba.La excepción no es manejada en el bloque TRY-ENDTRY (como se dijo anteriormente).Una excepción es levantada en el área protegida. pero sí en algún punto de la jerarquía. la siguiente sentencia es válida: CATCH cx_exc_1 cx_exc_2 INTO ref_exc. es decir. La ejecución del código que puede estar incluido en el bloque CLEANUP. msg TYPE string. resultado. 1) El código de arriba incorpora el bloque TRY . " global Data TRY. ENDTRY. al ejecutar el programa. Por lo tanto. para salir del error: Notar que el método get_text() que se utilizó en el ejemplo es el que implementa la claseCX_ROOT de la interfaz IF_MESSAGE. WRITE: 'El resultado es: '.ENDTRY para capturar el error. 2) En cambio. el sistema desplegará el siguiente mensaje en tiempo de ejecución cuando el divisor sea cero: . el cual es heredado por toda la cadena de subclases hasta llegar a CX_SY_ZERODIVIDE (ver más abajo jerarquía de clases para comprender su comportamiento). MESSAGE msg TYPE 'I'. CATCH cx_sy_zerodivide INTO ref_exc. resultado = pa_num1 / pa_num2. donde luego deberá ingresar otro valor distinto de cero. si se ingresa un cero como divisor ocurrirá lo mostrado a continuación.*&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------* INCLUDE z_excepcion_prueba_top . msg = ref_exc->get_text( ). si se comenta el bloque TRY-ENDTRY y sólo se deja la sentencia que realiza la división. Notar que la clase hereda de una superclase. se puede acceder a la misma. Se puede observar en el primer paso. el error ocurre porque la excepción no fue manejada. como no existe un manejador de tal excepción (la sentencia no se encuentra encerrada en un bloque try- catch) se produce un error en tiempo de ejecución. El sistema levanta automáticamente la excepción en la sentencia que realiza la división cuando el divisor es cero. Jerarquía de clases Exceptions La excepción capturada en el ejemplo anterior proviene de una clase standard de SAP llamada CX_SY_ZERODIVIDE. Por lo tanto. cómo el manejo de la excepción logró una interacción más amigable con el usuario. La jerarquía básica de herencia de excepciones en ABAP se puede ver en la siguiente ilustración: Ejemplo 2: Creación y utilización de una clase excepción . En este caso. De esta forma se puede ver el árbol jerárquico de herencia hasta llegar a la clase padre CX_ROOT. que es la clase raíz de todas las excepciones. Si se hace doble click a la superclaseCX_SY_ARITHMETIC_ERROR. Para visualizar el arbol de jerarquía de clases "exceptions": Ir a la solapa “Properties” de la clase CX_SY_ZERODIVIDE. Los tipos asociados son “string” y “int2”. volver a la lista de métodos. mostrará los mensajes mencionados previamente. en el caso que sea igual a cero. seleccionar el constructor y oprimir el botón “Exceptions”. Se crea la clase Z_PERRO y se declaran los atributos nombre y peso. presionar “Enter” para crearla. 2. Se desea que el constructor de la clase "levante" una excepción cuando se intente instanciar un objeto de la clase PERRO con peso negativo o igual a cero. Para este ejemplo se va a definir una clase PERRO que tenga como atributos el nombre y peso. En la solapa de “Methods” se declara el constructor y se definen los siguientes parámetros: 3. Se mostrará por pantalla dos mensajes diferentes para cada situación: En el caso que el número sea negativo el mensaje será: “El peso de <nombre_perro>no puede ser negativo”. Posteriormente. En cambio. respectivamente. el mensaje dirá: <nombre_perro> no puede no pesar nada" Luego se creará un programa de prueba que maneje dichas excepciones y en los casos que corresponda. y finalmente oprimir “Save” en la ventana emergente: . Los pasos a llevar a cabo son: 1. Declarar la excepción ZCX_PESO_INVALIDO. . Ingresar un nuevo ID llamado ZCX_PESO_INVALIDO_CERO y completar el texto como se indica: Notar que en la solapa de atributos se crearon automáticamente dos constantes con los nombres de ambos ID’s (el que ya estaba definido y el que nuevo que se definió). Dentro de la clase ZCX_PESO_INVALIDO. cuyos valores se generaron automáticamente. Agregar el atributo nombre con tipo “string”.4. en la solapa “Texts” definir el texto que se muestra a continuación para el ID ZCX_PESO_INVALIDO (note que el ID se llama igual que la clase y ya viene definido). Posteriormente volver a la clase Z_PERRO y escribir el código para la implementación del método CONSTRUCTOR.5. peso = i_peso. Código del programa de prueba que maneja la excepción: *&------------------------------------------------------------------- --* *& Report Z_PERRO_PRUEBA *& *&------------------------------------------------------------------- --* *& *& . Activar la clase Z_PERRO. RAISE EXCEPTION TYPE zcx_peso_invalido EXPORTING textid = zcx_peso_invalido=>zcx_peso_invalido_cero nombre = i_nombre. ENDMETHOD. RAISE EXCEPTION TYPE zcx_peso_invalido EXPORTING nombre = i_nombre. A continuación se muestra un programa de prueba que maneja la excepción. 6. IF i_peso LT 0. ELSEIF i_peso EQ 0. nombre = i_nombre. ELSE. Código para la Implementación del método CONSTRUCTOR: METHOD constructor. ENDIF. Activar la clase ZCX_PESO_INVALIDO. msg = ref_exc->get_text( ). WRITE: 'Lazy creado exitosamente'.*&------------------------------------------------------------------- --* REPORT Z_PERRO_PRUEBA. ENDTRY. TRY. MESSAGE msg type 'I'. WRITE: 'Milu creado exitosamente'. CATCH zcx_peso_invalido INTO ref_exc. TRY. CATCH zcx_peso_invalido INTO ref_exc. DATA: un_perro TYPE REF TO Z_PERRO. CREATE OBJECT un_perro EXPORTING i_nombre = 'Lazy' i_peso = 0. . msg = ref_exc->get_text( ). ref_exc TYPE REF TO cx_root. msg TYPE string. MESSAGE msg type 'I'. CREATE OBJECT un_perro EXPORTING i_nombre = 'Milu' i_peso = -10. ENDTRY. Ejecutar el programa y ver los mensajes que se muestran por pantalla. WRITE: 'Budy creado exitosamente'. CREATE OBJECT un_perro EXPORTING i_nombre = 'Budy' i_peso = 30. Observar que el texto que corresponde a la constante es “El peso de &nombre&no puede ser negativo”. por lo tanto. Como es necesario que el texto cambie. se exporta el “textid” correspondiente a cuando el peso es igual a cero (la constante Z_PESO_INVALIDO_CERO). por lo tanto se ejecuta únicamente el bloque CATCH dentro del bloque TRY- ENDTRY. 8. Consideraciones adicionales para el Ejemplo 2 Analizando la implementación del método CONSTRUCTOR. CATCH zcx_peso_invalido INTO ref_exc. Este parámetro toma por default la constante que tiene el mismo nombre que la clase Z_PESO_INVALIDO. msg = ref_exc->get_text( ). En la segunda sentencia RAISE EXCEPTION. ENDTRY. se requiere explicitar el parámetro "textid". no necesita ser exportada. se levantó la excepción con la primera instrucción RAISE EXCEPTIONpero no se exportó el parámetro “textid” . porque cuando se intenta crear los objetos "Lazy" y "Milu" el método constructor levanta la excepción. observar que en el caso que elpeso sea negativo. Observar que elúnico objeto que se crea es el último (“Budy”).TRY. . MESSAGE msg type 'I'.
Comments
Report "ABAP Manejo de excepciones y mensajes.docx"