I think I found the problem Matthias referred to. On line 139 in GroovyWeaver.groovy, I see the following line: WeavingContext.getRefreshContext().setRecompileRecommended(ScriptingConst.ENGINE_TYPE_JAVA, Boolean.FALSE);
If I change it into: WeavingContext.getRefreshContext().setRecompileRecommended(ScriptingConst.ENGINE_TYPE_GROOVY, Boolean.FALSE); ...the MyFaces 1.2 example works. I can commit it, as well as the other fix for EXTSCRIPT-27, but since I don't completely oversee the ext-scripting architecture, I thought I'll ask before doing anything. ;-) It looks like a bug. The MyFaces 2.0 example already works, because of the IntialScanAnnotationListener that's being invoked by MyFaces 2.0. The Spring example also didn't work, but I've changed the dependencies in the pom to be the same as in the MyFaces 1.2 pom. I didn't put much effort into it, but this is what I did: - add core-java6 - add myfaces12-extensions - remove the SNAPSHOT from the myfaces dependencies I'll also commented on the JIRA issue and attached a patch, containing all this stuff. /JK 2009/12/13 Jan-Kees van Andel <[email protected]>: > Hey, > > As promised, I've been testing on my Vista machine. Bernhard was right > about the slashes. I needed to double escape them on some places. > > I also changed the paths in my web.xml to point to my workspace, but > I'm not sure what this does, since these are also the default paths > (at least, that's what my debugger is telling me). > > The MF2.0 examples now work fine. However, the MF1.2 examples don't. > When loading the MF1.2 test page, I get an exception in my console. > > Some things: > - A temp dir is used for storing the compiled classes. When running > mvn clean install, I see some test cases putting compiled classes > there. The MF2.0 example also produces class files, but the MF1.2 > example is not. And that leads to an exception in ClassUtils.java#77, > because the File points to a non existent file. > - The _scanner field in JavaScriptingWeaver is null in the MF1.2 > example. I'm sure this is by design, but while debugging, I see it > passing a lot of null checks on this field. > - I use mvn jetty:run to run the examples. > > I've attached my console log (startup and one page request). It might be > useful. > > /JK > > Ps. Werner, do you want me to commit my slash fixes? > > > [INFO] Scanning for projects... > [INFO] > ------------------------------------------------------------------------ > [INFO] Building A custom project using myfaces > [INFO] task-segment: [org.mortbay.jetty:maven-jetty-plugin:6.1.1:run] > [INFO] > ------------------------------------------------------------------------ > [INFO] Preparing jetty:run > [INFO] [resources:resources] > [WARNING] Using platform encoding (windows-1252 actually) to copy > filtered resources, i.e. build is platform dependent! > [INFO] skip non existing resourceDirectory > D:\dev\work\ideaprojects\threads\extscript\examples\myfaces12-example\src\main\resources > [INFO] [compiler:compile] > [INFO] Nothing to compile - all classes are up to date > [INFO] [jetty:run] > [INFO] Configuring Jetty for project: A custom project using myfaces > [INFO] Webapp source directory = > D:\dev\work\ideaprojects\threads\extscript\examples\myfaces12-example\src\main\webapp > [INFO] web.xml file = > D:\dev\work\ideaprojects\threads\extscript\examples\myfaces12-example\src\main\webapp\WEB-INF\web.xml > [INFO] Classes = > D:\dev\work\ideaprojects\threads\extscript\examples\myfaces12-example\target\classes > 2009-12-13 15:17:52.901::INFO: Logging to STDERR via > org.mortbay.log.StdErrLog > [INFO] Context path = /myfaces12-example > [INFO] Tmp directory = > D:\dev\work\ideaprojects\threads\extscript\examples\myfaces12-example\target\work > [INFO] Web defaults = jetty default > [INFO] Web overrides = none > [INFO] Webapp directory = > D:\dev\work\ideaprojects\threads\extscript\examples\myfaces12-example\src\main\webapp > 2009-12-13 15:17:52.983::INFO: jetty-6.1.1 > [INFO] Starting jetty 6.1.1 ... > [INFO] Classpath = > [file:/D:/dev/work/ideaprojects/threads/extscript/examples/myfaces12-example/target/classes/, > file:/D:/dev/maven-repo/org/codehaus/groovy/groovy-all/1.5.6/groovy-all-1.5.6.jar, > file:/D:/dev/maven-repo/org/apache/ant/ant/1.7.0/ant-1.7.0.jar, > file:/D:/dev/maven-repo/org/apache/ant/ant-launcher/1.7.0/ant-launcher-1.7.0.jar, > file:/D:/dev/maven-repo/jline/jline/0.9.94/jline-0.9.94.jar, > file:/D:/dev/maven-repo/org/apache/myfaces/extension-scripting/core/1.0-SNAPSHOT/core-1.0-SNAPSHOT.jar, > file:/D:/dev/maven-repo/commons-beanutils/commons-beanutils/1.8.0/commons-beanutils-1.8.0.jar, > file:/D:/dev/maven-repo/commons-logging/commons-logging/1.0.4/commons-logging-1.0.4.jar, > file:/D:/dev/maven-repo/asm/asm/3.2/asm-3.2.jar, > file:/D:/dev/maven-repo/commons-lang/commons-lang/2.1/commons-lang-2.1.jar, > file:/D:/dev/maven-repo/commons-validator/commons-validator/1.2.0/commons-validator-1.2.0.jar, > file:/D:/dev/maven-repo/commons-digester/commons-digester/1.8/commons-digester-1.8.jar, > file:/D:/dev/maven-repo/commons-collections/commons-collections/3.1/commons-collections-3.1.jar, > file:/D:/dev/maven-repo/xml-apis/xml-apis/1.0.b2/xml-apis-1.0.b2.jar, > file:/D:/dev/maven-repo/oro/oro/2.0.8/oro-2.0.8.jar, > file:/D:/dev/maven-repo/commons-el/commons-el/1.0/commons-el-1.0.jar, > file:/D:/dev/maven-repo/commons-codec/commons-codec/1.3/commons-codec-1.3.jar, > file:/D:/dev/maven-repo/velocity/velocity/1.5/velocity-1.5.jar, > file:/D:/dev/maven-repo/org/apache/commons/commons-jci-javac/1.0/commons-jci-javac-1.0.jar, > file:/D:/dev/maven-repo/org/apache/commons/commons-jci-core/1.0/commons-jci-core-1.0.jar, > file:/D:/dev/maven-repo/org/apache/commons/commons-jci-fam/1.0/commons-jci-fam-1.0.jar, > file:/D:/dev/maven-repo/commons-logging/commons-logging-api/1.1/commons-logging-api-1.1.jar, > file:/D:/dev/maven-repo/commons-io/commons-io/1.3.1/commons-io-1.3.1.jar, > file:/D:/dev/maven-repo/org/vafer/dependency/0.2/dependency-0.2.jar, > file:/D:/dev/maven-repo/asm/asm-commons/2.2.1/asm-commons-2.2.1.jar, > file:/D:/dev/maven-repo/asm/asm-util/2.2.1/asm-util-2.2.1.jar, > file:/D:/dev/maven-repo/asm/asm-analysis/2.2.1/asm-analysis-2.2.1.jar, > file:/D:/dev/maven-repo/asm/asm-tree/2.2.1/asm-tree-2.2.1.jar, > file:/D:/dev/maven-repo/asm/asm-attrs/2.2.1/asm-attrs-2.2.1.jar, > file:/D:/dev/maven-repo/org/apache/myfaces/extension-scripting/core-java6/1.0-SNAPSHOT/core-java6-1.0-SNAPSHOT.jar, > file:/D:/dev/maven-repo/org/apache/myfaces/extension-scripting/myfaces12-extensions/1.0-SNAPSHOT/myfaces12-extensions-1.0-SNAPSHOT.jar, > file:/D:/dev/maven-repo/org/apache/myfaces/core/myfaces-api/1.2.8/myfaces-api-1.2.8.jar, > file:/D:/dev/maven-repo/org/apache/myfaces/core/myfaces-impl/1.2.8/myfaces-impl-1.2.8.jar, > file:/D:/dev/maven-repo/commons-discovery/commons-discovery/0.4/commons-discovery-0.4.jar, > file:/D:/dev/maven-repo/javax/portlet/portlet-api/1.0/portlet-api-1.0.jar, > file:/D:/dev/maven-repo/com/sun/facelets/jsf-facelets/1.1.11/jsf-facelets-1.1.11.jar, > file:/D:/dev/maven-repo/jstl/jstl/1.2/jstl-1.2.jar, > file:/D:/dev/maven-repo/org/apache/myfaces/tomahawk/tomahawk/1.1.6/tomahawk-1.1.6.jar, > file:/D:/dev/maven-repo/commons-fileupload/commons-fileupload/1.0/commons-fileupload-1.0.jar] > 13-dec-2009 15:17:53 > org.apache.myfaces.webapp.StartupServletContextListener > dispatchInitializationEvent > INFO: Checking for plugins:org.apache.myfaces.FACES_INIT_PLUGINS > 13-dec-2009 15:17:53 > org.apache.myfaces.webapp.StartupServletContextListener > dispatchInitializationEvent > INFO: Plugins found > 13-dec-2009 15:17:53 > org.apache.myfaces.webapp.StartupServletContextListener > dispatchInitializationEvent > INFO: Processing > plugin:org.apache.myfaces.scripting.servlet.StartupServletContextPluginChainLoader > 13-dec-2009 15:17:53 > org.apache.myfaces.scripting.servlet.StartupServletContextPluginChainLoader > preInit > INFO: [EXT-SCRIPTING] Instantiating StartupServletContextPluginChainLoader > 13-dec-2009 15:17:53 > org.apache.myfaces.scripting.servlet.StartupServletContextPluginChainLoader > preInit > INFO: [EXT-SCRIPTING] Compiling all sources for the first time > 13-dec-2009 15:17:53 > org.apache.myfaces.webapp.StartupServletContextListener > dispatchInitializationEvent > INFO: Processing plugins done > 13-dec-2009 15:17:53 > org.apache.myfaces.shared_impl.config.MyfacesConfig > getBooleanInitParameter > INFO: No context init parameter > 'org.apache.myfaces.RENDER_CLEAR_JAVASCRIPT_FOR_BUTTON' found, using > default value false > 13-dec-2009 15:17:53 > org.apache.myfaces.shared_impl.config.MyfacesConfig > getBooleanInitParameter > INFO: No context init parameter > 'org.apache.myfaces.SAVE_FORM_SUBMIT_LINK_IE' found, using default > value false > 13-dec-2009 15:17:53 > org.apache.myfaces.shared_impl.config.MyfacesConfig > getBooleanInitParameter > INFO: No context init parameter > 'org.apache.myfaces.RENDER_VIEWSTATE_ID' found, using default value > true > 13-dec-2009 15:17:53 > org.apache.myfaces.shared_impl.config.MyfacesConfig > getBooleanInitParameter > INFO: No context init parameter > 'org.apache.myfaces.STRICT_XHTML_LINKS' found, using default value > true > 13-dec-2009 15:17:53 > org.apache.myfaces.shared_impl.config.MyfacesConfig > getLongInitParameter > INFO: No context init parameter > 'org.apache.myfaces.CONFIG_REFRESH_PERIOD' found, using default value > 2 > 13-dec-2009 15:17:53 > org.apache.myfaces.shared_impl.config.MyfacesConfig > getBooleanInitParameter > INFO: No context init parameter > 'org.apache.myfaces.VIEWSTATE_JAVASCRIPT' found, using default value > false > 13-dec-2009 15:17:53 > org.apache.myfaces.shared_impl.config.MyfacesConfig > createAndInitializeMyFacesConfig > INFO: Starting up Tomahawk on the MyFaces-JSF-Implementation > 13-dec-2009 15:17:53 org.apache.myfaces.config.FacesConfigurator > feedStandardConfig > INFO: Reading standard config META-INF/standard-faces-config.xml > 13-dec-2009 15:17:54 org.apache.myfaces.config.FacesConfigurator > feedClassloaderConfigurations > INFO: Reading config : > jar:file:/D:/dev/maven-repo/com/sun/facelets/jsf-facelets/1.1.11/jsf-facelets-1.1.11.jar!/META-INF/faces-config.xml > 13-dec-2009 15:17:54 org.apache.myfaces.config.FacesConfigurator > feedClassloaderConfigurations > INFO: Reading config : > jar:file:/D:/dev/maven-repo/org/apache/myfaces/extension-scripting/core/1.0-SNAPSHOT/core-1.0-SNAPSHOT.jar!/META-INF/faces-config.xml > 13-dec-2009 15:17:54 org.apache.myfaces.config.FacesConfigurator > feedClassloaderConfigurations > INFO: Reading config : > jar:file:/D:/dev/maven-repo/org/apache/myfaces/extension-scripting/myfaces12-extensions/1.0-SNAPSHOT/myfaces12-extensions-1.0-SNAPSHOT.jar!/META-INF/faces-config.xml > 13-dec-2009 15:17:54 org.apache.myfaces.config.FacesConfigurator > feedClassloaderConfigurations > INFO: Reading config : > jar:file:/D:/dev/maven-repo/org/apache/myfaces/tomahawk/tomahawk/1.1.6/tomahawk-1.1.6.jar!/META-INF/faces-config.xml > 13-dec-2009 15:17:54 org.apache.myfaces.config.FacesConfigurator > feedWebAppConfig > INFO: Reading config /WEB-INF/faces-config.xml > 13-dec-2009 15:17:54 org.apache.myfaces.config.FacesConfigurator startLib > INFO: Starting up MyFaces-package : myfaces-api in version : 1.2.8 > from path : > file:/D:/dev/maven-repo/org/apache/myfaces/core/myfaces-api/1.2.8/myfaces-api-1.2.8.jar > 13-dec-2009 15:17:54 org.apache.myfaces.config.FacesConfigurator startLib > INFO: Starting up MyFaces-package : myfaces-impl in version : 1.2.8 > from path : > file:/D:/dev/maven-repo/org/apache/myfaces/core/myfaces-impl/1.2.8/myfaces-impl-1.2.8.jar > 13-dec-2009 15:17:54 org.apache.myfaces.config.FacesConfigurator startLib > INFO: Starting up MyFaces-package : tomahawk in version : 1.1.6 from > path : > file:/D:/dev/maven-repo/org/apache/myfaces/tomahawk/tomahawk/1.1.6/tomahawk-1.1.6.jar > 13-dec-2009 15:17:54 org.apache.myfaces.config.FacesConfigurator startLib > INFO: MyFaces-package : tomahawk12 not found. > 13-dec-2009 15:17:54 org.apache.myfaces.config.FacesConfigurator startLib > INFO: MyFaces-package : tomahawk-sandbox not found. > 13-dec-2009 15:17:54 org.apache.myfaces.config.FacesConfigurator startLib > INFO: MyFaces-package : tomahawk-sandbox12 not found. > 13-dec-2009 15:17:54 org.apache.myfaces.config.FacesConfigurator startLib > INFO: MyFaces-package : tomahawk-sandbox15 not found. > 13-dec-2009 15:17:54 org.apache.myfaces.config.FacesConfigurator startLib > INFO: MyFaces-package : myfaces-orchestra-core not found. > 13-dec-2009 15:17:54 org.apache.myfaces.config.FacesConfigurator startLib > INFO: MyFaces-package : myfaces-orchestra-core12 not found. > 13-dec-2009 15:17:54 org.apache.myfaces.config.FacesConfigurator startLib > INFO: MyFaces-package : trinidad-api not found. > 13-dec-2009 15:17:54 org.apache.myfaces.config.FacesConfigurator startLib > INFO: MyFaces-package : trinidad-impl not found. > 13-dec-2009 15:17:54 org.apache.myfaces.config.FacesConfigurator startLib > INFO: MyFaces-package : tobago not found. > 13-dec-2009 15:17:54 org.apache.myfaces.config.FacesConfigurator startLib > INFO: Starting up MyFaces-package : commons-el in version : 1.0 from > path : file:/d:/dev/maven-repo/commons-el/commons-el/1.0/commons-el-1.0.jar > 13-dec-2009 15:17:54 org.apache.myfaces.config.FacesConfigurator startLib > INFO: MyFaces-package : jsp-api not found. > 13-dec-2009 15:17:54 sun.reflect.NativeMethodAccessorImpl invoke0 > INFO: [EXT-SCRIPTING] Loading Groovy > file:org\apache\myfaces\groovyloader\test\TestNavigationHandler.groovy > 13-dec-2009 15:17:54 org.apache.myfaces.shared_impl.util.LocaleUtils toLocale > WARNING: Locale name in faces-config.xml null or empty, setting locale > to default locale : nl_NL > 13-dec-2009 15:17:54 sun.reflect.NativeMethodAccessorImpl invoke0 > INFO: [EXT-SCRIPTING] Loading Groovy > file:org\apache\myfaces\groovyloader\test\TestComponent.groovy > 13-dec-2009 15:17:54 sun.reflect.NativeMethodAccessorImpl invoke0 > INFO: [EXT-SCRIPTING] Loading Groovy > file:org\apache\myfaces\groovyloader\test\TestConverter.groovy > 13-dec-2009 15:17:54 sun.reflect.NativeMethodAccessorImpl invoke0 > INFO: [EXT-SCRIPTING] Loading Groovy > file:org\apache\myfaces\groovyloader\test\TestValidator.groovy > 13-dec-2009 15:17:55 sun.reflect.NativeMethodAccessorImpl invoke0 > INFO: [EXT-SCRIPTING] Loading Groovy > file:org\apache\myfaces\groovyloader\test\TestRenderer.groovy > 13-dec-2009 15:17:55 sun.reflect.NativeMethodAccessorImpl invoke0 > INFO: [EXT-SCRIPTING] Loading Groovy > file:org\apache\myfaces\groovyloader\test\TestPhaseListener.groovy > 13-dec-2009 15:17:55 org.apache.myfaces.config.FacesConfigurator > handleSerialFactory > INFO: Serialization provider : class > org.apache.myfaces.shared_impl.util.serial.DefaultSerialFactory > 13-dec-2009 15:17:55 sun.reflect.NativeMethodAccessorImpl invoke0 > INFO: [EXT-SCRIPTING] Loading Groovy > file:org\apache\myfaces\groovyloader\blog\Blog.groovy > 13-dec-2009 15:17:55 > org.apache.myfaces.scripting.loaders.java.JavaScriptingWeaver > loadScriptingClassFromFile > INFO: [EXT-SCRIPTING] Loading Java > file:org\apache\myfaces\javaloader\blog\BlogService.java > 13-dec-2009 15:17:55 > org.apache.myfaces.scripting.loaders.java.JavaScriptingWeaver > loadScriptingClassFromFile > INFO: [EXT-SCRIPTING] Loading Java > file:org\apache\myfaces\javaloader\test\TestBean2.java > 13-dec-2009 15:17:55 > org.apache.myfaces.scripting.loaders.java.JavaScriptingWeaver > loadScriptingClassFromFile > INFO: [EXT-SCRIPTING] Loading Java > file:org\apache\myfaces\javaloader\blog\Blog.java > 13-dec-2009 15:17:55 sun.reflect.NativeMethodAccessorImpl invoke0 > INFO: [EXT-SCRIPTING] Loading Groovy > file:org\apache\myfaces\groovyloader\test\TestBean.groovy > 13-dec-2009 15:17:55 sun.reflect.NativeMethodAccessorImpl invoke0 > INFO: [EXT-SCRIPTING] Loading Groovy > file:org\apache\myfaces\groovyloader\blog\BlogService.groovy > 13-dec-2009 15:17:55 > org.apache.myfaces.webapp.AbstractFacesInitializer validateFacesConfig > WARNING: File for navigation 'from id' does not exist > D:\dev\work\ideaprojects\threads\extscript\examples\myfaces12-example\src\main\webapp\/helloWorld.jsp > 13-dec-2009 15:17:55 > org.apache.myfaces.webapp.AbstractFacesInitializer validateFacesConfig > WARNING: File for navigation 'to id' does not exist > D:\dev\work\ideaprojects\threads\extscript\examples\myfaces12-example\src\main\webapp\/page2.jsp > 13-dec-2009 15:17:55 > org.apache.myfaces.webapp.AbstractFacesInitializer validateFacesConfig > WARNING: File for navigation 'from id' does not exist > D:\dev\work\ideaprojects\threads\extscript\examples\myfaces12-example\src\main\webapp\/page2.jsp > 13-dec-2009 15:17:55 > org.apache.myfaces.webapp.AbstractFacesInitializer validateFacesConfig > WARNING: File for navigation 'to id' does not exist > D:\dev\work\ideaprojects\threads\extscript\examples\myfaces12-example\src\main\webapp\/helloWorld.jsp > 13-dec-2009 15:17:55 > org.apache.myfaces.webapp.AbstractFacesInitializer validateFacesConfig > WARNING: Could not locate class > org.apache.myfaces.javaloader.blog.BlogService for managed bean > 'javaBlogService' > 13-dec-2009 15:17:55 > org.apache.myfaces.webapp.AbstractFacesInitializer validateFacesConfig > WARNING: Could not locate class > org.apache.myfaces.javaloader.test.TestBean2 for managed bean > 'javatestbean' > 13-dec-2009 15:17:55 > org.apache.myfaces.webapp.AbstractFacesInitializer validateFacesConfig > WARNING: Could not locate class > org.apache.myfaces.javaloader.blog.Blog for managed bean > 'javaBlogView' > 13-dec-2009 15:17:55 > org.apache.myfaces.webapp.AbstractFacesInitializer initFaces > INFO: ServletContext > 'D:\dev\work\ideaprojects\threads\extscript\examples\myfaces12-example\src\main\webapp\' > initialized. > 13-dec-2009 15:17:55 > org.apache.myfaces.webapp.StartupServletContextListener > dispatchInitializationEvent > INFO: Processing > plugin:org.apache.myfaces.scripting.servlet.StartupServletContextPluginChainLoader > 13-dec-2009 15:17:55 > org.apache.myfaces.webapp.StartupServletContextListener > dispatchInitializationEvent > INFO: Processing plugins done > 13-dec-2009 15:17:55 > org.apache.myfaces.webapp.StartupServletContextListener > contextInitialized > INFO: MyFaces already initialized > 2009-12-13 15:17:55.649::INFO: Started SelectChannelConnector @ 0.0.0.0:9090 > [INFO] Started Jetty Server > [INFO] Starting scanner at interval of 1 seconds. > 13-dec-2009 15:18:09 com.sun.facelets.compiler.TagLibraryConfig loadImplicit > INFO: Added Library from: > jar:file:/D:/dev/maven-repo/com/sun/facelets/jsf-facelets/1.1.11/jsf-facelets-1.1.11.jar!/META-INF/jstl-fn.taglib.xml > 13-dec-2009 15:18:09 com.sun.facelets.compiler.TagLibraryConfig loadImplicit > INFO: Added Library from: > jar:file:/D:/dev/maven-repo/com/sun/facelets/jsf-facelets/1.1.11/jsf-facelets-1.1.11.jar!/META-INF/jsf-html.taglib.xml > 13-dec-2009 15:18:09 com.sun.facelets.compiler.TagLibraryConfig loadImplicit > INFO: Added Library from: > jar:file:/D:/dev/maven-repo/com/sun/facelets/jsf-facelets/1.1.11/jsf-facelets-1.1.11.jar!/META-INF/jsf-ui.taglib.xml > 13-dec-2009 15:18:09 com.sun.facelets.compiler.TagLibraryConfig loadImplicit > INFO: Added Library from: > jar:file:/D:/dev/maven-repo/com/sun/facelets/jsf-facelets/1.1.11/jsf-facelets-1.1.11.jar!/META-INF/jsf-core.taglib.xml > 13-dec-2009 15:18:09 com.sun.facelets.compiler.TagLibraryConfig loadImplicit > INFO: Added Library from: > jar:file:/D:/dev/maven-repo/com/sun/facelets/jsf-facelets/1.1.11/jsf-facelets-1.1.11.jar!/META-INF/jstl-core.taglib.xml > 13-dec-2009 15:18:10 > org.apache.myfaces.config.annotation.DefaultLifecycleProviderFactory > getLifecycleProvider > INFO: Using LifecycleProvider > org.apache.myfaces.config.annotation.ResourceAnnotationLifecycleProvider > 13-dec-2009 15:18:10 > org.apache.myfaces.scripting.loaders.java.JavaScriptingWeaver > loadScriptingClassFromFile > INFO: [EXT-SCRIPTING] Loading Java > file:org\apache\myfaces\javaloader\test\TestBean2.java > 13-dec-2009 15:18:10 com.sun.facelets.FaceletViewHandler handleRenderException > SEVERE: Error Rendering View[/helloWorld.xhtml] > javax.faces.FacesException: Exception while calling encodeEnd on > component : {Component-Path : [Class: > javax.faces.component.UIViewRoot,ViewId: /helloWorld.xhtml][Class: > javax.faces.component.html.HtmlForm,Id: form][Class: > javax.faces.component.html.HtmlPanelGrid,Id: grid]} > at > javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:627) > at javax.faces.component.UIComponent.encodeAll(UIComponent.java:261) > at javax.faces.component.UIComponent.encodeAll(UIComponent.java:257) > at javax.faces.component.UIComponent.encodeAll(UIComponent.java:257) > at > com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:578) > at > org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:41) > at > org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:140) > at > org.apache.myfaces.scripting.jsf.dynamicdecorators.implemetations.LifefcycleProxy.render(LifefcycleProxy.java:75) > at javax.faces.webapp.FacesServlet.service(FacesServlet.java:182) > at > org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:491) > at > org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1074) > at > org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:147) > at > org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1065) > at > org.apache.myfaces.scripting.servlet.ScriptingServletFilter.doFilter(ScriptingServletFilter.java:48) > at > org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1065) > at > org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:365) > at > org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:185) > at > org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181) > at > org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:689) > at > org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:391) > at > org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:146) > at > org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114) > at > org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:139) > at org.mortbay.jetty.Server.handle(Server.java:285) > at > org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:457) > at > org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:751) > at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:500) > at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:209) > at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:357) > at > org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:329) > at > org.mortbay.thread.BoundedThreadPool$PoolThread.run(BoundedThreadPool.java:475) > Caused by: javax.faces.FacesException: Exception while calling > encodeEnd on component : {Component-Path : [Class: > javax.faces.component.UIViewRoot,ViewId: /helloWorld.xhtml][Class: > javax.faces.component.html.HtmlForm,Id: form][Class: > javax.faces.component.html.HtmlPanelGrid,Id: grid][Class: > javax.faces.component.html.HtmlOutputFormat,Id: j_id6]} > at > javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:627) > at > org.apache.myfaces.shared_impl.renderkit.RendererUtils.renderChild(RendererUtils.java:534) > at > org.apache.myfaces.shared_impl.renderkit.html.HtmlGridRendererBase.renderChildren(HtmlGridRendererBase.java:231) > at > org.apache.myfaces.shared_impl.renderkit.html.HtmlGridRendererBase.encodeEnd(HtmlGridRendererBase.java:102) > at > javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:624) > ... 30 more > Caused by: javax.faces.FacesException: Could not retrieve value of > component with path : {Component-Path : [Class: > javax.faces.component.UIViewRoot,ViewId: /helloWorld.xhtml][Class: > javax.faces.component.html.HtmlForm,Id: form][Class: > javax.faces.component.html.HtmlPanelGrid,Id: grid][Class: > javax.faces.component.html.HtmlOutputFormat,Id: j_id6]} > at > org.apache.myfaces.shared_impl.renderkit.RendererUtils.getValue(RendererUtils.java:343) > at > org.apache.myfaces.shared_impl.renderkit.RendererUtils.getStringValue(RendererUtils.java:291) > at > org.apache.myfaces.renderkit.html.HtmlFormatRenderer.getOutputFormatText(HtmlFormatRenderer.java:89) > at > org.apache.myfaces.renderkit.html.HtmlFormatRenderer.encodeEnd(HtmlFormatRenderer.java:73) > at > javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:624) > ... 34 more > Caused by: javax.faces.FacesException: > java.lang.ClassNotFoundException: > org.apache.myfaces.javaloader.test.TestBean2 > at > org.apache.myfaces.config.ManagedBeanBuilder.buildManagedBean(ManagedBeanBuilder.java:160) > at > org.apache.myfaces.el.unified.resolver.ManagedBeanResolver.createManagedBean(ManagedBeanResolver.java:198) > at > org.apache.myfaces.el.unified.resolver.ManagedBeanResolver.getValue(ManagedBeanResolver.java:164) > at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:143) > at > org.apache.myfaces.el.unified.resolver.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:140) > at > org.apache.myfaces.scripting.jsf.dynamicdecorators.implemetations.ELResolverProxy.getValue(ELResolverProxy.java:55) > at > org.apache.myfaces.el.VariableResolverImpl.resolveVariable(VariableResolverImpl.java:64) > at > org.apache.myfaces.el.convert.VariableResolverToELResolver.getValue(VariableResolverToELResolver.java:95) > at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:143) > at > org.apache.myfaces.el.unified.resolver.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:140) > at > org.apache.myfaces.scripting.jsf.dynamicdecorators.implemetations.ELResolverProxy.getValue(ELResolverProxy.java:55) > at com.sun.el.parser.AstIdentifier.getValue(AstIdentifier.java:68) > at com.sun.el.parser.AstValue.getValue(AstValue.java:107) > at > com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:192) > at > com.sun.facelets.el.TagValueExpression.getValue(TagValueExpression.java:71) > at javax.faces.component.UIOutput.getValue(UIOutput.java:73) > at > org.apache.myfaces.shared_impl.renderkit.RendererUtils.getValue(RendererUtils.java:339) > ... 38 more > Caused by: java.lang.ClassNotFoundException: > org.apache.myfaces.javaloader.test.TestBean2 > at java.net.URLClassLoader$1.run(URLClassLoader.java:200) > at java.security.AccessController.doPrivileged(Native Method) > at java.net.URLClassLoader.findClass(URLClassLoader.java:188) > at java.lang.ClassLoader.loadClass(ClassLoader.java:307) > at > org.codehaus.classworlds.RealmClassLoader.loadClassDirect(RealmClassLoader.java:195) > at > org.codehaus.classworlds.DefaultClassRealm.loadClass(DefaultClassRealm.java:255) > at > org.codehaus.classworlds.DefaultClassRealm.loadClass(DefaultClassRealm.java:274) > at > org.codehaus.classworlds.RealmClassLoader.loadClass(RealmClassLoader.java:214) > at java.lang.ClassLoader.loadClass(ClassLoader.java:252) > at > org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:363) > at > org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:325) > at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320) > at java.lang.Class.forName0(Native Method) > at java.lang.Class.forName(Class.java:247) > at > org.apache.myfaces.shared_impl.util.ClassUtils.classForName(ClassUtils.java:176) > at > org.apache.myfaces.config.annotation.NoInjectionAnnotationLifecycleProvider.newInstance(NoInjectionAnnotationLifecycleProvider.java:44) > at > org.apache.myfaces.config.ManagedBeanBuilder.buildManagedBean(ManagedBeanBuilder.java:85) > ... 54 more > 13-dec-2009 15:18:10 > org.apache.myfaces.scripting.loaders.java.JavaScriptingWeaver > loadScriptingClassFromFile > INFO: [EXT-SCRIPTING] Loading Java > file:org\apache\myfaces\javaloader\test\TestBean2.java > org.apache.myfaces.groovyloader.test.testrende...@14ef239restoring a > view bbb bbbRENDER_RESPONSE(6) > 13-dec-2009 15:18:10 > org.apache.myfaces.shared_tomahawk.config.MyfacesConfig > getCurrentInstance > INFO: Starting up Tomahawk on the MyFaces-JSF-Implementation > 13-dec-2009 15:18:10 > org.apache.myfaces.renderkit.html.util.ReducedHTMLParser parse > WARNING: Invalid tag found: unexpected input while looking for attr > name or '/>' at line 431 > > > > > 2009/12/12 Bernhard Huemer <[email protected]>: >>> What about following hypothetical case >>> >>> >>> private void doSomething() { >>> .. long running >>> C myVar = appContext.getBean("C"); >>> .. long running >>> } >> >> Okay, first of all, yes, that will eventually result in a >> ClassCastException, but there is a different reason for that. If you >> "circumvent" dependency management, well then, sorry, there's no way to get >> to know that dependency then. However, the cause of this problem is not a >> race condition, it's just missing information. So basically it will always >> raise an exception, regardless of how many more requests the user initiates >> (i.e. the only "advantage" that synchronizing requests has in this case is >> that it won't fail for that particular request, but it will fail for the >> following ones as well). >> >> regards, >> Bernhard >> >> Werner Punz wrote on 12/12/2009 08:00 PM (GMT): >>> >>> Bernhard Huemer schrieb: >>>> >>>> Okay, I'll tell you how that works in my case, though I'm not really sure >>>> if I got your example entirely right (in fact I am most probably mistaken). >>>> The thing is if class A somehow references class C, C already has to be >>>> loaded at that time - you cannot even load the class A otherwise. Now if >>>> the >>>> developer modifies the class C, obviously the daemon thread will notify the >>>> system to refresh all relevant beans. If it turns out, that there is a >>>> relevant bean of a different class (e.g. the relevant bean somehow has a >>>> dependency on something that is of the type C), the system will tell the >>>> reloading class loader in my case to forcefully reload that particular >>>> class >>>> (i.e. assuming that the relevant bean is an instance of the class A, it >>>> will >>>> also reload A again, regardless of whether the source actually changed or >>>> not). The purpose of this forceful reload is to correct linkage >>>> dependencies, i.e. if the class A on its own depends on class C (e.g. >>>> there's a setter setC(C c)), it will reload A just in order to ensure that >>>> it's using the correct version of C. >>>> >>> Well I do the same but I drop just the beans for not having the same >>> control as you have in spring. >>> >>> As far as I know your system that only works on spring level and do you >>> put the requests on hold while the object and class refresh happens? >>> >>> What about following hypothetical case >>> >>> >>> private void doSomething() { >>> .. long running >>> C myVar = appContext.getBean("C"); >>> .. long running >>> } >>> >>> >>> >>> Now lets assume following case: >>> A is currently processing doSomething, the compile is in full process >>> and has compiled C, you load C via the app context, the running A >>> then assignes a new class of C to the old C myVar and you run into >>> the famous classcast exception. >>> >>> I am in this case somewhat safe in single user environments because >>> the refresh happens synchronously, and I still think that either >>> synchrionizing the compile operation between requests is the cheapest way to >>> go to prevent a situation like that. >>> >>> >>> >>> So there are either two chances, you have to find a way that doSomething >>> does not start in the first case or you have to wait until doSomething has >>> stopped before doing the compile. >>> >>> The forceful reload is quite nice, I use it very similarily, but since I >>> dont have springs dependency capabilities I do it differently, but the issue >>> still stays, you will run into a classcast Exception that way. >>> >>> Give it a try do something along the lines of >>> >>> private void doSomething() { >>> .. >>> while(true) { >>> C myVar = appContext.getBean("C"); >>> Thread.sleep(...) >>> } >>> } >>> >>> >>> >>> and then chance C you will get the classcast exception here! Because you >>> cannot terminate the doSomething here but the classloader will push in the C >>> to the old reference! >>> >>> >>> >>> >>>> You cannot really implement it in a different way I suppose as otherwise >>>> you've got to take care with the order how you refresh classes and beans >>>> (i.e. determine the class that no other class depends on and refresh that >>>> at >>>> first, etc.. - doesn't work for cycles though). >>>> >>>> regards, >>>> Bernhard >>>> >>>> Werner Punz wrote on 12/12/2009 03:09 PM (GMT): >>>>> >>>>> Bernhard Huemer schrieb: >>>>>> >>>>>> > Under normal no locking circumstances, the beans get >>>>>> > replaced in the middle of the request because someone >>>>>> > else triggered it for the application singleton, which >>>>>> > is probably fine but somewhat dirty because in some >>>>>> > cases this might end up with a temporary classcast >>>>>> > exception which is resolved then at the following >>>>>> > request cleanly. >>>>>> >>>>>> Well, you're listing more and more issues that are only valid if you >>>>>> refresh beans at the beginning of a request. What you're saying is that >>>>>> the >>>>>> application is in an inconsistent state from the moment you recompile >>>>>> classes until the beginning of the next request that refreshes beans, >>>>>> renderer, etc. for which those recompiled classes are relevant. However, >>>>>> to >>>>>> be more precise you'd have to say that the application is in an >>>>>> inconsistent >>>>>> state from the moment you recompile until all the relevant artifacts are >>>>>> refreshed. As you refresh artifacts only at the beginning of a request, >>>>>> you'll have to somehow synchronize requests, granted, but that doesn't >>>>>> mean >>>>>> that it's necessarily also the case if you'd refresh artifacts in your >>>>>> daemon thread instead. Ensuring that the recompile/refresh operation is >>>>>> an >>>>>> atomic one is just so much easier, if you don't have to wait for the next >>>>>> request for the refresh (as - again - that's where you refresh >>>>>> artifacts). >>>>>> >>>>> The main issue here is to avoid inconsistent states as much as possible, >>>>> if you do the refreshing asynchronously you just push the inconsistencies >>>>> one level up. >>>>> I will give an example. >>>>> The compile and refresh is atomic ok, that is a common point! >>>>> The main issue the application state for the user. >>>>> >>>>> If you compile and refresh asynchronously without having old states of >>>>> the objects not only the classes you basically exchange classes and >>>>> objects in the middle of a request. Ok granted this does not happen to >>>>> often but it can happen! >>>>> So what happens, is that a) the user has to wait in the middle of >>>>> request processing that the atomic compile and refresh is done (or not >>>>> depending what you want to lock there) and then to the worse you suddenly >>>>> in >>>>> the middle of the request you have the beans and classes exchanged. >>>>> Ok this is not too different to what happens if you refresh in request >>>>> level if you dont streamline the requests during the compile and refresh >>>>> cycle. >>>>> So pretty much you end up with one request in an inconsistent state and >>>>> probably errors. >>>>> Anyway, I have given the solutions for the problem and it does not >>>>> matter when you compile, it is either double buffer the classes and >>>>> objects >>>>> or streamline the requests for the time of compile and refresh the >>>>> objects! >>>>> >>>>> >>>>>> > What we are talking about here is a 1% corner case which >>>>>> > imposes 90% extra work in that area, and that is definitely >>>>>> > a post 1.0 thing to solve. >>>>>> >>>>>> Granted, but just don't get me wrong. I've never meant to point out >>>>>> every single tiny, inconvenient and maybe even insignificant issue as you >>>>>> were the one who brought up the Windows file locking issue (which I btw. >>>>>> still doubt that it exists as even Windows provides - if I'm not mistaken >>>>>> and if not specified otherwise - exclusive read, write and delete access >>>>>> to >>>>>> one process at a time only). What I'm saying is, yes, there are certain >>>>>> race >>>>>> conditions, but that's at least partly a result of your "JSP-like" >>>>>> refresh >>>>>> approach. >>>>>> >>>>> I still dont think those issues except for a longer waiting time has >>>>> anything to do with the jsp like approach, granted you have >>>>> to wait for the compiler instead of having it executed parallely (which >>>>> is a fraction of a second, but the rest of the problems with the >>>>> inconsistencies of the application state are the same, and to the third >>>>> you >>>>> give the developer basically in a single developer environment back the >>>>> control when to compile instead of enforcing it. >>>>> >>>>> But as I said that was not even my intention I just had the jsp logic in >>>>> my mind when coding it and did not think about asynchronous compile. >>>>> >>>>> But the rest of the application state problems exist in either approach. >>>>> All you gain is a faster compile for the sake of taking away the deveopers >>>>> control of when to compile exactly in a typical dev environment. >>>>> >>>>> >>>>>> > [...] (the biggest issue simply is the singleton constructs like >>>>>> > application scoped managed beans, that means double buffer the >>>>>> > class files so every compile has to go into a separate dir, [...] >>>>>> >>>>>> Why do you think that you have to use separate directories all the >>>>>> time? Once the class loader has loaded the class, it's in the main memory >>>>>> anyway, just reuse the in-memory definition of the class and then you >>>>>> could >>>>>> basically drop the class file on the file system. What you mean is >>>>>> probably >>>>>> to somehow freeze the reloading process so that it only picks up reloaded >>>>>> classes at a certain time, but that doesn't require you to use separate >>>>>> directories (and again, that's only required if you refresh artifacts >>>>>> JSP-like). >>>>> >>>>> Not really true, you definitely need a full snapshot, you have >>>>> overlooked one corner case: >>>>> >>>>> See it that way, bean a references classes b and c, c on a later stage >>>>> loaded dynamically. >>>>> >>>>> By the time the class of a and b and c gets recompiled c has not been >>>>> loaded, >>>>> a developer/user hits the refresh at a time the compile is in full force >>>>> or has a running request at the time he still has the old reference to a, >>>>> but then because the classes are exchanged exactly at the request b and c >>>>> get refreshed, b and c are referenced, b is still picked up because the >>>>> old >>>>> version is in the ram, but c is loaded dynamically and not yet in ram, and >>>>> you might end up with an error because something does not match (in the >>>>> worst case classcast along the lines of c cannot be cast to c), because >>>>> for >>>>> a and b you are still on the old version while c is loaded from the new >>>>> version. >>>>> >>>>> So it is either, buffer all classes as snapshot in ram for the "compile" >>>>> transaction (which with normal classloader logic is only possible for 95% >>>>> due to the lazy initialisation of classes classloader in fact do) so that >>>>> old requests get a consistent state or buffer the classes on the hd and >>>>> keep >>>>> the logic in the classloader down to the bare minimum, so it is just >>>>> either >>>>> ram or diskspace. The other solution is just compile when no request is >>>>> going on and block all requests until the compile and replace is done. >>>>> >>>>> Normal classloader logic can deal with most cases but not with the fully >>>>> dynamical part which gets loaded somewhere in the code via loadClass! >>>>> >>>>> >>>>> But as I said, this is so much logic overhead to cover a cornercase >>>>> which is not really that important for a development environment. >>>>> The worst case is in this case just a lost request. And if we look at >>>>> pure scripting languages, they do not even remotely try to solve this. >>>>> If the application logic and data structures go haywire then the >>>>> developer has to perform the reboot in those languages! >>>>> >>>>> >>>>>> >>>>>> For example, you could do something like: save the time stamp of the >>>>>> beginning of the request and only reload class definitions if the last >>>>>> modified time stamp of the according class file is less than the >>>>>> previously >>>>>> saved one (i.e. basically if the class file has been recompiled before >>>>>> the >>>>>> beginning of the current request, use it - which also means, you won't >>>>>> care >>>>>> about recompiled classes during the request). However, that's just an >>>>>> idea, >>>>>> I haven't tried it as I don't have to implement something like that in my >>>>>> case. >>>>>> >>>>> I am doing that on bean level to kick through the session and custom >>>>> scoped beans, the timestamp part needs a full snapshot of all classes, but >>>>> yes that is definitely the way to identify when the transactional boundary >>>>> is reached. >>>>> >>>>> >>>>>> > And to go back to the original discussion, the compile trigger >>>>>> > point is mostly a matter of preferrence, I have to admit doing >>>>>> > the compile on request start was just because I had jsps >>>>>> > behavior in mind, when I was coding it, I was not even >>>>>> > thinking of doing it parallely in the watchdog daemon thread. >>>>>> >>>>>> .. which is why I told you about the possibility of doing it that way >>>>>> now. You know, four eyes can see more than two and I really like this >>>>>> module, I think it could be a great advantage of MyFaces. That's why I'm >>>>>> trying to suggest improvements as far as possible. ;-) >>>>>> >>>>> Yes indeed... and no offence taken. >>>>> >>>>> >>>>>> regards, >>>>>> Bernhard >>>>>> >>>>>> Werner Punz wrote on 12/12/2009 10:31 AM (GMT): >>>>>>> >>>>>>> Bernhard Huemer schrieb: >>>>>>>>> >>>>>>>>> I悲 rather have a single pretictable triggering point than having >>>>>>>>> the compiler being triggered continously in unpredictable manner. >>>>>>>>> A standalone developer can code and save and can cause continous >>>>>>>>> errors. But at the time he hits refresh, he can be pretty sure that >>>>>>>>> his code should work (well often it does not but that is a different >>>>>>>>> matter) >>>>>>>> >>>>>>>> Even if you compile continuously the developer can introduce >>>>>>>> mistakes, save them and the application won't pick them up as it simply >>>>>>>> doesn't compile anyway - or do you mean runtime errors? Just thinking >>>>>>>> about >>>>>>>> it - apparently it doesn't really matter at which point you pick up >>>>>>>> the >>>>>>>> changes as long as you pick them up at all (which you do), which >>>>>>>> basically >>>>>>>> means, if the developer introduces runtime errors at runtime it will >>>>>>>> affect >>>>>>>> your application regardless of whether you recompile it JSP-like or not >>>>>>>> (btw. using the term "JSP-like" as a way to express how you manage >>>>>>>> compilation isn't really precise either as e.g. the Jasper 2 engine >>>>>>>> provides >>>>>>>> background compilation as well - but let's stick with the usual >>>>>>>> approach to >>>>>>>> define what "JSP-like" means). >>>>>>>> >>>>>>>> Anyhow if it works JSP-like in your case, then you can't just treat >>>>>>>> users and developers the same. The relationship that any developer who >>>>>>>> uses >>>>>>>> your module is a user of your module doesn't really matter when it >>>>>>>> comes to >>>>>>>> race conditions, so I'd suggest we'll ignore that fact. >>>>>>>> However, what matters is that there are people who issue requests to >>>>>>>> the web server, namely the users, and people who actually modify the >>>>>>>> source >>>>>>>> files of those applications, the developers. The problem with the users >>>>>>>> requests being the "compilation trigger" is apparently that you'll >>>>>>>> have to >>>>>>>> deal with race conditions as there are multiple possible request >>>>>>>> threads. >>>>>>>> If, however, the developer, or more precisely said the daemon thread >>>>>>>> that >>>>>>>> checks for file modifications, triggers compilations you've only got >>>>>>>> one >>>>>>>> thread - the file monitoring thread - that could possibly access the >>>>>>>> compiler, hence no need for synchronization at all in this case! >>>>>>>> >>>>>>>> Well, we've already talked about it a lot anyway, and it's probably >>>>>>>> just a matter of preference, I just wanted to point out some issues and >>>>>>>> compare different approaches. Maybe others want to follow that >>>>>>>> discussion as >>>>>>>> well, which is why I'm still responding to this emails as well >>>>>>> >>>>>>> Actually the trigger point of the compiler is really just a matter of >>>>>>> personal preference, but the concurrency issues go way deeper than that >>>>>>> and >>>>>>> mostly are singleton related. >>>>>>> >>>>>>> We have application scoped, session scoped and request scoped beans. >>>>>>> Well what happens if a compile is done in a middle of a request for >>>>>>> someone who hits the site, this happens in both approaches. >>>>>>> >>>>>>> Under normal no locking circumstances, the beans get replaced in the >>>>>>> middle of the request because someone else triggered it for the >>>>>>> application >>>>>>> singleton, which is probably fine but somewhat dirty because in some >>>>>>> cases >>>>>>> this might end up with a temporary classcast exception which is resolved >>>>>>> then at the following request cleanly. >>>>>>> >>>>>>> If you want to solve it cleanly you have various options. >>>>>>> a) Let the requests run out which already are in progress >>>>>>> Then compile and while compilation put any new request on hold >>>>>>> Then let the requests through again. >>>>>>> >>>>>>> The compile has to be seen as transaction boundary, everything >>>>>>> before the compile has to be a single unit, which is not mutable, >>>>>>> everything >>>>>>> after the compile also. >>>>>>> >>>>>>> The problem here starts with long running requests like comet >>>>>>> frameworks issue them, then suddenly the compiler literally has to wait >>>>>>> for >>>>>>> ages until it can trigger (until the timeout for the comet related long >>>>>>> running xhr request, if you run for instance on Bayeux not on websockets >>>>>>> which are handled differently). >>>>>>> >>>>>>> b) Try to double buffer everything possible so that requests before >>>>>>> and during the compile see a single application state (the biggest issue >>>>>>> simply is the singleton constructs like application scoped managed >>>>>>> beans, >>>>>>> that means double buffer the class files so every compile has to go >>>>>>> into a >>>>>>> separate dir, double buffer the managed beans which means the old beans >>>>>>> have >>>>>>> to be preserved until the last jsf request has terminated which >>>>>>> accesses the >>>>>>> current state, so I even assume we need an unlimited nesting depth of >>>>>>> the >>>>>>> application state here. >>>>>>> >>>>>>> Just in short terms to sum it up, this is way too much to handle for >>>>>>> my 1.0 version, which is mainly aimed at easing the life of the >>>>>>> developers. >>>>>>> I probably will add solution a) but will make it only optionally >>>>>>> turned on sort of as additional safety net for production sites which >>>>>>> do not >>>>>>> run comet over jsf (99% of all sites). I am not aiming for a 100% >>>>>>> perfect >>>>>>> solution in 1.0 but only for a solution which should ease the life of >>>>>>> the >>>>>>> developers by reducing the number of server restarts as much as >>>>>>> possible. >>>>>>> >>>>>>> What we are talking about here is a 1% corner case which imposes 90% >>>>>>> extra work in that area, and that is definitely a post 1.0 thing to >>>>>>> solve. >>>>>>> After all the entire library is not done with 1.0, 1.0 is just a first >>>>>>> version which aims to solve certain things to some extend. >>>>>>> And we are not talking about rendering the application in an unusable >>>>>>> state but that after compile time users in a multiuser environment >>>>>>> might get >>>>>>> an error for exactly one request. A situation which cannot happen in a >>>>>>> single user dev environment entirely. >>>>>>> So hot patching a running server or having multiple developers >>>>>>> programming against a running server might trigger this, but only for >>>>>>> one >>>>>>> request only. It simply is not worth it for 1.0 to solve that, although >>>>>>> I am >>>>>>> sure some users will run into it, hence this needs to be documented! >>>>>>> >>>>>>> >>>>>>> And to go back to the original discussion, the compile trigger point >>>>>>> is mostly a matter of preferrence, I have to admit doing the compile on >>>>>>> request start was just because I had jsps behavior in mind, when I was >>>>>>> coding it, I was not even thinking of doing it parallely in the watchdog >>>>>>> daemon thread. >> >> >
