Mejora en la gestión de excepciones y errores. Nuevo managedBean para

gestión de errores anto AJAX como en peticiones normales.
This commit is contained in:
Marcos Garcia Nuñez
2020-01-01 21:42:31 +01:00
parent 7e04274255
commit 75ed5e2635
5 changed files with 257 additions and 199 deletions

View File

@@ -24,7 +24,7 @@
</context-param> </context-param>
<context-param> <context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value> <param-value>server</param-value>
</context-param> </context-param>
<context-param> <context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name> <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
@@ -52,46 +52,11 @@
<url-pattern>*.xhtml</url-pattern> <url-pattern>*.xhtml</url-pattern>
</servlet-mapping> </servlet-mapping>
<!-- Filters -->
<filter>
<filter-name>facesExceptionFilter</filter-name>
<filter-class>org.omnifaces.filter.FacesExceptionFilter</filter-class>
</filter>
<!-- Filter mappings -->
<filter-mapping>
<filter-name>facesExceptionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Error pages mapping --> <!-- Error pages mapping -->
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/error.xhtml?type=expired</location>
</error-page>
<error-page>
<exception-type>java.sql.SQLException</exception-type>
<exception-type>org.hibernate.exception.GenericJDBCException</exception-type>
<exception-type>java.net.ConnectException</exception-type>
<exception-type>javax.persistence.PersistenceException</exception-type>
<location>/error.xhtml?type=sql</location>
</error-page>
<error-page>
<exception-type>javax.persistence.PersistenceException</exception-type>
<location>/error.xhtml?type=runtime</location>
</error-page>
<error-page>
<exception-type>java.net.ConnectException</exception-type>
<location>/error.xhtml?type=sql</location>
</error-page>
<error-page> <error-page>
<error-code>500</error-code> <error-code>500</error-code>
<location>/error.xhtml</location> <location>/error.xhtml</location>
</error-page> </error-page>
<error-page>
<error-code>401</error-code>
<location>/error.xhtml?type=expired</location>
</error-page>
<session-config> <session-config>
<session-timeout>30</session-timeout> <session-timeout>30</session-timeout>

View File

@@ -2,7 +2,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui" xmlns:o="http://omnifaces.org/ui"> xmlns:p="http://primefaces.org/ui" xmlns:o="http://omnifaces.org/ui" xmlns:fn="http://xmlns.jcp.org/jsp/jstl/functions" xmlns:of="http://omnifaces.org/functions">
<ui:composition template="./header.xhtml"> <ui:composition template="./header.xhtml">
<ui:define name="content"> <ui:define name="content">
@@ -12,34 +12,43 @@
<div class="ui-g-8 ui-md-8"> <div class="ui-g-8 ui-md-8">
<p:panel id="ErrorPanel"> <p:panel id="ErrorPanel">
<f:facet name="header"> <f:facet name="header">
<p:outputLabel rendered="#{param.type == 'sql'}" value="No se puede conectar con la base de datos" /> <p:outputLabel rendered="#{error.errorType == 'sql'}" value="No se puede conectar con la base de datos" />
<p:outputLabel rendered="#{param.type == 'auth'}" value="Se ha producido un error de autorización" /> <p:outputLabel rendered="#{error.errorType == 'auth'}" value="Se ha producido un error de autorización" />
<p:outputLabel rendered="#{param.type == 'expired'}" value="Su sesión ha caducado" /> <p:outputLabel rendered="#{error.errorType == 'expired'}" value="Su sesión ha caducado" />
<p:outputLabel rendered="#{param.type == 'runtime'}" value="Se producido un error en tiempo de ejecución" /> <p:outputLabel rendered="#{error.errorType == 'runtime'}" value="Se producido un error en tiempo de ejecución" />
<p:outputLabel rendered="#{param.type == '' or param.type == null}" value="Se ha producido un error desconocido" />
</f:facet> </f:facet>
<div class="ui-g ui-fluid"> <div class="ui-g ui-fluid">
<div class="ui-g-12"> <div class="ui-g-12">
<p:outputLabel rendered="#{param.type == 'sql'}" <p:outputLabel rendered="#{error.errorType == 'sql'}"
value="No ha sido posible realizar una conexión con el servidor de base de datos subyante, o ha ocurrido un error grave cuando se intentaba realizar la conexión. Por favor contacte con el equipo de soporte." /> value="No ha sido posible realizar una conexión con el servidor de base de datos subyante, o ha ocurrido un error grave cuando se intentaba realizar la conexión. Por favor contacte con el equipo de soporte." />
<p:outputLabel rendered="#{param.type == 'auth'}" <p:outputLabel rendered="#{error.errorType == 'auth'}"
value="No está autorizado a ver la url consultada. Por favor, vaya a la página principal y utilice el menú de la aplicación para acceder las funcionalidades disponibles." /> value="No está autorizado a ver la url consultada. Por favor, vaya a la página principal y utilice el menú de la aplicación para acceder las funcionalidades disponibles." />
<p:outputLabel rendered="#{param.type == 'expired'}" value="Su sesión ha caducado. Por favor, incie sesión de nuevo en el sistema." /> <p:outputLabel rendered="#{error.errorType == 'expired'}" value="Su sesión ha caducado. Por favor, incie sesión de nuevo en el sistema." />
<p:outputLabel rendered="#{param.type == 'runtime'}" <p:outputLabel rendered="#{error.errorType == 'runtime'}"
value="Se ha producido un error en el servidor durante la ejecución de la última acción. Por favor, intentelo de nuevo o contacte con el equipo de soporte." /> value="Se ha producido un error en el servidor durante la ejecución de la última acción. Por favor, intentelo de nuevo o contacte con el equipo de soporte." />
<p:outputLabel rendered="#{param.type == '' or param.type == null}"
value="La acción que estaba realizando a causado un error inesperado en el sistema. A continuación podrá ver un descripción detallada del error para que pueda comunicarlo al equipo de soporte." />
</div> </div>
<div class="ui-g-12"> <div class="ui-g-12">
<p:messages id="errorMessage" showDetail="true" closable="false" autoupdate="true" showSummary="true" showIcon="true" /> <p:messages id="errorMessage" showDetail="true" closable="false" autoupdate="true" showSummary="true" showIcon="true" />
</div> </div>
<ui:fragment rendered="#{error.renderBack == false}">
<div class="ui-g-4" /> <div class="ui-g-4" />
<div class="ui-g-4"> <div class="ui-g-4">
<p:button value="Ir a la página principal" outcome="home" icon="pi pi-home" /> <p:button value="Ir a la página principal" outcome="home" icon="pi pi-home" />
</div> </div>
<div class="ui-g-4" /> <div class="ui-g-4" />
</ui:fragment>
<ui:fragment rendered="#{error.renderBack == true}">
<div class="ui-g-2" />
<div class="ui-g-4">
<p:button value="Ir a la página principal" outcome="home" icon="pi pi-home" />
</div>
<div class="ui-g-4">
<p:button rendered="#{error.renderBack}" value="Volver atrás" href="#{error.requestURI}" icon="pi pi-home" />
</div>
<div class="ui-g-2" />
</ui:fragment>
</div> </div>
</p:panel> </p:panel>
</div> </div>

