martes, 18 de julio de 2017

Mensajes y Alertas de Oracle Forms

Objetivos:


 Describir el comportamiento predeterminado de los mensajes de Oracle Forms.
 Controlar errores de subprogramas built-ins en tiempo de ejecución.
 Identificar los tipos de mensajes de Oracle Forms.
 Controlar mensajes del sistema.
 Crear y controlar alertas.
 Manejar errores del servidor de base de datos.

NOTA: Usamos como ejemplo la Base de Datos: ORCL (Esquema: OE), la cual viene por defecto en cualquier versión de ORACLE.
______________________________________________________________________________________
Mensajes y Alertas en Tiempo de Ejecución.
Forms muestra mensajes en tiempo de ejecución para informar al usuario sobre eventos que ocurren en la sesión. Como diseñador, dependiendo de la naturaleza de la aplicación, es posible que desee suprimir o modificar algunos de estos mensajes.
Forms puede comunicarse con el usuario de las siguientes maneras:
 Mensaje Informativo: Mensaje que indica al usuario el estado actual del proceso o proporciona información sensible del contexto. Por defecto, esto mensajes se muestran en la línea de mensajes. Puede suprimir y/o modificar su apariencia con el Trigger On-Message.
 Mensaje de Error: Informa al usuario de un error que impide la acción actual. Por defecto, esto mensajes se muestran en la línea de mensajes. Puede suprimir y/o modificar errores con el Trigger On-Error.
 Mensaje de Trabajo (Working Message): Indica al usuario que el formulario está procesando (Ejemplo: Trabajando...). Esto se muestra en la línea de mensaje. Este tipo de mensaje puede suprimirse estableciendo la variable de sistema SUPPRESS_WORKING en TRUE:
:SYSTEM.SUPPRESS_WORKING := 'TRUE';
 Alerta del Sistema: Estas alertas proporcionan información al usuario y requieren que el mismo proporcione algún consentimiento o respuesta a una pregunta antes de que el procesamiento pueda continuar. Se muestra como una ventana modal.

Nota: Cuando existe más de un mensaje en cola (esperando para ser mostrado en la línea de mensajes), el mensaje actual se muestra como una alerta.

También puede crear mensajes y alertas en su aplicación:
 Mensaje de Aplicación: Estos son mensajes que crea en su aplicación mediante el built-in MESSAGE. Por defecto se muestran en la línea de mensajes.
 Alerta de Aplicación: Son las alertas que diseña como parte de su aplicación las cuales esperan una respuesta por parte del usuario. Estas alertas son mostradas utilizando la función SHOW_ALERT (built-in).
______________________________________________________________________________________
Manejando Errores en Tiempo de Ejecución.
Cuando un subprograma built-in falla, este no causa una excepción en el Trigger o Program Unit del cual es llamado. Esto significa que la ejecución continúa con el código subsiguiente después del error, a menos que tome medidas para detectar dicho error.

Ejemplo:
Un botón (Stock_Button) en el bloque CONTROL se encuentra en el Toolbar Canvas del form ORDERS. Al hacer clic en él, el Trigger When-Button-Pressed navega al bloque INVENTORIES y realiza una consulta allí.
GO_BLOCK ('INVENTORIES');
EXECUTE_QUERY;
Si el built-in GO_BLOCK falla porque el bloque INVENTORIES no existe o porque no es accesible, el procedimiento EXECUTE_QUERY intentaría realizar una consulta en dicho bloque.

