tags:

views:

262

answers:

2

Hi all,

I am working on some UI Components that I would like to use entirely instead of writing the XHTML.

I am perfectly happy with XHTML; however, I want to break everything up into modules as well as break the physical connection between a URL and a file in a WAR or on the filesystem. I also want it to be entirely virtual so that I have greater control over security.

Is it possible to do this using a Servlet Filter? I am using Seam 2.2.0.GA and should have access to the FacesContext which means I will have access to the UIViewRoot component as well as render kit.

This is the latest error I'm getting - I am guessing I don't have my components properly configured:

java.lang.NullPointerException
    at com.sun.faces.context.FacesContextImpl.getRenderKit(FacesContextImpl.java:258)
    at com.sun.faces.renderkit.RenderKitUtils.getResponseStateManager(RenderKitUtils.java:237)
    at com.sun.faces.lifecycle.LifecycleImpl.reload(LifecycleImpl.java:331)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:134)
    at com.walterjwhite.seamCore.servlet.filter.FacesFilter.doFilter(FacesFilter.java:97)
    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
    at com.walterjwhite.webContent.servlet.filter.UploadedFileFilter.doFilter(UploadedFileFilter.java:97)
    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
    at com.walterjwhite.seamCore.servlet.filter.HttpRequestMonitoringFilter.doFilter(HttpRequestMonitoringFilter.java:59)
    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
    at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64)
    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
    at com.walterjwhite.seamCore.servlet.filter.ContextFilter$1.process(ContextFilter.java:60)
    at org.jboss.seam.servlet.ContextualHttpServletRequest.run(ContextualHttpServletRequest.java:53)
    at com.walterjwhite.seamCore.servlet.filter.ContextFilter.doFilter(ContextFilter.java:55)
    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:73)
    at org.jboss.seam.web.HotDeployFilter.doFilter(HotDeployFilter.java:53)
    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
    at org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:60)
    at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
    at org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1139)
    at com.walterjwhite.seamCore.servlet.filter.DisableUrlSessionFilter.doFilter(DisableUrlSessionFilter.java:82)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1139)
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:378)
    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:417)
    at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)
    at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at org.mortbay.jetty.Server.handle(Server.java:324)
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:535)
    at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:865)
    at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:539)
    at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
    at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
    at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:520)

Walter

A: 

You can definitely modify the component tree from a filter. Another technique is to build part of the page as jsf, then bind to a component such as a panel group layout & build the components inside it from a managed bean.

UIComponent parent = ...
for(...) {
   parent.getChildren().add(...);
}

The physical connection between URL & file is already broken. You can use a navigation rule to point to anything you want. Not sure what you mean by entirely virtual regarding security.

This is just my opinion, but a dynamic component approach is not as extensible as jsf & metadata.

Wayne Young
I agree with your comment about extensibility - for the bulk of my pages, they fit into a simple pattern. There are a few pages that are unique, require some navigation, but I don't want to handle those with my servlet filter, I'll let Seam/JSF do the work.I guess my question is, what actually does the grunt work in reading in the xhtml file in the war/filesystem? How does JSF know that an incoming request corresponds to a particular file and then process it?
A: 

Is it possible to do this using a Servlet Filter? I am using Seam 2.2.0.GA and should have access to the FacesContext which means I will have access to the UIViewRoot component as well as render kit.

A Filter is probably not a good place to do this. If memory serves, the FacesContext is set up and torn down in the FacesServlet in core JSF (you may know better than me if Seam requires other servlets to do some lifecycle lifting). So, the context will probably not be in scope in the filter.

Providing your own ViewHandler decorator would probably be a better bet. You can extend ViewHandlerWrapper and give it a constructor that takes the decorated ViewHandler from the framework. This can be defined in your faces-config.xml. You'll find more details in the spec.

McDowell
Actually - I just wrote a FacesFilter that appears to be working. I don't have my renderkits mapped so I got the exception there. However, it does appear to be working. I essentially copied the FacesServlet source code and modified it to work inside a filter. Seam also appears to work under this schema.
I will check into the ViewHandler ...
Be aware that the `FacesContext` is a thread-local artefact, so if you create one and then forward to `FacesServlet`, it'll get replaced when the `service` method creates one. I'm not sure if that would result in any undefined behaviour. If you're going to all this effort, consider just replacing the `FacesServlet` with your own implementation.
McDowell