Java and JBoss related stuff
RSS icon Home icon
  • Instant Facelets: changes in .xhtml and no redeploying

    Posted on December 7th, 2007 Adam Warski 10 comments

    If you are developing anything with Facelets/Seam/… frameworks, you probably know the pain of having to redeploy after each .xhtml file change to see the changes, even if they are only cosmetic. I wrote about possible solutions for that problem earlier, but they didn’t quite work for facelets (more specifically, templates didn’t get refreshed and any included pages).

    Of course, the best solution is to try JBoss Tools and Red Hat Developer Studio. However if you want to use IDEA, or some other IDE (vi? :) ), try the following.

    The trick is to tell Facelets to read the files from disk. Sounds simple, and Facelets have built-in mechanisms which make it simple.

    First, you have to implement the ResourceResolver interface:

    package org.jboss.shotoku.web;
    
    import com.sun.facelets.impl.ResourceResolver;
    
    import java.net.MalformedURLException;
    import java.net.URL;
    
    /**
     * @author Adam Warski
     */
    public class FilesystemResourceResolver implements ResourceResolver {
        public URL resolveUrl(String s) {
            try {
                return new URL("file", "",
                      "PATH_TO_FACELETS_FILES_GOES_HERE" + s);
            } catch (MalformedURLException e) {
                e.printStackTrace();
                return null;
            }
        }
    }

    and replace the path to your Facelets directory in the appropriate place (absolute path, for example /home/user/mygreatapp/view). (It is also easy to externalize that configuration using a context parameter.)
    Then, to your web.xml you have to add:

        <context-param>
            <param-name>facelets.DEVELOPMENT</param-name>
            <param-value>true</param-value>
        </context-param>
        <context-param>
            <param-name>facelets.REFRESH_PERIOD</param-name>
            <param-value>0</param-value>
        </context-param>
        <context-param>
            <param-name>facelets.RESOURCE_RESOLVER</param-name>
            <param-value>org.jboss.shotoku.web.FilesystemResourceResolver</param-value>
        </context-param>

    And you’re done! Try editing a .xhtml page (or template, or included page) and refreshing your browser.

    If you want also other resources to be read from disk (like css files), try the Resources Filter.

    Adam

     

    8 responses to “Instant Facelets: changes in .xhtml and no redeploying” RSS icon

    • It’s great feature ;)
      I use NetBeans and now I don’t use Total Commander for copy my .xhtml to glassfish :)

      In Seam tutorial is write that I can use hot deploy for Seam components. How I can implement it? I can hotdeploy only .xhtml, pages.xml files.
      I hope that I can use hotdeploy for EJB components :)

    • Hotdeploy is certainly is available in JBoss Developer Studio / JBoss Tools, but I don’t know if there are any means to use this feature outside of the eclipse ide. You’ll have to check there :)

    • icefaces-user

      Wow, that’s really great!
      I was desperately searching for such a possibility! Thanks!

    • any idea how to make it working with SEAM’s debug page?

    • What do you mean exactly? You want to swap the debug page?

    • Just try to browse:
      http://localhost:8080/seam_project/debug.jt

      It couses redirect loop with following errors (Seam 2.1.1, JBoss 5.0.1.GA):
      javax.servlet.ServletException: Servlet execution threw an exception
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:313)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
      at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83)
      at org.jboss.seam.web.IdentityFilter.doFilter(IdentityFilter.java:40)
      at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
      at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:90)
      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 org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45)
      at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
      at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:177)
      at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:267)
      at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:380)
      at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:507)
      at org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:56)
      at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
      at org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:58)
      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.servlet.SeamFilter.doFilter(SeamFilter.java:158)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
      at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
      at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)
      at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:433)
      at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)
      at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
      at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
      at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
      at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)
      at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:601)
      at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
      at java.lang.Thread.run(Thread.java:619)
      Caused by: java.lang.IllegalAccessError: com/sun/facelets/StateWriter
      at com.sun.facelets.StateWriterControl.initialize(StateWriterControl.java:18)
      at org.jboss.seam.debug.jsf.SeamDebugPhaseListener.beforePhase(SeamDebugPhaseListener.java:52)
      at com.sun.faces.lifecycle.Phase.handleBeforePhase(Phase.java:214)
      at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:96)
      at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
      at javax.faces.webapp.FacesServlet.service(FacesServlet.java:266)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
      … 41 more

    • Hello,
      no idea really … the stack trace doesn’t have anything from the filter. I’ve been using it in several projects and got no problems (needles to say, I was getting the debug page quite often ;) ) The only difference I can see is that I’ve been using JBoss 4, not 5, but that shouldn’t really impact Facelets. And the filter doesn’t do any redirects, it just returns an URL to the resource …
      Adam

    • it’s seam’s bug:
      https://jira.jboss.org/jira/browse/JBSEAM-4070


    2 Trackbacks / Pingbacks

    Leave a reply