Uploaded image for project: 'Shale'
  1. Shale
  2. SHALE-390

NPE in ComponentConfigBean$WatchDog.isDirty

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Major
    • Resolution: Fixed
    • 1.1.0-SNAPSHOT
    • 1.0.5
    • Clay
    • None
    • Debian 3.1 and Windows XP Prof.
      Tomcat 5.5.20

    Description

      2007-01-10 01:34:03,996 ERROR [org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/scn].[faces]] Servlet.service() for servlet faces threw exception
      java.lang.NullPointerException
      at org.apache.shale.clay.config.beans.ComponentConfigBean$WatchDog.isDirty(ComponentConfigBean.java:1248)
      at org.apache.shale.clay.config.beans.ComponentConfigBean$WatchDog.refresh(ComponentConfigBean.java:1276)
      at org.apache.shale.clay.config.beans.TemplateConfigBean.getElement(TemplateConfigBean.java:79)
      at org.apache.shale.clay.component.Clay.getRootElement(Clay.java:271)
      at org.apache.shale.clay.component.Clay.encodeBegin(Clay.java:314)
      at org.apache.shale.clay.component.Clay.recursiveRenderChildren(Clay.java:412)
      at org.apache.shale.clay.component.Clay.recursiveRenderChildren(Clay.java:415)
      at org.apache.shale.clay.component.Clay.recursiveRenderChildren(Clay.java:415)
      at org.apache.shale.clay.component.Clay.encodeChildren(Clay.java:444)
      at org.apache.shale.clay.component.Clay.recursiveRenderChildren(Clay.java:417)
      at org.apache.shale.clay.component.Clay.encodeChildren(Clay.java:444)
      at org.apache.shale.clay.faces.ClayViewHandler.recursiveRender(ClayViewHandler.java:468)
      at org.apache.shale.clay.faces.ClayViewHandler.renderView(ClayViewHandler.java:394)
      at org.apache.shale.view.faces.ViewViewHandler.renderView(ViewViewHandler.java:151)
      at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:384)
      at javax.faces.webapp.FacesServlet.service(FacesServlet.java:138)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
      at org.apache.shale.faces.ShaleApplicationFilter.doFilter(ShaleApplicationFilter.java:268)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
      at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:292)
      at org.acegisecurity.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:116)
      at org.acegisecurity.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:79)
      at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:303)
      at org.acegisecurity.ui.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:143)
      at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:303)
      at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:138)
      at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:303)
      at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:220)
      at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:303)
      at org.acegisecurity.securechannel.ChannelProcessingFilter.doFilter(ChannelProcessingFilter.java:168)
      at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:303)
      at org.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:173)
      at org.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:120)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
      at com.scn.web.common.filter.CharsetFilter.doFilter(CharsetFilter.java:45)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
      at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:199)
      at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:282)
      at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:744)
      at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:674)
      at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:866)
      at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
      at java.lang.Thread.run(Thread.java:595)

      ---------------------------------------------------------------------

      This NPE is probably caused by the WatchDog.refresh() method not being synchronized. This method opens and closes connections to the Clay config files, which means that one thread can open and another thread can close connections before the first one is done, causing connections to be null in the isDirty() method. I suppose that normally the ComponentConfigBean.refresh() method should be called as it synchronizes access to the WatchDog.refresh() method. However, the TemplateConfigBean.getElement() method, that is called in above stack trace, calls the WatchDog.refresh method directly without synchronizing access.

      Tried to turn off auto reloading of Clay config files with the org.apache.shale.clay.AUTO_RELOAD_CONFIG_FILES context parameter but didn't help as the WatchDog.refresh() method does not check this context parameter, only the ComponentConfigBean.refresh() method does so. Also, setting the AUTO_RELOAD_CONFIG_FILES to false in Shale 1.0.3, the version that we use, is not picked up by the ComponentConfigBean.

      I did a test and implemented new synchronization (watchDogs = Collections.synchronizedMap(new TreeMap());, displayElements = Collections.synchronizedMap(new HashMap(size));, public synchronized boolean WatchDog.refresh(boolean forceReload), public synchronized void ComponentConfigBean.assignParent(ComponentBean b) ) and removed all block synchronization which seemed to solve most of my problems. Did this in Shale 1.1.0 SNAPSHOT.
      However, the block synchronization is probably there for performance reasons I guess...

      ---------------------------------------------------------------------

      I used the following JUnit test to stress our home page:

      import junit.framework.TestCase;
      import org.apache.commons.httpclient.methods.GetMethod;
      import org.apache.commons.httpclient.HttpClient;
      import org.apache.commons.httpclient.HttpStatus;

      import java.io.IOException;
      import java.util.List;
      import java.util.ArrayList;

      public class StressTest extends TestCase {

      public void testStressWebSite()

      { ConcurrentTestDriver testDriver = new ConcurrentTestDriver( 10, new ConcurrentTask(100)); testDriver.start(); }

      private class ConcurrentTestDriver {
      List<Thread> threads = new ArrayList<Thread>();
      int numberOfThreads;
      ConcurrentTask concurrentTask;

      ConcurrentTestDriver(int threads,
      ConcurrentTask task)

      { numberOfThreads = threads; concurrentTask = task; }

      public void start() {
      // Create the threads
      for (int i=0; i<numberOfThreads; i++)

      { Thread thread = new Thread(concurrentTask); threads.add(thread); }

      // Start the threads
      for (Thread thread: threads)

      { thread.start(); }

      // Wait for all threads to finish
      for (Thread thread: threads) {
      try

      { thread.join(); }

      catch (InterruptedException e)

      { e.printStackTrace(); System.exit(12); }

      }
      }
      }

      private class ConcurrentTask implements Runnable {
      int testCaseRepeats;

      public ConcurrentTask(int repeats)

      { testCaseRepeats = repeats; }

      public void run() {
      GetMethod gm = new GetMethod("http://localhost:8080/scn");
      HttpClient hc = new HttpClient();

      for (int rep=0; rep<testCaseRepeats; rep++) {
      System.out.println(Thread.currentThread().getName()": Test # "(rep+1));
      try {
      int responseCode = hc.executeMethod(gm);

      if (responseCode != HttpStatus.SC_OK)

      { fail("response code: " + responseCode); }

      System.out.println(Thread.currentThread().getName()+": Response code = "+responseCode);
      } catch(IOException ioe)

      { fail("IOException: " + ioe.getMessage()); }

      try

      { long numMillisecondsToSleep = 10; Thread.sleep(numMillisecondsToSleep); }

      catch (InterruptedException e)

      { fail("InterruptedException: " + e.getMessage()); }

      }
      }
      }
      }

      Attachments

        Activity

          People

            gvanmatre@comcast.net Gary VanMatre
            gravitonian Martin Bergljung
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: