Kyle Banks

Creating a Custom 404 Page in Grails, and How to Raise a 404 Error

Written by @kylewbanks on Apr 5, 2013.

Implementing a custom 404 page can be an effective way to retain visits from people who have found a dead link to your site, or have stumbled upon a page that doesn't exist. Depending on the content of the URL, you may even be able to show the vistor some links they may be interested in based on related content.

In this post, I'm going to show you the process of setting up a simple 404 page that you can use to inform your users that they have stumbled upon some non-existent content. Using this method, you should be able to go a step further and customize the view however you like. For an example of how this will work, click on this broken link (which is much nicer than the default Tomcat 404...)

The first step is to declare the 404 page in grails-app/conf/UrlMappings.groovy. You can see that this is the default file with the addition of just one line, containing "404"(view: '/404').

class UrlMappings {

	static mappings = {
		"/$controller/$action?/$id?"{
			constraints {
				// apply constraints here
			}
		}

		"/"(view:"/index")
		"500"(view:'/error')
                "404"(view: '/404')
	}
}

The next step is to create a grails-app/views/404.gsp view that will contain the content of your 404 page. Here is the very simple 404 I use for this site:

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
    <meta name="layout" content="main">
    <title>That's a Fail... | Kyle W. Banks</title>
</head>
<body>
    <h2>Well, that's a fail...</h2>

    <p>
        This page doesn't seem to exist anymore, or perhaps it never did. It's tough to say for sure.
        What I do know, however, is that you can find plenty of other great content right over <a href="/"><b>here</b></a>.
    </p>
</body>
</html>

Now every time a 404 error is raised (i.e. a controller/action is not found), users will see the content of 404.gsp. Obviously 404 pages are meant as a last resort when a page is not found, but what about when a user navigates to a URL that they aren't meant to see?

For instance, if you have an administrative panel on your website, you may want to check if the user is authenticated, and if not, show a 404 (just so they don't think there is any content there). In this case, the only administrative page that should be available is the login page, and all others throw a 404. In order to do this, we need to be able to raise a 404 error from within a controller:

//Example of throwing a 404 error from within a controller
def adminPage() {
    if(!loginService.userIsAdmin(session)) {
         log.error("Unauthorized access, throwing 404!")
         return response.sendError(404)                 
    }

    //User is authenticated, business as usual...
}

Here, our theoretical loginService will check the session for the proper credentials to access the administrative panel, and if it deems the user is not authorized, we throw a 404 response. Grails will intercept this error and show our 404 page automatically.

Let me know if this post was helpful on Twitter @kylewbanks or down below, and follow me to keep up with future posts!