Tratamiento de las excepciones en Java - Junta de Andalucía

Página creada Lucia Barambones
 
SEGUIR LEYENDO
Tratamiento de las excepciones en Java - Junta de Andalucía
Published on Marco de Desarrollo de la Junta de Andalucía (http://madeja.i-administracion.junta-
andalucia.es/servicios/madeja)

Tratamiento de las excepciones en Java
   Área: Gestión de Errores y Excepciones
   Carácter del recurso : Recomendado
   Tecno lo gías: Java

Có digo : RECU-0214
Tipo de recurso : Referencia

 Descripción
 Objetivos y Estrategia del tratamiento de excepciones
 Los objetivos que se deben buscar al diseñar un mecanismo de control de excepciones deben ser:
  1. Evitar que la ocurrencia de excepciones se muestre al usuario final en pantalla de forma incontrolada.
  2. No perder información de las excepciones lanzadas a más bajo nivel en la aplicación.
  3. Mantener un Log de todas las excepciones que ocurren en el sistema y que sea lo más legible posible.
  4. Dar soporte al sistema de validaciones de la aplicación.
 La estrategia planteada deberá ser en líneas generales la siguiente (planteamiento para JSF/ADF):
     Diseñar una jerarquía de excepciones especificando en qué casos se debe utilizar cada una de ellas.
     Establecer un conjunto de reglas para determinar que excepciones deben ser capturadas. Unas recomendaciones podrían
     ser:
         Las excepciones controladas deben ser capturadas en el método en el que se producen, transformadas en las
         excepciones de aplicación adecuadas y enviadas hacia las capas superiores.
         Las excepciones de tipo no controladas que se lancen en la capa de acceso a datos deberán ser capturadas en la
         capa de servicio y traducidas en una excepción de tipo Aplicación.
         Las excepciones de tipo no controlado que se produzcan en la capa de servicio se considerarán en general errores del
         sistema. Para evitar que su ocurrencia se muestre al usuario se tendrá que utilizar el mecanismo de control de errores
         Web.
         En la capa de vista / controlador se tendrán que capturar tanto las excepciones de tipo Aplicación que provienen de las
         capas inferiores como las que se produzcan en esta capa. Las excepciones serán capturadas en el backing bean
         dentro de cada uno de los métodos donde se ejecuta el acceso a la capa de servicio.
     El sistema deberá gestionar los mensajes orientados a los usuarios y a los administradores. Los primeros serán los que se
     muestren en las páginas de la aplicación y los segundos los que se registren en el Log del sistema.
     Si se considera necesario, se tendrá que adaptar el mecanismo de ejecución de las acciones de los backing beans, para
     que todas compartan el mismo comportamiento respecto a las excepciones.

 Jerarquía de clases de excepciones
 Para la gestión de excepciones, lo más recomendable será definir una jerarquía de clases propias para el Sistema que se esté
 desarrollando. Esta jerarquía la formará un conjunto de clases con distinta funcionalidad dentro del sistema y su complejidad
 vendrá dada en función de:
     Complejidad del sistema que se está desarrollando.
     Granuralidad en la distinción de tipos de excepción.
     Estrategia a seguir en la diferenciación de excepciones: por funcionalidad, por capa, por subsistema asociado, etc
 A continuación se muestra una propuesta genérica de jerarquía de clases de excepción que aporta la suficiente funcionalidad
 como para que sea suficiente en la mayoría de las aplicaciones de tamaño medio.

                                                                                                                                   1
SistemaExceptio n: excepción base del sistema que contiene los métodos necesarios para la escritura de los mensajes de
error en el Log. Hereda de java.lang.RuntimeException.
SistemaValidatio nExceptio n: clase de excepciones para tener un envoltorio de los errores de validación que se
produzcan en la capa de negocio y modelo del sistema. Esta clase contendrá una colección de errores de validación,
representados por la clase ErrorBean. Las validaciones serán implementadas en el componente que corresponda y diseñado a
tal efecto (servicio de negocio, backing bean, etc.).
Erro rBean: clase para encapsular los errores de validación que se produzcan en el sistema. Estos errores de validación
estarán compuestos por los siguientes datos: código de error, lista de parámetros asociados, entidad del modelo de negocio
y atributos asociados. Sirve de elemento de apoyo a la lista de errores de validación y al componente de validación.
SistemaApplicatio nExceptio n: clase para capturar excepciones controladas que se consideren errores del sistema /
errores de programación, pero que no deben impedir que se continúe trabajando con él. Pueden ser consideradas errores de
aplicación:
   Ficheros no encontrados.
   Errores en operaciones aritméticas.
   Intentar modificar entidades que no se encuentren en base de datos.
