Site-aware exception handling
This guide explains how to configure site-aware exception handling to deliver customized, user-friendly error pages for each site.
Magnolia CMS supports multiple sites, each mapped to distinct URLs, domains, or hosts. By default, errors like HTTP 404 (Resource Not Found) or 500 (Internal Server Error) display the web container’s technical error page, which is not user-friendly. For instance, an invalid URL such as https://demopublic.magnolia-cms.com/travel/%20where%20is%20my%20tour
might show:
HTTP STATUS 500 - javax.servlet.ServletException: Invalid path:/travel/ where is my tour
java.lang.RuntimeException: javax.servlet.ServletException: Invalid path:/travel/ where is my tour
info.magnolia.module.cache.filter.CacheFilter.doFilter(CacheFilter.java:234)
...
Configuration steps
Configure the servlet container
To customize error handling in your web container (for example, Apache Tomcat), add the following to Tomcat/webapps/YOUR-MAGNOLIA-WEBAPP/WEB-INF/web.xml
before the </web-app>
tag:
<error-page>
<error-code>404</error-code>
<location>/customException</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/customException</location>
</error-page>
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/customException</location>
</error-page>
The /customException path handles all java.lang.Throwable exceptions.
If this conflicts with existing configurations, update the path and corresponding mappings.
|
Implement site-aware exception handling
Deploy the following Java class to enable site-aware exception handling. Include it in your classpath if developing a custom Magnolia Maven module.
Java implementation
Class: info.magnolia.virtualuri.mapping.SiteAwareExceptionMapping
package info.magnolia.virtualuri.mapping;
import info.magnolia.context.MgnlContext;
import info.magnolia.module.site.SiteManager;
import info.magnolia.objectfactory.Components;
import javax.servlet.http.HttpServletRequest;
import java.net.URI;
import java.util.Optional;
public class SiteAwareExceptionMapping extends DefaultVirtualUriMapping {
public static final String SERVLET_ERROR_REQUEST_URI_ATTRIBUTE_NAME = "javax.servlet.error.request_uri";
private String siteName;
@Override
public Optional<Result> mapUri(URI uri) {
HttpServletRequest request = MgnlContext.getWebContext().getRequest();
Object errorRequestObject = request.getAttribute(SERVLET_ERROR_REQUEST_URI_ATTRIBUTE_NAME);
if (errorRequestObject == null) {
return Optional.empty();
}
String errorRequest = errorRequestObject.toString();
String[] requestParts = errorRequest.split("/");
if (requestParts.length >= 3) {
errorRequest = "/" + requestParts[2] + "/";
}
String requestedSite = Components.getComponent(SiteManager.class)
.getAssignedSite(request.getServerName(), errorRequest)
.getName();
if (!siteName.equals(requestedSite)) {
return Optional.empty();
}
return super.mapUri(uri);
}
public String getSiteName() {
return siteName;
}
public void setSiteName(String siteName) {
this.siteName = siteName;
}
}
Light development deployment
For light development, deploy the class using the Groovy app:
-
In the Groovy app, create a folder structure with a file named
SiteAwareExceptionMapping
in it.Name Enabled 📁 info
📁 magnolia
📁 virtualuri
📁 mapping
SiteAwareExceptionMapping
true
-
Paste the Java code above into the file.
This makes the class available in the classpath without a custom module.
Configure virtual URI mappings
Map the /customException
path to site-specific error pages using either YAML or JCR configuration.
Use only one method to avoid duplication.
Ensure the exception page does not trigger the same error, as this may cause a cyclic reference and stack overflow. |
YAML configuration
Define virtual URI mappings that redirect requests from /customException
to specific exception pages (/travel/exception
, /sportstation/exception
, or /exception
) based on the site context (travel
, sportstation
, or fallback
).
In your light module, create a virtualUriMappings
folder and add these configurations as new YAML files:
class: info.magnolia.virtualuri.mapping.SiteAwareExceptionMapping
fromUri: /customException
toUri: forward:/travel/exception
siteName: travel
class: info.magnolia.virtualuri.mapping.SiteAwareExceptionMapping
fromUri: /customException
toUri: forward:/sportstation/exception
siteName: sportstation
class: info.magnolia.virtualuri.mapping.SiteAwareExceptionMapping
fromUri: /customException
toUri: forward:/exception
siteName: fallback
Create exception pages
In the Pages app, create site-specific exception pages (for the travel
and fallback
sites, for instance) and assign appropriate templates.
Error details are stored in the In the
|
Customize exception page location
To change the error page location, update the toUri
property.
For example, modify /modules/ui-admincentral/virtualUriMappings/travel-exception-mapping@toUri
from forward:/travel/exception
to a new path.
See the Virtual URI Mapping documentation for more details.
Customize exception page template
To use a custom template:
-
Create a FreeMarker file in your light module.
-
Update
/modules/ui-admincentral/templates/pages/exception@templateScript
to reference the new file.
Sample template
<!DOCTYPE html>
<html>
<head>
<title>Server Error</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<style>
body { font-family: sans-serif; line-height: 1.4; text-align: center; }
#boxer { display: inline-block; margin: 40px; }
.error-details { width: 80%; text-align: left; margin-top: 40px; }
</style>
</head>
<body>
[#assign mySite=sitefn.site()]
<div id="boxer">
<h2>Error on ${mySite.name}</h2>
<div class="error-details">
<img src="data:image/gif;base64,..."/>
<h3>Server Error: ${ctx.request.getAttribute("javax.servlet.error.exception")!'No exception'}</h3>
<hr/>
<pre>Please check server logs for details.</pre>
</div>
</div>
</body>
</html>