¿ Cómo Interpreto un Mensaje de Error en Java ?
Parte 2 de 2 - Excepciones Anidadas
En el documento anterior se explicaron qué son las excepciones en una aplicación java, y cómo interpretarlas. En este nuevo documento se profundizará más al respecto.
Una excepción anidada ocurre cuando una excepción encapsula a otra. Esto ocurre típicamente cuando una excepción de un tipo debe ser convertida a un tipo diferente con el fin de que pueda ser lanzada hacia una capa más externa de la aplicación.
En este tipo de escenarios un tipo de excepción particular pudiera ser convertida en un tipo de excepción más general. Considérese el siguiente flujo de ejecución como un ejemplo:
![]() |
En este escenario el método iniciar() de la clase sql.ConexionBD lanza una excepción de tipo java.sql.SQLException, que es atrapada por el método agregarDato() de la clase com.example.AdministradorAlta, y envuelta en una excepción de tipo java.lang.IllegalStateException que a su vez es lanzada por dicho método. El anidamiento de excepciones estándares es posible en la plataforma java a partir de J2SE 1.4.
Como resultado de lo anterior, se generaría en salida estándar de error un stack trace similar al siguiente:
java.lang.IllegalStateException: java.sql.SQLException: SQL ERROR
at com.example.AdministradorAlta.agregarDato (AdministradorAlta.java:35)
at com.example.PruebaAlta.main (PruebaAlta.java:35)
Caused By: java.sql.SQLException: SQL ERROR
at sql.ConexionBD.iniciar (ConexionBD.java:49)
at com.example.AdministradorAlta.agregarDato (AdministradorAlta.java:32)
at com.example.PruebaAlta.main (PruebaAlta.java:35)
En este caso el stack trace en realidad se trata de dos stack traces; el correspondiente a la excepción más interna, y el correspondiente a la excepción más externa.
El primer listado corresponde a la excepción externa, java.lang.IllegalStateException; el segundo listado inicia con la línea “Caused By”, y corresponde a la excepción interna, java.sql.SQLException.
Cuando se presentan listados con excepciones anidadas, casi siempre será más importante el analizar la excepción más interna; y menos importante la excepción más externa. Esto se debe a que la excepción más interna se encuentra más cerca de la causa que generó el problema, lo que generalmente apuntará más rápidamente hacia la solución del mismo.
Por ejemplo, si alguien se guiara únicamente por la excepción más externa, se enfocaría únicamente a la primera parte de la excepción:
java.lang.IllegalStateException: java.sql.SQLException: SQL ERROR
at com.example.AdministradorAlta.agregarDato (AdministradorAlta.java:35)
at com.example.PruebaAlta.main (PruebaAlta.java:35)
Y entonces, de acuerdo a la discusión realizada en el documento anterior, esa persona pensaría que la raíz del problema se encuentra en el método agregarDato() de la clase AdministradorAlta, cuando en realidad la raíz del problema en este caso se encuentra en la clase sql.ConexionBD.
Puede parecer obvio en el ejemplo anterior que el stack trace cuenta con una excepción anidada, pero en realidad no siempre es el caso.
En servidores de aplicaciones u otros ambientes, los stack traces que genera una aplicación pueden ser bastante largos; al verificar una bitácora muchas veces hay que avanzar algunas páginas antes de poder determinar que existe una excepción anidada; es decir, antes de poder ver la línea que inicia con “Caused By”. Algunas veces si no se tiene cuidado esta línea podría pasar desapercibida. Además, debe tenerse cuidado en determinar si existen excepciones anidadas de forma múltiple, porque puede haberlas.
Existe otra razón para pasar por alto la existencia de excepciones anidadas en un Stack Trace. El listado de excepción anterior daba una pista de que la excepción era anidada desde su primera línea:
java.lang.IllegalStateException: java.sql.SQLException: SQL ERROR
Sin embargo, el método agregarDato() de la clase AdministradorAlta podría reescibirse de forma diferente:
public void agregarDato( String cadena ) { try { _conexion.iniciar(); } catch ( SQLException e ) { throw new IllegalStateException( "Bad Condition", e ); } }
En este caso, la construcción de java.lang.IllegalStateException recibe un mensaje además de la excepción anidada, lo que generará un stack trace que ya no indica desde un inicio que la excepción es anidada:
java.lang.IllegalStateException: Bad Condition
at com.example.AdministradorAlta.agregarDato (AdministradorAlta.java:35)
at com.example.PruebaAlta.main (PruebaAlta.java:35)
Caused By: java.sql.SQLException: SQL ERROR
at sql.ConexionBD.iniciar (ConexionBD.java:49)
at com.example.AdministradorAlta.agregarDato (AdministradorAlta.java:32)
at com.example.PruebaAlta.main (PruebaAlta.java:35)
at com.example.AdministradorAlta.agregarDato (AdministradorAlta.java:35)
at com.example.PruebaAlta.main (PruebaAlta.java:35)
Caused By: java.sql.SQLException: SQL ERROR
at sql.ConexionBD.iniciar (ConexionBD.java:49)
at com.example.AdministradorAlta.agregarDato (AdministradorAlta.java:32)
at com.example.PruebaAlta.main (PruebaAlta.java:35)
La detección y análisis adecuado de excepciones anidadas es importante, y es por ello que se ha expuesto a detalle aquí.
Por supuesto, igualmente importante es anidar las excepciones desde el código. Si el método agregarDato() no realizara la anidación, se tendría un verdadero problema. Existen desarrolladores que creen que la manera correcta de realizar una anidación es la siguiente:
public void agregarDato( String cadena ) { try { _conexion.iniciar(); } catch ( SQLException e ) {// INCORRECTO!!!! se pierde información de la excepción anidadathrow new IllegalStateException( “Bad Condition” ); } }
Sin embargo, el código anterior generará el siguiente stack trace:
java.lang.IllegalStateException: SQL ERROR
at com.example.AdministradorAlta.agregarDato (AdministradorAlta.java:35)
at com.example.PruebaAlta.main (PruebaAlta.java:35)
at com.example.AdministradorAlta.agregarDato (AdministradorAlta.java:35)
at com.example.PruebaAlta.main (PruebaAlta.java:35)
Este stack trace pierde toda la información relacionada con la excepción interna excepto el mensaje de error de la misma ( recuperado a partir de e.getMessage() ). El perder toda esta información puede dificultar la labor de solución de problemas una vez que se presenten, por lo que este tipo de codificaciones inadecuadas deben ser detectadas y corregidas oportunamente.
Claro que es mucho peor el ni siquiera almacenar la información de la excepción anidada, como se muestra en el siguiente fragmento de código:
public void agregarDato( String cadena ) { try { _conexion.iniciar(); } catch ( SQLException e ) {// INCORRECTO!!!! se pierde información de la excepción anidadathrow new IllegalStateException( “Bad Condition” ); } }
Este código por lo general no es adecuado, a menos que se tenga una buena razón para ignorar la información correspondiente a la excepción interna.
Con esto se han presentado las características más importantes para el manejo de excepciones en plataforma java. Posteriormente se liberarán documentos que presentan las excepciones estándares más típicas, y las razones por las que se presentan y cómo corregirlas.
Regresar
Derechos Reservados de este Material:
Atribución-No Comercial-Licenciamiento Recíproco 2.5 México
http://creativecommons.org/licenses/by-nc-sa/2.5/mx/
Eres libre de: a) copiar, distribuir y comunicar públicamente la obra, b) hacer obras derivadas. Bajo las condiciones siguientes: a) Atribución. Debes reconocer la autoría de la obra en los términos especificados por el propio autor o licenciante. b) No comercial. No puedes utilizar esta obra para fines comerciales. c) Licenciamiento Recíproco. Si alteras, transformas o creas una obra a partir de esta obra, solo podrás distribuir la obra resultante bajo una licencia igual a ésta.
Al reutilizar o distribuir la obra, tiene que dejar bien claro los términos de la licencia de esta obra. Alguna de estas condiciones puede no aplicarse si se obtiene el permiso del titular de los derechos de autor. Nada en esta licencia menoscaba o restringe los derechos morales del autor.
Java and all Java-based trademarks and logos are trademarks of Sun Microsystems in the United States and/or other countries.
Other products and services are trademarks of their respective owners.
|






