Ejemplo de manejo de excepciones y errores de Servlet

Hoy vamos a analizar la Excepción de Servlet y el Manejo de Errores. Hace algún tiempo escribí un post sobre Manejo de Excepciones en Java, pero cuando se trata de aplicaciones web, necesitamos más que un manejo normal de excepciones en Java.

Excepción de Servlet

Si te fijas, los métodos doGet() y doPost() lanzan javax.servlet.ServletException y IOException, veamos qué sucede cuando lanzamos estas excepciones desde nuestra aplicación. Escribiré un servlet simple que lanzará la ServletException.

package com.journaldev.servlet.exception;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/MyExceptionServlet")
public class MyExceptionServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		throw new ServletException("GET method is not supported.");
	}

}

Ahora, cuando invocamos este servlet a través del navegador con el método GET, obtenemos una respuesta como la imagen de abajo. Dado que el navegador solo entiende HTML, cuando nuestra aplicación lanza una excepción, el contenedor de servlets procesa la excepción y genera una respuesta HTML. Esta lógica es específica del contenedor de servlets. Estoy usando tomcat y obteniendo esta página de error. Si usas otros servidores como JBoss o Glassfish, es posible que obtengas una respuesta HTML de error diferente. El problema con esta respuesta es que no tiene valor para el usuario. Además, muestra las clases de nuestra aplicación y detalles del servidor al usuario, lo que no tiene sentido para el usuario y no es bueno desde el punto de vista de la seguridad.

Error de Servlet

I am sure you must have seen 404 error when you are trying to hit a URL that doesn’t exists. Let’s see how our servlet container responds to 404 error. If we send request for an invalid URL, we get response HTML like below image. Again it’s a generic HTML generated by server on our application behalf and hold little to no value to the user.

Excepción y Manejo de Errores de Servlet

La API de Servlet proporciona soporte para servlets de Manejador de Excepciones y Errores personalizados que podemos configurar en el descriptor de implementación. El propósito principal de estos servlets es manejar la Excepción o Error generado por la aplicación y enviar una respuesta HTML útil al usuario. Podemos proporcionar un enlace a la página de inicio de la aplicación o algunos detalles para informar al usuario qué salió mal. Así que primero necesitamos crear un servlet de Manejador de Excepciones y Errores personalizado. Podemos tener múltiples servlets de manejo de excepciones y errores para la aplicación, pero por simplicidad crearé un único servlet y lo usaré tanto para excepciones como para errores. AppExceptionHandler.java

package com.journaldev.servlet.exception;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/AppExceptionHandler")
public class AppExceptionHandler extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		processError(request, response);
	}

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		processError(request, response);
	}

	private void processError(HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		// Analizar la excepción del servlet
		Throwable throwable = (Throwable) request
				.getAttribute("javax.servlet.error.exception");
		Integer statusCode = (Integer) request
				.getAttribute("javax.servlet.error.status_code");
		String servletName = (String) request
				.getAttribute("javax.servlet.error.servlet_name");
		if (servletName == null) {
			servletName = "Unknown";
		}
		String requestUri = (String) request
				.getAttribute("javax.servlet.error.request_uri");
		if (requestUri == null) {
			requestUri = "Unknown";
		}
		
		// Establecer el tipo de contenido de la respuesta
	      response.setContentType("text/html");
	 
	      PrintWriter out = response.getWriter();
	      out.write("Exception/Error Details");
	      if(statusCode != 500){
	    	  out.write("

Error Details

"); out.write("Status Code:"+statusCode+"
"); out.write("Requested URI:"+requestUri); }else{ out.write("

Exception Details

"); out.write("
  • Servlet Name:"+servletName+"
  • "); out.write("
  • Exception Name:"+throwable.getClass().getName()+"
  • "); out.write("
  • Requested URI:"+requestUri+"
  • "); out.write("
  • Exception Message:"+throwable.getMessage()+"
  • "); out.write("
"); } out.write("

"); out.write("Home Page"); out.write(""); } }

Vamos a ver cómo podemos configurarlo en el descriptor de implementación y luego entenderemos su implementación y cómo funciona.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  <display-name>ServletExceptionHandling</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
  
  <error-page>
  	<error-code>404</error-code>
  	<location>/AppExceptionHandler</location>
  </error-page>
  
  <error-page>
  <exception-type>javax.servlet.ServletException</exception-type>
  <location>/AppExceptionHandler</location>
  </error-page>
</web-app>

Como puedes ver, es muy fácil especificar servlets manejadores de excepciones para la aplicación usando el elemento error-page. Cada elemento error-page debe tener un elemento error-code o exception-type. Definimos el servlet manejador de excepciones en el elemento location. Basándonos en la configuración anterior, si la aplicación genera un error 404 o ServletException, será manejado por el servlet AppExceptionHandler. Cuando ocurren tales excepciones y escenarios de error, el contenedor de servlets invocará el método HTTP correspondiente del servlet manejador de excepciones y pasará el objeto de solicitud y respuesta. Observa que he proporcionado la implementación de ambos métodos doGet() y doPost() para que pueda manejar las solicitudes GET y POST y usar un método común para procesarlas. Antes de que el contenedor de servlets invoque el servlet para manejar la excepción, establece algunos atributos en la solicitud para obtener información útil sobre la excepción, algunos de ellos son javax.servlet.error.exception, javax.servlet.error.status_code, javax.servlet.error.servlet_name y javax.servlet.error.request_uri. Para las excepciones, el código de estado siempre es 500, lo que corresponde al “Error interno del servidor”; para otros tipos de errores, obtenemos diferentes códigos de error como 404, 403, etc. Usando el código de estado, nuestra implementación presenta diferentes tipos de respuestas HTML al usuario. También proporciona un hipervínculo a la página de inicio de la aplicación. Ahora, cuando accedamos a nuestro servlet que está generando ServletException, obtendremos una respuesta como en la siguiente imagen. Si intentamos acceder a una URL no válida que resultará en una respuesta 404, obtendremos una respuesta como en la siguiente imagen. ¿No parece bueno y ayuda al usuario a entender fácilmente qué sucedió y les proporciona un camino para ir a la ubicación correcta? También evita enviar información sensible de la aplicación al usuario. Siempre debemos tener manejadores de excepciones en su lugar para nuestra aplicación web. Si deseas manejar excepciones en tiempo de ejecución y todas las demás excepciones en un solo manejador de excepciones, puedes proporcionar exception-type como Throwable.

<error-page>
  <exception-type>java.lang.Throwable</exception-type>
  <location>/AppExceptionHandler</location>
</error-page>

Si hay múltiples entradas de páginas de error, digamos una para Throwable y otra para IOException y la aplicación lanza FileNotFoundException entonces será manejada por el manejador de errores de IOException. También puedes usar una página JSP como manejador de excepciones, simplemente proporciona la ubicación del archivo jsp en lugar del mapeo del servlet. Eso es todo para el manejo de excepciones de servlet en la aplicación web, espero que te haya gustado.

Descargar Proyecto de Ejemplo de Manejo de Excepciones de Servlet

Echa un vistazo a otros artículos de esta serie:

  1. Aplicación Web Java
  2. Tutorial de Servlet Java
  3. Manejo de Sesiones en Java
  4. Filtro de Servlet
  5. Oyentes de Servlet
  6. Cookies en Servlets
  7. Ejemplo de Carga y Descarga de Archivos Servlet

Source:
https://www.digitalocean.com/community/tutorials/servlet-exception-and-error-handling-example-tutorial