3 Replies Latest reply on Dec 1, 2010 12:13 PM by Stan Silvert

    FacesContext is null for sharing jsfSession instance

    Dave Chen Master

      I tried to use one jsfSession instance for all tests in order to enable web caching of css and javascripts. After the first test, the JSF session is created. For the second test,  facesContext is null.

       

      JSFSession jsfSession = getJSFSession();  // singleton

      FacesContext facesContext = FacesContext.getCurrentInstance();

      or

      FacesContext facesContext = jsfSession.getJSFServerSession().getFacesContext();

       

      But from debug, the currentFacesContext in jsfSeverSession is not null.

      Is faesContext bound to server thread and will go away after the request is finished? But jsfunit docs says jsfSession keeps a reference to it.

       

      Thanks,

      Dave

        • 1. Re: FacesContext is null for sharing jsfSession instance
          Stan Silvert Master

          Yes, FacesContext is always bound to the server thread as per the JSF spec.  It has to be cleaned up at the end of each test to avoid a leak where one request gets a FacesContext from an old test.  The thing that is different in a JSFUnit test is that the FacesContext is actually kept around longer than it would normally be in a regular JSF request.  Once the JSF request is done the FacesContext is removed from the JSF request thread and bound to your test thread.  This allows you to do all the server-side assertions.  See JSFUnitSessionAndThreads for more details.

           

          As I indicated in the other discussion thread, I do think that your line of inquiry about caching CSS and javascript is a good one.  It would be great if you could do some profiling to see if that is really the bottleneck.  Then we can address the issue with HtmlUnit.

           

          Stan

          • 2. Re: FacesContext is null for sharing jsfSession instance
            Dave Chen Master

            Richfaces has a very large number of css/js to load and parse for each test. If they can be cached across tests, it would save a lots time. HtmlUnit has API: WebClient.setCache(Cache), but I am not sure if caching is enabled by default.  Based on my testing, jsf testing takes completely different time than clicking by hand.

             

            For example, a test:  login, click menu and create a record in database table.It takes about 6 seconds by hand. But it took JSFUnit/HtmlUnit more than 260 seconds, 40 times longer. From debug, when I step over  domNode.click(), it takes a long time to complete. This makes debugging very time consuming.

             

            For the logging, I set the property, but it can not prevent error level logging from emitting. I would like to disable HtmlUnit logging.

            System.getProperties().put("org.apache.commons.logging.simplelog.defaultlog", "error");

             

            Thanks,

            Dave

            • 3. Re: FacesContext is null for sharing jsfSession instance
              Stan Silvert Master

              You could do an experiment to see if the HtmlUnit Cache implementation can be reused for new instances of WebClient.  I'd be very interested to see how it turns out.  The code would do something like this:

               

              // make sure every WebClient uses the same Cache instance
              public class CacheRequestStrategy extends SimpleInitialRequestStrategy
              {
                 private Cache savedCache = null;
              
                 public Page doInitialRequest(WebClientSpec wcSpec) throws IOException {
                    WebClient webClient = wcSpec.getWebClient();
                    if (savedCache == null) {
                       savedCache = webClient.getCache();
                    }
              
                    webClient.setCache(savedCache);
                    return super.doInitialRequest(wcSpec);
                 }
              
              }
              
              public class MyTest extends ServletTestCase {
              
                 private InitialRequestStrategy cacheStrategy = new CacheRequestStrategy();
                 private JSFSession jsfSession;
              
                 public void setUp() throws Exception {
                    WebClientSpec wcSpec = new WebClientSpec("/index.jsf");
                    wcSpec.setInitialRequestStrategy(cacheStrategy);
                    this.jsfSession = new JSFSession(wcSpec);
                 }
              
                 public void testNumberOne() throws IOException  {  // both tests use same Cache }
              
                 public void testNumberTwo() throws IOException { // both tests use same Cache }
              }