Funciones built-in para detectar el éxito o fracaso.
Forms Builder proporciona funciones que indican si la acción más reciente en el Form tuvo éxito.
Función Built-In
Valor de Retorno
FORM_SUCCESS
TRUE: Acción exitosa.
FALSE: Ocurrió algún Error (puede ser simple o fatal).
FORM_FAILURE
TRUEOcurrió un Error (No fatal).
FALSESi ocurrió un error fue fatal.
FORM_FATAL
TRUEOcurrió un Error fatal.
FALSE: Si ocurrió un error no fue fatal.
Nota: Estas funciones built-in devuelven el estado de éxito o fracaso de la acción más reciente en el Form. La acción fallida puede haber ocurrido en un Trigger que disparó como resultado de un built-in en un otro Trigger. Por ejemplo, el procedimiento EXECUTE_QUERY, puede provocar que se desencadene el Trigger Pre-Query, y este último fallar.
______________________________________________________________________________________
Errores y Built-ins.
Por lo general resulta más práctico utilizar FORM_SUCCESS, esto debido a que devuelve FALSE si se produce algún error (fatal o no fatal). Luego, puede codificar el Trigger para que tome la acción apropiada.

Ejemplo de FORM_SUCCESS:
En el siguiente ejemplo, la función FORM_SUCCESS se utiliza en una condición para decidir si la consulta debe realizarse, dependiendo del éxito de la acción GO_BLOCK.
GO_BLOCK('INVENTORIES');
IF FORM_SUCCESS THEN
EXECUTE_QUERY;
ELSE
MESSAGE('An error occurred while navigating to Stock');
END IF;

Los Triggers fallan sólo si hay una excepción no controlada o si usted levanta la excepción FORM_TRIGGER_FAILURE el cual hace que el Trigger falle de una manera controlada.

Nota: La unidad de programa CHECK_PACKAGE_FAILURE, que se genera al construir bloques de detalle maestro, puede ser llamada para hacer fallar un Trigger si la última acción no se ha realizado correctamente.

Funciones Built-ins para determinar el error.
Cuando detecta un error, es posible que deba identificarlo para realizar una acción específica. Tres funciones built-ins proporcionan esta información:
Función
Descripción del Valor Retornado
ERROR_CODE
Número de error (datatype NUMBER).
ERROR_TEXT
Descripción del error (datatype CHAR).
ERROR_TYPE
FRM= Indica un error de Forms Builder, ORA= Indica un error de Oracle (datatype CHAR).
______________________________________________________________________________________
Niveles de Severidad de los Mensajes.
Supresión de mensajes según su Severidad.
Puede evitar la emisión de mensajes del sistema, en función de su nivel de severidad. Forms Builder clasifica cada mensaje con un nivel de severidad que indica qué tan crítica o trivial es la información; Cuanto más altos sean los números, más crítico será el mensaje. Hay seis niveles que puedes afectar.
Nivel de Severidad
Descripción
0
Todos los mensajes.
5
Reafirma una condición obvia.
10
El usuario ha cometido un error de procedimiento.
15
El usuario intenta una acción para la cual el Form no está diseñado
20
No se puede continuar la acción deseada debido a un problema en el Trigger o a alguna otra condición excepcional.
25
Una condición que podría provocar que el Form se ejecute incorrectamente.
> 25
Mensajes que no pueden ser suprimidos.
En un Trigger, puede especificar que sólo los mensajes por encima de un nivel de severidad especificado deben ser emitidos por el Form. Esto se hace asignando un valor a la variable de sistema MESSAGE_LEVEL. Forms entonces sólo emite mensajes que están por encima del nivel de severidad definido en esta variable.
El valor predeterminado para MESSAGE_LEVEL (al inicio del Form) es 0. Esto significa que se muestran los mensajes de todas las severidades.

______________________________________________________________________________________
Supresión de Mensajes.
Como habíamos mencionado, puede suprimir la aparición de ciertos mensajes de acuerdo a su nivel de severidad. A continuación un ejemplo de como hacerlo:
:SYSTEM.MESSAGE_LEVEL := '5';
UP;
IF  NOT FORM_SUCCESS THEN
  MESSAGE('Already at the first Order');  
END IF;    
:SYSTEM.MESSAGE_LEVEL := '0';