View File

@@ -9,7 +9,8 @@
<p:panel header="Pagina principal"> <p:panel header="Pagina principal">
<div class="ui-g ui-fluid"> <div class="ui-g ui-fluid">
<div class="ui-g-12 ui-md-12"> <div class="ui-g-12 ui-md-12">
Logeado como: <h:outputLabel value="#{home.userDisplayName}" style="font-weight: bold;" /> Logeado como:
<h:outputLabel value="#{home.userDisplayName}" style="font-weight: bold;" />
</div> </div>
<div class="ui-g-2 ui-md-2"> <div class="ui-g-2 ui-md-2">
<p:outputLabel for="selectorTema" value="Cambio de tema" /> <p:outputLabel for="selectorTema" value="Cambio de tema" />

View File

@@ -48,39 +48,15 @@ public class AuthorizationFilter implements Filter {
HttpServletResponse resp = null; HttpServletResponse resp = null;
HttpSession ses = null; HttpSession ses = null;
// Si establecemos esta variable a true se realiza el autologin
// TODO: Eliminar esta variable al terminar el desarrollo
boolean Debug = false;
try {
req = (HttpServletRequest) request; req = (HttpServletRequest) request;
String reqURI = req.getRequestURI(); String reqURI = req.getRequestURI();
ses = req.getSession(false);
resp = (HttpServletResponse) response; resp = (HttpServletResponse) response;
// TODO: Eliminar este código al terminar el desarrollo.
// Realizamos un login automatico (para agilizar el desarrollo.
if (Debug == true) {
ses = req.getSession(true);
if (SessionUtils.isLogedIn(ses) == false) {
LoginMBean login = new LoginMBean();
login.setUsername("PRO#100");
login.setPassword("asdf");
boolean result = login.autoLogin(ses);
if (result == true)
SessionUtils.addMessage(ses, FacesMessage.SEVERITY_ERROR, "Login automático correcto", "Se ha realizado un login automático correctamente.");
else
SessionUtils.addMessage(ses, FacesMessage.SEVERITY_ERROR, "El login automático ha fallado.", "No se ha podido realizar el login automático.");
}
}
ses = req.getSession(false);
// Para recursos publicos permitimos el acceso exista sesión o no. // Para recursos publicos permitimos el acceso exista sesión o no.
if (reqURI.indexOf("/login.xhtml") >= 0 || reqURI.indexOf("/profile/RegisterUser.xhtml") >= 0 || reqURI.indexOf("/home.xhtml") >= 0 if (reqURI.indexOf("/login.xhtml") >= 0 || reqURI.indexOf("/profile/RegisterUser.xhtml") >= 0 || reqURI.indexOf("/home.xhtml") >= 0 || reqURI.indexOf("/error.xhtml") >= 0
|| reqURI.indexOf("/error.xhtml") >= 0 || reqURI.indexOf("/public/") >= 0 || reqURI.contains("javax.faces.resource")) { || reqURI.indexOf("/public/") >= 0 || reqURI.contains("javax.faces.resource")) {
chain.doFilter(request, response); chain.doFilter(request, response);
return; return;
} }
@@ -184,17 +160,6 @@ public class AuthorizationFilter implements Filter {
} }
resp.sendRedirect(req.getContextPath() + "/login.xhtml"); resp.sendRedirect(req.getContextPath() + "/login.xhtml");
} catch (Exception e) {
if (Exceptions.is(e, PersistenceException.class) == true) {
if (ses != null)
SessionUtils.addMessage(ses, FacesMessage.SEVERITY_ERROR, "Error al intentar acceder a la base de datos", Utils.getExceptionRootCause(e).getLocalizedMessage());
resp.sendRedirect(req.getContextPath() + "/error.xhtml?type=sql");
} else {
SessionUtils.addMessage(ses, FacesMessage.SEVERITY_ERROR, "Error interno del servidor", Utils.getExceptionRootCause(e).getLocalizedMessage());
resp.sendRedirect(req.getContextPath() + "/error.xhtml");
}
}
} }
@Override @Override

