Судя по приведенной информации, все выглядит так, как будто все должно работать нормально. У вас нет <dispatcher>ERROR</dispatcher>
на фильтре, поэтому фильтр вообще не должен вызываться при броске NPE.
Очевидно, что NPE был заключен в другое исключение, потому что он был брошен в нелогичное место, такое как конструктор бина, вместо обычного метода действия бина. В таком случае JSF выбросит его как ManagedBeanCreationException
. Контейнер получит его вместо NPE и, следовательно, не сможет найти страницу с ошибкой. На странице ошибок HTTP 500 по умолчанию контейнера следует прочитать самое верхнее исключение трассировки стека, чтобы определить правильное исключение для определения страницы ошибки.
Имейте в виду, что исключения времени выполнения, такие как NPE, являются ошибками разработчика (ошибками!), А не производственными ошибками, и что они должны быть исправлены как можно скорее. Лично я бы просто использовал глобальную страницу ошибок HTTP 500 для такого рода ошибок:
<error-page>
<status-code>500<status-code>
<location>/errors/generic.jsp</location>
</error-page>
Для более конкретных, реальных производственных исключений вы всегда можете объявить более конкретную страницу ошибки:
<error-page>
<exception-type>com.example.YourDatabaseAccessException</exception-type>
<location>/errors/database.jsp</location>
</error-page>
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/errors/sessionexpired.jsp</location>
</error-page>