El anterior Trigger usa el Built-in UP para mover o cambiar el cursor del registro actual al que se encuentra arriba. Si el cursor ya está en el primer registro, el built-in falla y aparece el siguiente mensaje: FRM-40100: At first record.
FRM-40100 se trata de un mensaje de nivel de severidad 5. Sin embargo, el Trigger lo suprime y emite su propio mensaje de aplicación, mas adelante se restablece el nivel de mensaje a normal (0).

Supresión del Mensaje Trabajando (Working).
El mensaje Working se muestran cuando Forms está ocupado procesando una acción. Por ejemplo, al realizar una consulta. Puede suprimir este mensaje estableciendo la variable de sistema SUPPRESS_WORKING en True:
:SYSTEM.SUPPRESS_WORKING := 'TRUE';
Nota: Puede configurar estas variables de sistema tan pronto como se inicie el Form, si es necesario, realizando las asignaciones en el Trigger WHEN-NEW-FORM-INSTANCE.
______________________________________________________________________________________
La Excepción FORM_TRIGGER_FAILURE.
Los Triggers fallan cuando ocurre uno de los siguientes:
 Se levanta una excepción no controlada.
 Cuando solicita la interrupción del Trigger al generar la excepción Built-in FORM_TRIGGER_FAILURE.

Esta excepción está definida y gestionada por Forms Builder. Puede levantar esta excepción:
 En la parte ejecutable de un Trigger, para saltarse las acciones restantes y hacer fallar el Trigger.
 En un manejador de excepciones, para detener el Trigger después de que se hayan cumplido sus propias acciones de gestión de excepciones.
En cualquier caso, Forms Builder tiene su propio manejador de excepciones para FORM_TRIGGER_FAILURE, que hace fallar el Trigger pero no causa una excepción no controlada. Esto significa que puede hacer fallar el Trigger de manera controlada.

Ejemplo:
SELECT cust_first_name ||' '|| cust_last_name
  INTO :ORDERS.customer_name
  FROM CUSTOMERS
  WHERE customer_id = :ORDERS.customer_id;  
EXCEPTION
WHEN no_data_found THEN 
  MESSAGE('Customer with this ID not found');
  RAISE form_trigger_failure;

Este ejemplo agrega una acción al manejador de excepciones del Trigger When-Validate-Item para el elemento Customer_ID. Si el usuario introduce un número de cliente no existente, se muestra el mensaje: Customer with this ID not found y el Trigger falla.
______________________________________________________________________________________
Triggers para interceptar Mensajes del Sistema.
Al escribir Trigger que activan eventos de mensajes, puede interceptar los mensajes del sistema antes de que se muestren en la pantalla. Para ello usamos los siguientes Triggers:
 On-Error: Disparan cuando ocurre un mensaje de error del sistema.
 On-Message: Disparan cuando ocurre un mensaje informativo del sistema.

Estos Triggers reemplazan la visualización de un mensaje, de modo que el operador no ve ningún mensaje a menos que emita uno del propio Trigger.

Puede definir estos Triggers en cualquier nivel. Por ejemplo, un Trigger On-Error en el nivel de Item sólo intercepta los mensajes de error que se producen mientras el control está en ese Item. Sin embargo, si define uno o ambos Triggers en el nivel de Form, podrá reemplazar todos los mensajes sin importar el objeto que los provoque.

Trigger On-Error.
Utilice este Trigger para:
 Detectar errores Oracle y errores de Forms. Este Trigger puede realizar acciones correctivas basadas en el error que ocurrió.
 Reemplazar el mensaje de error predeterminado con un mensaje personalizado para esta aplicación.

Recuerde que puede utilizar las funciones built-in: ERROR_CODE, ERROR_TEXT y ERROR_TYPE para identificar los detalles del error y, posiblemente, utilizar esta información en su propio mensaje.

Ejemplo:

IF ERROR_CODE = 40202 THEN

  MESSAGE('You must fill in this field for an Order');