SistemaFaultExcepcio n: clase para la captura de excepciones que se consideran errores críticos en el sistema y que
impedirán que se continúe trabajando en la aplicación. Implementa la interfaz ThrowsAdvice, lo que permite insertarla como un
aspecto de la aplicación. Se utilizará para:
   Fallos de configuración.
   Caídas del sistema.
   Problemas relacionados con la instalación.
   Base de datos no disponible.

Clases de soporte al tratamiento de excepciones
Las siguientes clases dan soporte al tratamiento de las excepciones:
ServicioDePresentacion: clase de soporte a tareas útiles para la capa de presentación (por ejemplo, traducción de mensajes
de error en mensajes para las páginas JSF). Es un managed bean de aplicación utilizado por los backing beans.
UtilidadesJSF: se trata de utilidades genéricas para la transformación de los mensajes de error en mensajes para ser
mostrados en el sistema de mensajería JSF.
Servicio DeExcepcio nes: clase utilizada para realizar un tratamiento centralizado de las excepciones ocurridas en la capa
de negocio y modelo del sistema. Será un bean manejado por Spring. Esta clase implementa los métodos necesarios para
particularizar los mensajes mostrados en el caso de excepciones generadas por restricciones de base de datos.
Exceptio nHelper: clase con utilidades genéricas para la manipulación de la jerarquía de clases de excepciones del Sistema.

Registro de excepciones
Todas las excepciones del sistema tienen que ser registradas en el momento en que son encapsuladas por una excepción de
                                                                                                                                2
la jerarquía de excepciones establecida. Para su registro se hace uso del sistema de Log. Cada una de las excepciones tiene
características distintas para las siguientes propiedades:
    Nivel de criticidad con el que se graba en el Log.
    Indicador de impresión de la pila de errores.
    Mensaje de error impreso en el Log para usuarios administradores (con fines de registro).
    Mensaje de error para mostrar a los usuarios.
SistemaValidacio nExceptio n: tiene un nivel de Log Info. No se imprime ninguna pila de errores y el mensaje que se
imprime contiene los códigos de error de cada una de las validaciones que han fallado.
SistemaApplicatio nExceptio n: tiene un nivel de Log Warning, se imprime la pila de errores y el mensaje de error deberá
ser recuperado del fichero de recursos para mensajes definido en la Aplicación, con los parámetros adecuados sustituidos.
SistemaFaultExceptio n: tiene un nivel de Log Error. Se imprime la pila de errores, el mensaje puede estar basado en el
fichero de recursos y contiene la traza origen del error.

Captura y flujo de las excepciones
En el siguiente diagrama se presenta la captura y el flujo de las excepciones:

Las excepciones generadas en la capa de acceso a datos serán siempre DataAccessExceptio n lanzadas desde el
contenedor de Spring.
Todas las excepciones debidas a acceso desde la capa de servicio a otros sistemas o componentes serán encapsuladas en la
capa de servicio. Para realizar esa tarea, las clases de servicio usan la clase Servicio DeExcepcio nes. Esta clase traduce las
excepciones que se lanzan dentro de la ejecución de una clase de servicio a la excepción del tipo de la Aplicación adecuada.
Esta traducción se realiza mediante la configuración almacenada en el fichero excepcio nes.xml, en el cual se establece la
traducción correspondiente para los diferentes tipos de excepciones que se puedan producir.
Las excepciones lanzadas en una clase de servicio por acceso a otras capas de la arquitectura (por ejemplo acceso a datos,
acceso a un tramitador de expedientes, acceso a servicios Web, etc.) también son gestionadas por esta clase de servicio.
Desde la capa de servicio tan sólo se lanzan hacia la capa de vista / controlador excepciones de tipo de la Aplicación
convenientemente encapsuladas.
En la capa de vista / controlador se capturan las excepciones provenientes de las capas inferiores además de las excepciones
que se generan en la ejecución de las tareas propias de esa capa.
Para la presentación de los mensajes de excepción y su puesta a disposición de las páginas de la aplicación, como para la
gestión de las excepciones que se puedan producir en la propia capa de presentación, se utilizará la clase
Servicio DePresentacio n, que será un managed bean de aplicación que contiene otras funcionalidades de apoyo para la
capa de presentación.

