[
https://issues.apache.org/struts/browse/SHALE-390?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Gary VanMatre resolved SHALE-390.
---------------------------------
Resolution: Fixed
Fix Version/s: 1.1.0-SNAPSHOT
1.0.5-SNAPSHOT
Assignee: Gary VanMatre
Thanks for doing such detail analysis. The test case you provided allowed me
to easily recreate the problem. I applied the changes you suggested which
seemed to fix the problem.
This fix will be in the 20070225 nightly build.
> 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
> Assigned To: Gary VanMatre
> Fix For: 1.0.5-SNAPSHOT, 1.1.0-SNAPSHOT
>
>
> 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.
-
You can reply to this email to add a comment to the issue online.