ELSE

  MESSAGE(ERROR_TYPE || '-' || TO_CHAR(ERROR_CODE) ||   ': ' || ERROR_TEXT);

END IF;

RAISE FORM_TRIGGER_FAILURE;

Este Trigger On-Error envía un mensaje personalizado para el error 40202 (You must fill in this field for an Order), y reconstruye el mensaje estándar del sistema para todos los demás errores.

Trigger On-Message.
Utilice este Trigger para suprimir mensajes informativos, reemplazándolos con mensajes personalizados, según corresponda.

Puede manejar mensajes en On-Message de manera similar a On-Error. Sin embargo, debido a que este Trigger se activa debido a mensajes informativos, debe utilizar diferentes Built-ins para determinar la naturaleza del mensaje actual.
Built-In
Descripción
MESSAGE_CODE
Número del mensaje (tipo de datos NUMBER).
MESSAGE_TEXT
Texto del mensaje informativo que se mostraría (tipo de datos CHAR).
MESSAGE_TYPE
FRM = Mensaje de Form Builder.
ORA = Mensaje del Servidor Oracle.
NULL = No se ha emitido ningún mensaje en esta sesión (tipo de datos CHAR).
Nota: Estas funciones devuelven información sobre el mensaje más reciente que se ha emitido. Si sus aplicaciones deben estar soportadas en más de un idioma nacional, utilice MESSAGE_CODE en preferencia a MESSAGE_TEXT al comprobar un mensaje.

Ejemplo:
      IF  MESSAGE_CODE in (40350,40301) THEN
  MESSAGE('No Orders found-check your search values');
ELSE
  MESSAGE(MESSAGE_TYPE || '-' || TO_CHAR(MESSAGE_CODE)   ||': '|| MESSAGE_TEXT);
END IF;
Este Trigger modifica el mensaje "Query caused no records to be retrieved" (40350) y “Query caused no records to be retrieved. Re-enter.” Mensaje (40301).
______________________________________________________________________________________
Las Alertas y sus Propiedades.
Las alertas son un método alternativo para comunicarse/interactuar con el usuario. Debido a que se muestran en una ventana modal, las alertas proporcionan una forma eficaz de llamar la atención y obligar al operador a contestar el mensaje antes de que el procesamiento pueda continuar.
Utilice las alertas cuando necesite realizar lo siguiente:
 Mostrar un mensaje que el usuario no puede ignorar, y debe reconocer.
 Preguntar al usuario una pregunta en la que son adecuadas hasta tres respuestas (normalmente , No o Cancelar).

Maneje las respuestas a una alerta mediante el uso de subprogramas Built-ins. Por lo tanto, las alertas se gestionan en dos etapas:
 Cree la alerta en tiempo de diseño y defina sus propiedades en la paleta Propiedad.
 Activar la alerta en tiempo de ejecución mediante built-ins y tomar medidas basadas en la respuesta devuelta del operador.

Crear una Alerta.
Al igual que otros objetos que se crean en el tiempo de diseño, se crean alertas desde el Navegador de objetos.
 Seleccione el nodo Alertas en el Navegador y, a continuación, seleccione Crear.
 Defina las propiedades de la alerta en la paleta de propiedades.

Las propiedades que puede especificar para una alerta son las siguientes:
Propiedad
Descripción
Name
Es el nombre de la alerta.
Title
Título a mostrar en la alerta.
Alert Style
Símbolo mostrado en la alerta: Stop, Caution, o Note
Button1, Button2, Button3 Labels
Etiquetas u opciones para cada uno de los 3 posibles botones (NULL indica que el botón no será mostrado).
Default Alert Button
Especifica el botón que se presionara cuando el usuario presiona [Enter].
Message
Mensaje mostrado en la alerta -  puede tener múltiples líneas, con un máximo de 200 caracteres.
Planificando Alertas: ¿Cuántas Necesita?
Potencialmente, puede crear una alerta para cada mensaje que necesite mostrar, pero esto suele ser innecesario. Puede definir o modificar el mensaje de una alerta en tiempo de ejecución, antes de que se muestre al usuario. Se puede utilizar una sola alerta para mostrar muchos mensajes, siempre que sus botones sean adecuados para responder a los mensajes.
Crear una alerta para cada combinación de:
 Estilo de Alerta.
 Conjunto de botones (y etiquetas) para la respuesta del usuario.

