2

When I type a url to a non-existing resource from javax.faces.resource such as

http://myapp/javax.faces.resource/noexisting.xhtml 

I am getting the default HTTP 404 page while my 404 error page is not being rendered . I understood that the FacesServlet is setting the status code to 404 instead of sending en error which is why my error page is never called. Is there a way to override this implementation to send an error instead of setting the status code?

I am using primefaces 3.5 and morajara 2.1.14.

Thanks for any help.

alpha2011
  • 365
  • 6
  • 18
  • you mean something like this http://stackoverflow.com/a/10298460/1692632 ? – Darka Sep 17 '13 at 19:48
  • No. That is what I've already implemented. My custom error page is never called for non-existing resources under /javax.faces.resource/. – alpha2011 Sep 17 '13 at 20:01

1 Answers1

5

I found the solution by myself. I implemented my own ResourceHandlder and check the existence of a resource.If the resource does not exist I send an 404 error. In case anybody else has the same issue, here is the code:

package com.mypackage;

import java.io.IOException;
import javax.faces.application.Resource;
import javax.faces.application.ResourceHandler;
import javax.faces.application.ResourceHandlerWrapper;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import com.sun.faces.util.Util;

public class MyResourceHandler extends ResourceHandlerWrapper {

  // Properties
  // -----------------------------------------------------------------------------------------------------

  private final ResourceHandler wrapped;

  public MyResourceHandler (final ResourceHandler wrapped) {
    this.wrapped = wrapped;
  }

  @Override
  public ResourceHandler getWrapped() {
    return wrapped;
  }


  /**
   * @see javax.faces.application.ResourceHandlerWrapper#isResourceRequest(javax.faces.context.FacesContext)
   */
  @Override
  public boolean isResourceRequest(final FacesContext context) {
    return super.isResourceRequest(context);
  }

  @Override
  public void handleResourceRequest(FacesContext context) throws IOException {
    String resourceId = normalizeResourceRequest(context);
    if (null != resourceId && resourceId.startsWith(RESOURCE_IDENTIFIER)) {
      Resource resource = null;
      String resourceName = null;
      if (ResourceHandler.RESOURCE_IDENTIFIER.length() < resourceId.length()) {
        resourceName = resourceId.substring(RESOURCE_IDENTIFIER.length() + 1);
        if (!StringUtils.isEmpty(resourceName)) {
          resource =
              context
                  .getApplication()
                  .getResourceHandler()
                  .createResource(resourceName,
                      context.getExternalContext().getRequestParameterMap().get("ln"));
        }
      }
      if (resource == null) {
        HttpServletResponse response =
            (HttpServletResponse) context.getExternalContext().getResponse();
        response.sendError(404);
        return;
      }
    }
    super.handleResourceRequest(context);
  }

  private String normalizeResourceRequest(FacesContext context) {

    String path;
    String facesServletMapping = Util.getFacesMapping(context);
    // If it is extension mapped
    if (!Util.isPrefixMapped(facesServletMapping)) {
      path = context.getExternalContext().getRequestServletPath();
      // strip off the extension
      int i = path.lastIndexOf(".");
      if (0 < i) {
        path = path.substring(0, i);
      }
    } else {
      path = context.getExternalContext().getRequestPathInfo();
    }
    return path;
  }


}
alpha2011
  • 365
  • 6
  • 18
  • This is a great piece. thanks man @alpha2011! helped me a bunch! But I was wondering, can you point me to where you learn of this: "I understood that the FacesServlet is setting the status code to 404 instead of sending an error which is why my error page is never called" – Fritz Apr 17 '17 at 06:29
  • Also I edited some parts in your code to use OmniFaces since I'm using MyFaces and I don't have the com.sun.faces.util.Util – Fritz Apr 17 '17 at 06:31