View File

@@ -0,0 +1,118 @@
package managedbean.common;
import java.io.IOException;
import java.io.Serializable;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;
import TO.VisitTO;
/***
*
* @author Marcos García Núñez (mgarcianun@uoc.edu)
*
*/
@Named("error")
@RequestScoped
public class errorMBean extends ManagedBeanBase implements Serializable {
private static final long serialVersionUID = 1L;
private String errorType;
private String requestURI;
private boolean renderBack;
@PostConstruct
public void init() throws IOException {
FacesContext fc = FacesContext.getCurrentInstance();
this.setRenderBack(false);
if (fc != null) {
HttpServletRequest req = (HttpServletRequest) fc.getExternalContext().getRequest();
Map<String, String> requestParams = fc.getExternalContext().getRequestParameterMap();
this.errorType = this.getRequestParameter(requestParams,"type");
if (this.errorType.equals("") == true) {
this.requestURI = this.getRequestAttribute(req, "javax.servlet.error.request_uri");
if (requestURI.equals("") == true)
this.requestURI = req.getContextPath().concat("/home.xhtml");
setRenderBack(true);
this.errorType = this.getRequestAttribute(req, "javax.servlet.error.exception_type").replaceFirst("class ", "");
// Si no hay error volvemos al home.
if (this.errorType.equals("") == true)
fc.getExternalContext().redirect(req.getContextPath().concat("/home.xhtml"));
switch (this.errorType) {
case "javax.faces.application.ViewExpiredException":
this.errorType = "expired";
this.addFacesMessage(FacesMessage.SEVERITY_WARN, "Sesión caducada", "Su sesión ha caducado, debe logearse de nuevo");
break;
case "java.sql.SQLException":
case "org.hibernate.exception.GenericJDBCException":
case "java.net.ConnectException":
case "javax.persistence.PersistenceException":
this.errorType = "sql";
this.addFacesMessage(FacesMessage.SEVERITY_ERROR, "Error interno del servidor", this.getRequestAttribute(req, "javax.servlet.error.message"));
break;
default:
this.errorType = "runtime";
this.addFacesMessage(FacesMessage.SEVERITY_ERROR, "Error interno del servidor", this.getRequestAttribute(req, "javax.servlet.error.message"));
}
}
}
}
private String getRequestAttribute(HttpServletRequest req, String attrName) {
Object attr = req.getAttribute(attrName);
if (attr != null)
return attr.toString();
else
return "";
}
private String getRequestParameter(Map<String, String> pars, String paramName) {
Object par = pars.get(paramName);
if (par != null)
return par.toString();
else
return "";
}
public String getErrorType() {
return errorType;
}
public void setErrorType(String errorType) {
this.errorType = errorType;
}
public String getRequestURI() {
return requestURI;
}
public void setRequestURI(String requestURI) {
this.requestURI = requestURI;
}
public boolean isRenderBack() {
return renderBack;
}
public void setRenderBack(boolean renderBack) {
this.renderBack = renderBack;
}
}