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