NPE in ComponentConfigBean$WatchDog.isDirty
-------------------------------------------

                 Key: SHALE-390
                 URL: https://issues.apache.org/struts/browse/SHALE-390
             Project: Shale
          Issue Type: Bug
          Components: Clay
    Affects Versions: 1.1.0-SNAPSHOT
         Environment: Debian 3.1 and Windows XP Prof.
Tomcat 5.5.20
            Reporter: Martin Bergljung


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());
                }
            }
        }
    }
}



-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: 
https://issues.apache.org/struts/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

Reply via email to