Por ejemplo, una aplicación puede requerir una alerta de tipo Note con un solo botón (Aceptar) para confirmación, una alerta tipo Caution con un botón similar y dos alertas Stop en las cuales cada una proporcione una combinación diferente de botones para una respuesta. A continuación, puede asignar un mensaje a la alerta adecuada antes de su visualización, mediante el procedimiento Built-in SET_ALERT_PROPERTY.

______________________________________________________________________________________
Controlando Alertas en Tiempo de Ejecución.
Hay subprogramas Built-ins que permiten cambiar el mensaje de una alerta y sus etiquetas.  También hay Built-ins para mostrar la alerta, los cuales devuelven la respuesta del usuario al Trigger de llamada.

Procedimiento SET_ALERT_PROPERTY.
Utilice este Built-in para cambiar el mensaje o título que está asignado actualmente a una alerta.
SET_ALERT_PROPERTY ('alert_name', property, 'mensaje/title');

Parámetro
Descripción
Alert_name
Nombre de la alerta definido en Forms Builder (De forma alternativa puede especificar el alert_id de la misma).
Property
Propiedad a establecer (Use ALERT_MESSAGE_TEXT para el mensaje y TITLE para el título).
Message/Title
Cadena de caracteres que define el mensaje/título.
Procedimiento SET_ALERT_BUTTON_PROPERTY.
Utilice este Built-in para cambiar la etiqueta en uno de los botones de la alerta:
SET_ALERT_BUTTON_PROPERTY('alert_name', button, property, 'value');
Parámetro
Descripción
Alert_name
Nombre de la alerta definido en Forms Builder (De forma alternativa puede especificar el alert_id de la misma).
Button
El número que especifica el botón de la alerta (Use las constantes ALERT_BUTTON1, ALERT_BUTTON2, y ALERT_BUTTON3.)
Property
Propiedad a establecer; utilice LABEL.
Value
Cadena de caracteres que define el Label o Etiqueta.
Función SHOW_ALERT.
SHOW_ALERT es utilizada para mostrar una alerta en tiempo de ejecución, dicha función devuelve la respuesta del usuario al trigger de llamada:
selected_button := SHOW_ALERT('alert_name');

alert_name es el nombre de la alerta, tal como se define en Forms Builter. También puede especificar un Alert_Id para este argumento.

SHOW_ALERT devuelve una constante NUMBER, que indica cuál de los tres posibles botones presionó el usuario. Estos números corresponden a los valores de tres constantes PL/SQL, que están predefinidas por Forms Builder.

Después de mostrar una alerta que tiene más de un botón, puede determinar qué botón pulsó el usuario comparando el valor devuelto con las constantes correspondientes.

Ejemplo:
   IF SHOW_ALERT('del_check') = ALERT_BUTTON1 THEN
  DELETE_RECORD;
END IF;

En el ejemplo un Trigger que se activa cuando el usuario intenta eliminar un registro, antes de eliminar el registro la alerta se invoca esperando la confirmación de usuario. Si el usuario selecciona , se llama a la función DELETE_RECORD para eliminar el registro actual del bloque.
______________________________________________________________________________________
Dirigir Errores a una Alerta.
Es posible que desee mostrar errores en una alerta de forma automática, a través de un Trigger "On-Error". Las funciones Built-ins que devuelven informaciones del error, como ERROR_TEXT, se pueden utilizar en el procedimiento SET_ALERT_PROPERTY para construir el mensaje de una alerta.

Ejemplo:
  PROCEDURE alert_on_failure IS
  n NUMBER;
