How to serve a custom html page for 404 errors?

631 views
Skip to first unread message

Anjum Naseer

unread,
Aug 7, 2016, 5:08:42 PM8/7/16
to dropwizard-user
Hi,

Background
I am using Dropwizard 1.0.0 and have a YAML file that contains this for the server settings:
server:
  type
: simple
  rootPath
: /rest
  applicationContextPath: /
app
  adminContextPath
: /app/admin

  connector
:
    type
: http
    port
: 8084


With this I am able to successfully create and server my REST resources off URL's like this:

http://<host>:8084/app/rest/<my-resource-name>


and my assets (i.e. html, css, js, images, etc) are served off URL's like this:

http://<host>:8084/app/path/to/asset/<asset-name>


where "path" cannot be "rest" as that is where my REST resources are served off.


My Dropwizard Application class overrides the initialize method and registers some bundles like so:

    @Override
   
public void initialize(final Bootstrap<AppConfiguration> bootstrap)
   
{
        bootstrap
.addBundle(new AssetsBundle("/assets/", "/", "index.html", "assets"));
        bootstrap
.addBundle(new AssetsBundle("/node_modules/", "/node_modules/", null, "node_modules"));
       
...
   
}


and also overrides the run method and registers my REST resources like so:

    @Override
   
public void run(final AppConfiguration configuration, final Environment environment)
   
{
        environment
.jersey().register(new MyRestResource1());
        environment
.jersey().register(new MyRestResource2());
       
...
   
}


The application itself is built using Maven which produces a shaded JAR.


My assets (i.e. html, css, js, images, etc), however, are not included in this shaded JAR. I have kept them separate and have modified my POM file accordingly by using the maven-jar-plugin to add the folder containing all my assets to the JAR file. For reference this is the POM section that does that:

<plugin>
   
<groupId>org.apache.maven.plugins</groupId>
   
<artifactId>maven-jar-plugin</artifactId>
   
<version>3.0.2</version>
   
<configuration>
     
<archive>
         
<manifest>
           
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
           
<addClasspath>true</addClasspath>
         
</manifest>
         
<manifestEntries>
           
<Class-Path>./path/to/where/my/assets/reside/</Class-Path>
         
</manifestEntries>
     
</archive>
   
</configuration>
 
</plugin>



Everything is working as expected.


Question

I now want to handle cases where the user either types a URL to an unknown REST request like:

http://<host>:8084/app/rest/some-unknown-REST-resource


or to an unknown asset like either of these:

http://<host>:8084/app/path/to/unknown-asset-folder/<asset-name>

http://<host>:8084/app/path/to/asset/<unknown-asset-name>


In the above cases I want to serve a custom 404 page.


What is the best way of achieving this?


What I've already tried

1. I have registered a custom RuntimeException ExceptionMapper in my applications run method.

This however only seems to kick-in on unknown REST resources. Trying to access unknown assets stills serves the default 404 page.


2. I tried creating a DefaultResource as described here: how-to-view-custom-404-page-in-dropwizard

but that did no seem to work.


3. I found this article: Jetty Custom Error Pages

and I really would like to use the first method described there that makes use of web.xml but am not sure how to use this with Dropwizard.


4. I tried looking in the Dropwizard configuration reference here: Reference

but could not find anything related to my requirements.

Doug Patriarche

unread,
Aug 9, 2016, 3:10:09 PM8/9/16
to dropwizard-user
Hi Anjum,

One way to serve custom pages for HTML errors is to use Jetty's error handler facility. In your Application.run() method add lines like these:

public class MyApplication extends Application<MyConfiguration> {
   
// ...
   
@Override
   
public void run(final MyConfiguration configuration, final Environment environment) {
       
// ...

       
final ErrorPageErrorHandler epeh = new ErrorPageErrorHandler();
       
// 400 - Bad Request, leave alone
        epeh
.addErrorPage(401, "/error/general-error");
        epeh
.addErrorPage(402, "/error/general-error");
        epeh
.addErrorPage(403, "/error/403");
        epeh
.addErrorPage(404, "/error/404");
        epeh
.addErrorPage(405, 499, "/error/general-error");
        epeh
.addErrorPage(500, 599, "/error/general-error");
        environment
.getApplicationContext().setErrorHandler(epeh);

       
// ...
   
}
}



Then define the /error/* handlers like you do for any other Jersey resource.

Regards,
Douglas

Anjum Naseer

unread,
Aug 9, 2016, 3:58:40 PM8/9/16
to dropwizard-user
Douglas - You Sir, are a genius!

I have been rattling my brain for several days trying to solve this - thank you very much indeed for pointing me in the right direction :)

Cheers.
Reply all
Reply to author
Forward
0 new messages