Hi.

I'm working in a project with Myfaces 2.0.5 and I have had a problem with a
custom ResourceResolver.

I have coded a ResourceResolver that dynamically builds an XHTML file when
the engine asks him to resolve a certain URL.

To achieve this, I have update the web.xml as follows:

  <context-param>
    <param-name>javax.faces.FACELETS_VIEW_MAPPINGS</param-name>
    <param-value>*.test;*.xhtml</param-value>
  </context-param>

  <context-param>
      <param-name>javax.faces.FACELETS_RESOURCE_RESOLVER</param-name>

<param-value>com.test.view.facelets.CustomResourceResolver</param-value>
  </context-param>

My CustomResourceResolver is very simple:

package com.test.view.facelets;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;

import javax.faces.view.facelets.ResourceResolver;

public class CustomResourceResolver extends ResourceResolver {

    private ResourceResolver innerResourceResolver;

    private String viewSource = ".... xhtml of the test page ....";

    public CustomResourceResolver(ResourceResolver resourceResolver){
        this.innerResourceResolver = resourceResolver;
    }

    @Override
    public URL resolveUrl(String path) {
        System.out.println("Buscando la URL del recurso: " + path);
        URL result = null;

        if(path.endsWith(".test")){
            try{
                result = getUrlForResourceAsStream(path);
            }catch(Exception e){
                System.out.println("Unexpected error while obtaining the URL
from resource " + path);
                e.printStackTrace(System.out);
            }

        }else{
            result = this.innerResourceResolver.resolveUrl(path);
        }

        return result;
    }

    private URL getUrlForResourceAsStream(String path) throws
MalformedURLException {
        URLStreamHandler handler = new URLStreamHandler() {
            protected URLConnection openConnection(URL u) throws IOException
{
                final String file = u.getFile();
                return new URLConnection(u) {
                    public void connect() throws IOException {
                    }

                    public InputStream getInputStream() throws IOException {
                        System.out.println("Opening internal url to " +
file);

                        try{
                            System.out.println("Generando el InputStream de
la pagina:\n" + viewSource);
                            return new
ByteArrayInputStream(viewSource.getBytes("UTF-8"));
                        }catch (Exception e) {
                            e.printStackTrace();
                            throw new RuntimeException("Unexpected error
while obtaining the view", e);
                        }
                    }
                };
            }
        };
        return new URL("internal", null, 0, path, handler);
    }
}


As you can see, the code is very simple. When the suffix matches the pattern
".test", the Resolver creates a mock URL with a backing
ByteArrayInputStream. If the suffix does not matches the pattern, the normal
ResourceResolver is invoked.

With this configuration and code, when I request the URL:
http://xxxxxx:yyyy/zzzzz/anything.test
the application fails with error:

The problem is this:

java.lang.NullPointerException
    at java.lang.StringBuilder.<init>(StringBuilder.java:92)
    at
org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage.getRenderedViewId(FaceletViewDeclarationLanguage.java:1630)
    at
org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage.buildView(FaceletViewDeclarationLanguage.java:279)
    ....

The executes the viewHandler.createView("xxxx.test") method. It internally
calls the getViewHandlerSupport().calculateViewId(context, viewId); method
to obtain the viewId, and this method calls
DefaultViewHandlerSupport.checkResourceExists(FacesContext context, String
viewId), that checks the physical file of this resource, but there are not
any file for this resource!!!! so it return false, and the viewId of the
resulting ViewRoot is assigned to null.

This causes a NullPointerException later, when the code executes the
ViewDeclarationLanguage.buildView(FacesContext context, ViewRoot viewRoot).

If I change the Myfaces implementation with Mojarra 2.0.4, it works
perfectly, so I think that the problem is in the implementation.

I can't extend any class of interface of Myfaces, because my application
must not be coupled to a specific implementation.

I have attached two web projects, one with Myfaces configuration, that
fails, and the same project with Mojarra configuration, that works (Both
without the jars of the implementation)

How can I solve this?

Thanks

Reply via email to