BEGIN
  SET_ALERT_PROPERTY('
error_alert',
  ALERT_MESSAGE_TEXT,
  ERROR_TYPE||'-'||TO_CHAR(ERROR_CODE)||': ' ||
  ERROR_TEXT);
  n := SHOW_ALERT('
error_alert');
END;
El anterior procedimiento (alert_on_failure) se puede llamar cuando la última acción de un Form no tuvo éxito. El procedimiento falla en el Trigger de llamada y muestra Error_Alert que contiene la información de error.

Nota: Si desea que el Trigger falle, incluya una llamada a RAISE form_trigger_failure.
______________________________________________________________________________________
Manejo de Errores Generados por el Servidor Oracle.
Los errores del Servidor de Base de Datos Oracle pueden ocurrir por muchas razones diferentes, como violar una restricción declarativa o encontrar un error en una Unidad de Programa. Usted debe saber cómo manejar los errores que pueden ocurrir en diferentes situaciones.

Causas de los errores del servidor Oracle.

Causa

Mensaje de Error
Algún Constraint
Causa un error predefinido.
Trigger de Base de Datos
Mensaje de error especificado en RAISE_APPLICATION_ERROR.
Program Unit
Mensaje de error especificado RAISE_APPLICATION_ERROR.
Tipos de Sentencias DML.
Las infracciones de restricciones tipo Constraint y la ejecución de Triggers de base de datos se deben a sentencias DML. Para fines de manejo de errores, debe distinguir entre los siguientes dos tipos de sentencias DML:
Tipo
Descripción
DML Implícito
Son sentencias DML  que están asociadas con bloques de base de datos. DML Implícito es también conocido como base table DML.  Por defecto, Forms construye y emite estas sentencias DML.
DML Explícito
Son sentencias DML que el desarrollador codifica en Triggers y Unidades de Programas.
Mensajes de error FRM causados por errores DML implícitos.
Si una sentencia DML implícita provoca un error del servidor Oracle, Forms muestra uno de estos mensajes de error:
 FRM-40508: ORACLE error: unable to INSERT record.
 FRM-40509: ORACLE error: unable to UPDATE record.
 FRM-40510: ORACLE error: unable to DELETE record.

Puede utilizar ERROR_CODE para interceptar estos errores en un Trigger On-Error y, a continuación, utilizar DBMS_ERROR_CODE y DBMS_ERROR_TEXT para determinar el código de error ORA y el mensaje.

Mensajes de error con Web-Deployed Forms.
Los usuarios pueden recibir un error genérico FRM-99999. Puede obtener información significativa acerca de este error desde el panel de control de JInitiator.
______________________________________________________________________________________
Capturar diferentes tipos de errores del Servidor Oracle.
Tipo
Manejo de Errores
DML Implícito
Utilice los Built-ins DBMS_ERROR_CODE DBMS_ERROR_TEXT en un Trigger On-Error.
DML Explícito
Utilice las funciones de PL/SQL SQLCODE SQLERRM en un manejador de excepciones WHEN   OTHERS de un Trigger o Unidad de Programa que ejecute sentencias DML.
Program Unit
Utilice las funciones de PL/SQL SQLCODE SQLERRM en un manejador de excepciones WHEN   OTHERS de un Trigger o Unidad de Programa el cual llama al Program Unit en cuestión.
Nota: Las violaciones a Constraints y Triggers de base de datos pueden ser causados tanto por DML implícito como explícito. Las unidades de programa siempre se llaman explícitamente desde un Trigger o desde otra unidad de programa.

Nota Técnica:
Los valores de DBMS_ERROR_CODE y DBMS_ERROR_TEXT son iguales a lo que el usuario vería después de seleccionar Ayuda>Mostrar error; Los valores no se restablecen automáticamente después de una ejecución exitosa.
______________________________________________________________________________________
Fuente: Oracle Forms Developer 10g: Build Internet Applications.