
En Tapestry se distingue entre la página de código de error HTTP 500 y la página del informe de excepción, aunque esta último también devuelve un código de error 500 se trata de otra página diferente. Esta página de informe de error también se muestra cuando se produce una excepción en una petición Ajax pero dentro de una ventana emergente dentro de la propia página.
La página de informe de error tienen el siguiente aspecto por defecto.
Como este aspecto no estará acorde con el resto de las páginas de la aplicación deberemos personalizarla. Creando una página personalizada de informe de error podemos darle el aspecto que al resto de páginas de la aplicación posiblemente usando el mismo componente Layout en todas.
Como se puede ver Tapestry proporciona mucha de la información que dispone acerca de la petición que nos servirá para corregirla de forma más rápida. Esta es una muy buena característica que posee Tapestry desde el año 2001, en otros frameworks habitualmente cuando se produce una excepción solo se te informa con la pila de llamadas de la excepción o excepcion strack trace que a veces no es suficiente para poder reproducir el problema. Por ejemplo, en Tapestry dispondremos de los parámetros que se enviaron en la petición y si la excepción se produce por ciertos valores o una combinación de ellos podremos reproducir el problema mucho más rápidamente que con solo la pila de llamadas de la excepción. Adicionalmente dispondremos de cierta información acerca del entorno en el que se está ejecutando la aplicación que a veces también nos puede ayudar a detectar el problema.
Para personalizar estas página deberemos crear en nuestra aplicación una página de nombre ExceptionReport, con esto será suficiente para que se muestre en vez de la de Tapestry por defecto. En ella distinguiremos entre el modo de desarrollo y producción, en el modo producción no mostraremos todos los detalles de la petición para no dar información interna de la aplicación al usuario.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package es.com.blogspot.elblogdepicodev.tapestry.jpa.pages; | |
import java.util.List; | |
import java.util.regex.Pattern; | |
import org.apache.tapestry5.SymbolConstants; | |
import org.apache.tapestry5.annotations.Property; | |
import org.apache.tapestry5.ioc.annotations.Inject; | |
import org.apache.tapestry5.ioc.annotations.Symbol; | |
import org.apache.tapestry5.ioc.internal.util.InternalUtils; | |
import org.apache.tapestry5.services.ExceptionReporter; | |
import org.apache.tapestry5.services.Request; | |
import org.apache.tapestry5.services.Session; | |
public class ExceptionReport implements ExceptionReporter { | |
private static final String PATH_SEPARATOR_PROPERTY = "path.separator"; | |
// Match anything ending in .(something?)path. | |
private static final Pattern PATH_RECOGNIZER = Pattern.compile("\\..*path$"); | |
private final String pathSeparator = System.getProperty(PATH_SEPARATOR_PROPERTY); | |
@Property | |
private String attributeName; | |
@Inject | |
@Property | |
private Request request; | |
@Inject | |
@Symbol(SymbolConstants.PRODUCTION_MODE) | |
@Property(write = false) | |
private boolean productionMode; | |
@Inject | |
@Symbol(SymbolConstants.TAPESTRY_VERSION) | |
@Property(write = false) | |
private String tapestryVersion; | |
@Inject | |
@Symbol(SymbolConstants.APPLICATION_VERSION) | |
@Property(write = false) | |
private String applicationVersion; | |
@Property(write = false) | |
private Throwable rootException; | |
@Property | |
private String propertyName; | |
@Override | |
public void reportException(Throwable exception) { | |
rootException = exception; | |
} | |
public boolean getHasSession() { | |
return request.getSession(false) != null; | |
} | |
public Session getSession() { | |
return request.getSession(false); | |
} | |
public Object getAttributeValue() { | |
return getSession().getAttribute(attributeName); | |
} | |
/** | |
* Returns a <em>sorted</em> list of system property names. | |
*/ | |
public List<String> getSystemProperties() { | |
return InternalUtils.sortedKeys(System.getProperties()); | |
} | |
public String getPropertyValue() { | |
return System.getProperty(propertyName); | |
} | |
public boolean isComplexProperty() { | |
return PATH_RECOGNIZER.matcher(propertyName).find() && getPropertyValue().contains(pathSeparator); | |
} | |
public String[] getComplexPropertyValue() { | |
// Neither : nor ; is a regexp character. | |
return getPropertyValue().split(pathSeparator); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html t:type="layout" titulo="Error en el servidor" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd" xmlns:p="tapestry:parameter"> | |
<h1 class="error">Error en el servidor</h1> | |
<h7> <a href="http://en.wikipedia.org/wiki/List_of_HTTP_status_codes" target="_blank">Error 500</a> </h7> | |
<p> | |
Oooops! Se ha producido un error en el servidor, puedes volver a la <a t:type="pageLink" page="index">página Inicio</a>. | |
</p> | |
<t:if test="productionMode"> | |
<p>${rootException.message}</p> | |
<p:else> | |
<t:exceptiondisplay exception="rootException" /> | |
<div class="t-env-data"> | |
<h2>Tapestry Framework</h2> | |
<dl> | |
<dt>Tapestry Version</dt> | |
<dd>${tapestryVersion}</dd> | |
<dt>Application Version</dt> | |
<dd>${applicationVersion}</dd> | |
</dl> | |
<h2>Request</h2> | |
<t:renderobject object="request" /> | |
<t:if test="hasSession"> | |
<h2>Session</h2> | |
<dl> | |
<t:loop source="session.attributeNames" value="attributeName"> | |
<dt>${attributeName}</dt> | |
<dd> | |
<t:renderobject object="attributeValue" /> | |
</dd> | |
</t:loop> | |
</dl> | |
</t:if> | |
<h2>System Properties</h2> | |
<dl> | |
<t:loop source="systemProperties" value="propertyName"> | |
<dt>${propertyName}</dt> | |
<dd> | |
<t:if test="! complexProperty"> | |
${propertyValue} | |
<p:else> | |
<ul> | |
<li t:type="loop" source="complexPropertyValue" value="var:path">${var:path}</li> | |
</ul> | |
</p:else> | |
</t:if> | |
</dd> | |
</t:loop> | |
</dl> | |
</div> | |
</p:else> | |
</t:if> | |
</html> |
Código fuente completo del ejemplo
Documentación sobre Apache Tapestry