Utilización del fichero de recursos
Los mensajes de error que se muestran por pantalla y en el sistema de Log se deberán almacenar en un fichero de recursos
que puede denominarse por ejemplo excepciones.properties. En este fichero se incluirán el código y mensaje de error tanto
para las excepciones del sistema como para los mensajes que se mostrarán en la pantalla de la aplicación. Se propone la

                                                                                                                                  3
siguiente nomenclatura del código de error:

.error.|comun..

Si el error es generado por una restricción de base de datos la nomenclatura deberá seguir la siguiente estructura:

.validacion.constraint.

excepciones.properties

#Errores de aplicación
sistema.comun.borrarentidad=Error al borrar %0 con identificador %1
sistema.error.comun.divisor.incorrecto=División por 0 o valor nulo
sistema.error.comun.fichero.noexiste=El fichero no existe en el sistema
sistema.error.comun.fichero.noexiste_detalle=El fichero %0 no existe en el sistema

#Errores de validación relacionados con actores
sistema.error.act.actorduplicado=La entidad %0 está duplicada
sistema.error.act.actornoexiste=Actor %0 no existe en el sistema
sistema.error.act.validar.idnulo=Valor de identificación de actor nulo
sistema.error.act.validar.idgrande=Valor de identificación de actor demasiado grande
sistema.error.act.nif.nocero=El valor del nif no puede ser 0
sistema.error.act.nif.menorqueuno=El valor del nif no puede ser menor de uno
sistema.validacion.constraint.ASDO_UK1=la asociación entre el profesional y el evento está repetida
sistema.validacion.constraint.PERF_UK1=Existe un perfil con el mismo nombre

Si el final del código contiene la extensión “_detalle”, este será el mensaje adoptado con fines de registro para las
excepciones de aplicación y de fallo del sistema.
El mensaje de error podrá contener espacios marcados con “%[número]” que serán completados mediante el sistema de
excepciones con los parámetros que se le pasen en el constructor de la excepción.

Generalidades
Los bloques try/catch son poco costosos en términos de rendimiento, cuando la excepción no se produce. El esfuerzo de
proceso para establecer un bloque try/catch es muy pequeño; sin embargo, el coste del tratamiento de la excepción cuando
ésta se produce no es trivial, pudiéndose llegar a penalizar el rendimiento si la excepción salta con relativa frecuencia (en cuyo
caso no sería una excepción y no debería ser tratada como tal).Por ello, se recomienda la utilización de excepciones para tratar
condiciones de error en un programa Java cuando se espera que éstas se produzcan de forma esporádica.
La principal alternativa al uso de excepciones es la utilización de retorno de códigos de estado; sin embargo este último no
ofrece mayor rendimiento, ya que el uso de excepciones, reduce el número de parámetros en las llamadas a método y por
consiguiente que éstos se ejecuten más rápidamente que utilizando códigos de estado. Muchas veces, resulta más eficaz
dejar que salte la excepción y capturarla, que ir controlando que dicha excepción no se produzca.

Trazas
Un sistema de trazas en Java debe de presentar las siguientes características:
    Diferenciar las trazas en distintos niveles
    Filtrar la información que se muestran en función de los usuarios
    Tener la posibilidad de enviar las trazas a destinos diversos (archivo, consola, bbdd)
    Ser configurable por ficheros
    Diferentes formatos de visualización.

