NullPointerException when starting JSF 2

The exception

Below is one of the exceptions I saw while migrating to JSF 2.x. Unlike others it was tricky to track the error down. This specific exception occured during startup when deploying the application to the server:

java.lang.NullPointerException
  at com.sun.faces.config.InitFacesContext.cleanupInitMaps(InitFacesContext.java:278)
  at com.sun.faces.config.InitFacesContext.(InitFacesContext.java:102)
  at com.sun.faces.config.ConfigureListener.contextInitialized(ConfigureListener.java:156)
  ..

The analysis

As this is a showstopper for even starting the application it is pretty visible. But what exactly is happening here? Let’s take a deeper look at the method in question which can be found in the JSF-reference implementation Mojarra:

static Map getInitContextServletContextMap() {
  ConcurrentHashMap initContextServletContext = null;
  try {
    Field initContextMap = FacesContext.class.getDeclaredField("initContextServletContext");
    initContextMap.setAccessible(true);
    initContextServletContext = (ConcurrentHashMap)initContextMap.get(null);
  } catch (Exception e) {}
  return initContextServletContext;
}

The first thing to see here is that the field access is done using reflection (so no compile safety applies) and the exception is ignored and null is returned. Sadly this method does not have any documentation and no clue on what the return value should be. That means the calling code must deal with a null value. But is that the case? Let’s take a closer look:

Map <InitFacesContext, ServletContext>initContextServletContext = InitFacesContext.getInitContextServletContextMap();
Set<Map.Entry<InitFacesContext, ServletContext>> entries = initContextServletContext.entrySet();

Now we can obviously see: A NullPointerException is going to happen and you have no chance to see the reason for the actual exception. Sadly it is pretty hard to work around a swallowed exception to figure out the details. Basically it is bad style to swallow exceptions. It is better to log the error, probably even with additional information like shown below:

...
} catch (Exception e) {
  log.error("Could not access FacesContext#initContextServletContext, " +
    "probably JSF-API and implementation mismatch!", e);
}

The solution

This way we would know what the error is: the JSF-API and implementation on the classpath don’t match. In my case I had more than one JSF-API as dependency, which resulted in an API-mixture. So my recommendation is to check the classpath of your Java-application for the following things:

  • Do the JSF implementation and JSF-API match (e.g. not mixing 2.0 and 2.1)?
  • Is more than one JSF implemenation on the classpath (e.g. JSF 1.x and 2.x)?
  • Is more than one JSF -API on the classpath?
Copyright © christophbrill.de, 2002-2018.