mojarra icon indicating copy to clipboard operation
mojarra copied to clipboard

custom exception factory broken in Mojarra 2.3.2

Open chris21k opened this issue 7 years ago • 4 comments

In my project (demo.war.zip, source code included) under vanilla Tomcat 9.0.1 x64 and Oracle JRE 1.8.0u144 x64, I use the following custom exception factory:

package demo.pack;

import java.io.IOException;
import java.util.Iterator;

import javax.faces.FacesException;
import javax.faces.context.ExceptionHandlerWrapper;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ExceptionQueuedEvent;

public class ExceptionHandlerFactory
        extends javax.faces.context.ExceptionHandlerFactory {

    public ExceptionHandlerFactory(
            javax.faces.context.ExceptionHandlerFactory wrapped) {
        super(wrapped);
    }
    
    @Override
    public javax.faces.context.ExceptionHandler getExceptionHandler() {
        return new ExceptionHandler(getWrapped().getExceptionHandler());
    }
    
    private class ExceptionHandler extends ExceptionHandlerWrapper {

        private ExceptionHandler(javax.faces.context.ExceptionHandler wrapped) {
            super(wrapped);
        }
        
        @Override
        public void handle() throws FacesException {
            for (Iterator<ExceptionQueuedEvent> it
                        = getUnhandledExceptionQueuedEvents().iterator();
                    it.hasNext(); ) {
                Throwable t = it.next().getContext().getException();
                while (t instanceof FacesException && t.getCause() != null) {
                    t = t.getCause();
                }

                FacesContext fctx = FacesContext.getCurrentInstance();
                ExternalContext ctx = fctx.getExternalContext();
                try {
                    ctx.dispatch("stop_error.xhtml");
                } catch (IOException e) {
                    // Now we are doomed.
                }
                fctx.responseComplete();

                it.remove();
            }
    
            getWrapped().handle();
        }
    }
}

Is there anything wrong with it? However, with Mojarra 2.3.2 pressing the button on the welcome page, i.e., tiggering a RuntimeException, the system throws an endless loop of handleRenderException (see log-snippet.txt). Using Mojarra 2.3.1 (swapping the jars in WEB-INF/lib and lib2 directories) the application works as desired and shows the error page.

If removing the line <h:outputStylesheet name="style.css" library="css" /> from the error page (facelet stop_error.xhtml, then the app also works with 2.3.2 . If this line is also contained in trigger.xhtml seems to have no effect on the described behavior.

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
     xmlns:h="http://xmlns.jcp.org/jsf/html">

<h:head>
    <h:outputStylesheet name="style.css" library="css" />
</h:head>

<h:body>
    An error occurred.
</h:body>

</html>

My IDE is Eclipse 4.7.1 under Win10 x64, if this should be of interest.

Thanks, Chris

chris21k avatar Oct 07 '17 07:10 chris21k

@chris21k My exception handler for Java EE 8/Galssfish v5 is a little different from you, but it works. I have used similar codes in several projects before.

hantsy avatar Oct 27 '17 01:10 hantsy

Aha, using

FacesContext fctx = FacesContext.getCurrentInstance();
NavigationHandler nav = fctx.getApplication().getNavigationHandler(); 
nav.handleNavigation(fctx, null, "stop_error.xhtml"); 
fctx.renderResponse();

instead of

ExternalContext ctx = fctx.getExternalContext();
ctx.dispatch("stop_error.xhtml");

makes the example (and my app) run again. Although also the latter should work in my humble opinion and did work with Mojarra <= 2.3.1. Maybe a bug introduced in 2.3.2? Or do I miss something with the latter snipped?

Many thanks to @hantsy .

chris21k avatar Oct 27 '17 10:10 chris21k

Please see this important message regarding community contributions to Mojarra.

https://javaee.groups.io/g/jsf-spec/message/30

Also, please consider joining that group, as that group has taken the place of the old [email protected] mailing list.

Thanks,

Ed Burns

edburns avatar Oct 29 '17 03:10 edburns

Using ctx.redirect() in a PhaseListener in Mojarra 2.3.3 also makes a/the similar problem throwing java.lang.UnsupportedOperationException: Unable to find the underlying Coyote request object (which is required to create a push request) from the request of type [org.apache.catalina.connector.RequestFacade]

It is again fixable in the app by instead using NavigationHandler similar to above with ?faces-redirect=true. As a positive side effect, this solves an old problem that in this scenario the flash scope is then usable.

However, also ctx.redirect worked under Mojarra <= 2.3.1 like a charm. So is there a general problem with forward/redirect based on servlet mechanisms while using Mojarra >= 2.3.2 ? Can anyone reproduce that, e.g., with the demo.war I have provided in my first post?

Chris

chris21k avatar Oct 29 '17 08:10 chris21k