Definir niveles de prioridad y la filtración de la información
Es imprescindible definir una estructura de prioridad de los mensajes de las trazas. Si seguimos el modelo recomendado por
MADEJA usando log4j, tendremos la siguiente clasificación
    OFF, no se muestra en ningún caso
    FATAL, para mostrar mensajes de situaciones que probablemente harán abortar la aplicación
    ERROR, para mostrar mensajes de errores que no son deseados pero que no interrumpirán la aplicación
    WARN, para mostrar mensajes de contextos peligros para la aplicación, o ciertas operaciones de uso no recomendado
    INFO, para mostrar mensajes de información sobre la ejecución de la aplicación, o eventos importantes dentro de la misma
    DEBUG, para mostrar mensajes interesantes para depurar la aplicación. Muy orientado al tiempo de desarrollo
    ALL, se muestra en todos los casos
Con esta división , se puede escribir las trazas de forma jerarquizada para que se visualicen en función de los tipos de usuario

                                                                                                                                     4
que están ejecutando la aplicación. Normalmente se aplica por defecto el nivel de prioridad de INFO, por lo que los mensajes
de nivel DEBUG no son visualizados. Este nivel genera un caudal elevado de trazas por lo que su uso suele estar restringido a
entornos de desarrollo.
Hay que considerar el manejo de las trazas en los casos de las excepciones y errores. Se sigue la recomendación de publicar
la menor información posible acerca del error. No se recomienda escribir las trazas de excepciones a nivel de error, ya que en
algunos casos no interesa que se visualicen.

Enviar las trazas por destinos diversos
Una vez establecido el nivel de trazas de nuestro código hay que configurar donde queremos que nuestras trazas sean
escritas o direccionadas. Es necesario poder enviar las trazas para diferentes destinos de salida. Siguiendo el uso de la librería
log4j se pueden enviar a consola, archivos, componentes Swing, servidores sockets remotos, JMS, Loggers de eventos NT y
demonios remotos Syslog de UNIX.
Pro cada destino de salida (conocido como "Appender" ) es necesario realizar una configuración. Para configurar un appender
es necesario configurar:
    El tipo de destino de salida
    El nivel de traza
    Asignarle un stream

Diseñar diferentes formatos de salida
Es importante que no sólo permita personalizar el destino de salida, sino también el formato de salida. Esto es posible
asociando un layout con un appender. El layout es el responsable de formatear la petición de logging de acuerdo a los deseos
del usuario, mientras que el appender se encarga de enviar la salida formateada a su destino. Cada appender tiene su propio
layout privado.

Rendimiento con el sistema de trazas
El incluir un sistemas de trazas provoca retrasos dentro de la ejecución de una aplicación. Normalmente se ralentiza la
ejecución de entre 5 y 50 nanosegundos cuando esta deshabilitada. Si esta habilitada depende del tipo de appender y del
layout. La mayor parte de este tiempo se gasta en construir el String del mensaje.
En el caso de que la velocidad sea un factor crítico se recomienda utilizar las facilidades que ofrece Log4j para reducir el
impacto de esta situación. Log4j tiene operaciones de que permiten habilitar y deshabilitar los logs a través de una condición.
De esta manera podemos ahorrar bastante tiempo a cambio de escribir la condición.

Buenas prácticas y recomendaciones de uso
Como resumen de las recomendaciones:
    Almacenar los mensajes de error dentro del fichero properties
    Utilizar un log para registrar la información sobre las excepciones
    Definir niveles de prioridad dentro del log
    Diseñar diversos formatos de salida de la información de las excepciones

Ejemplos
Un ejemplo básico sería el siguiente:

import java.io.IOException;

// ...

public static void main(String[] args) {
  try {
      // Se ejecuta algo que puede producir una excepción
  } catch (IOException e) {
       // manejo de una excepción de entrada/salida
  } catch (Exception e) {
       // manejo de una excepción cualquiera
  } finally {
       // código a ejecutar haya o no excepción
  }
}

Más información: Documentación sobre Logging del centro Java de la Junta de Andalucía
                                                                                                                                     5
Pautas
   Área: Desarrollo » Seguridad » Gestión de Errores y Excepciones

         Có digo          Título                                                           Tipo        Carácter
        LIBP-0281         Tratamiento de excepciones                                     Directriz     Obligatoria

   Seguridad

Source URL: http://madeja.i-administracion.junta-andalucia.es/servicios/madeja/contenido/recurso/214

                                                                                                                     6
También puede leer