1 2 Previous Next 24 Replies Latest reply on Sep 16, 2008 3:17 PM by iradix

    Facelets scanning for .taglib.xml is broken in trunk

    pmuir

      This means that e.g. the booking app won't work.

      Not yet tracked down why this has stopped working.

        • 1. Re: Facelets scanning for .taglib.xml is broken in trunk
          ccrouch

          Ok stupid question: How does this problem manifest itself?

          I'm not seeing anything obvious (e.g. web app not displaying, exceptions in the log) yet we're using facelets? I am seeing this though which looks kind of odd (taglibs getting loaded twice):

          14:10:59,828 ERROR [STDERR] Feb 4, 2008 2:10:59 PM com.sun.facelets.compiler.TagLibraryConfig loadImplicit
          INFO: Added Library from: vfsfile:/C:/usr/apps/jboss/jboss-5.0.0.r69477/server/default/deploy/embedded-console.war/WEB-INF/lib/jboss-seam-ui-2.0.1.GA.jar/META-INF/s.taglib.xml
          14:10:59,828 ERROR [STDERR] Feb 4, 2008 2:10:59 PM com.sun.facelets.compiler.TagLibraryConfig loadImplicit
          INFO: Added Library from: jar:file:/C:/usr/apps/jboss/jboss-5.0.0.r69477/server/default/tmp/deploy/embedded-console51602-exp.war/WEB-INF/lib/jboss-seam-ui-2.0.1.GA.jar!/META-INF/s.taglib.xml
          14:11:01,750 ERROR [STDERR] Feb 4, 2008 2:11:01 PM com.sun.facelets.compiler.TagLibraryConfig loadImplicit
          INFO: Added Library from: vfsfile:/C:/usr/apps/jboss/jboss-5.0.0.r69477/server/default/deploy/embedded-console.war/WEB-INF/lib/jsf-facelets-1.1.14.jar/META-INF/jsf-core.taglib.xml
          14:11:01,859 ERROR [STDERR] Feb 4, 2008 2:11:01 PM com.sun.facelets.compiler.TagLibraryConfig loadImplicit
          INFO: Added Library from: jar:file:/C:/usr/apps/jboss/jboss-5.0.0.r69477/server/default/tmp/deploy/embedded-console51602-exp.war/WEB-INF/lib/jsf-facelets-1.1.14.jar!/META-INF/jsf-core.taglib.xml



          Thanks

          • 2. Re: Facelets scanning for .taglib.xml is broken in trunk
            alesj

             

            "charles.crouch@jboss.com" wrote:
            Ok stupid question: How does this problem manifest itself?

            02:22:38,609 ERROR [STDERR] 5.2.2008 2:22:38 com.sun.facelets.compiler.Compiler initialize
            SEVERE: Missing Built-in Tag Libraries! Make sure they are included within the META-INF directory of Facelets' Jar

            I get this when hitting my browser.

            What's your environment?


            • 3. Re: Facelets scanning for .taglib.xml is broken in trunk
              alesj

              Just tested this on r69523 (pre Scott's war CL changes) and it works.

              • 4. Re: Facelets scanning for .taglib.xml is broken in trunk
                ccrouch

                You beat me to it :-) I'm running r69477 and not seeing this.

                • 5. Re: Facelets scanning for .taglib.xml is broken in trunk
                  ccrouch

                  do we have a jira for this yet?

                  • 6. Re: Facelets scanning for .taglib.xml is broken in trunk
                    alesj

                     

                    "charles.crouch@jboss.com" wrote:
                    do we have a jira for this yet?

                    No.
                    Can you create one?
                    Perhaps as a subtask of Scott's war CL change (if it exists).
                    And assign it to Scott, since he's currently the suspect. :-)

                    • 7. Re: Facelets scanning for .taglib.xml is broken in trunk
                      ccrouch

                      I have no idea which jira the war CL changes went into, so I created a new one

                      http://jira.jboss.com/jira/browse/JBAS-5211

                      • 8. Re: Facelets scanning for .taglib.xml is broken in trunk
                        alesj

                        The current version of Facelets used in our Seam Booking example is 1.1.14:
                        - https://facelets.dev.java.net/servlets/ProjectDocumentList?folderID=3635&expandFolder=3635&folderID=0

                        I think it all starts from FaceletViewHandler.buildView().
                        Calling DefaultFaceletFactory.getFacelet.
                        This call another getFacelet method, which calls createFacelet.
                        Which invokes compiler.compile(url, alias), that does initialize().
                        Compiler.initialize invokes TagLibraryConfig.loadImplicit, which does the actual search Classpath.search(cl, "META-INF/", ".taglib.xml").
                        The cl variable is context classloader.

                        ClassPath class:

                        public final class Classpath {
                        
                         /**
                         *
                         */
                         public Classpath() {
                         super();
                         }
                        
                         public static URL[] search(String prefix, String suffix) throws IOException {
                         return search(Thread.currentThread().getContextClassLoader(), prefix,
                         suffix);
                         }
                        
                         public static URL[] search(ClassLoader cl, String prefix, String suffix) throws IOException {
                         Enumeration[] e = new Enumeration[] {
                         cl.getResources(prefix),
                         cl.getResources(prefix + "MANIFEST.MF")
                         };
                         Set all = new LinkedHashSet();
                         URL url;
                         URLConnection conn;
                         JarFile jarFile;
                         for (int i = 0, s = e.length; i < s; ++i) {
                         while (e.hasMoreElements()) {
                         url = (URL) e.nextElement();
                         conn = url.openConnection();
                         conn.setUseCaches(false);
                         conn.setDefaultUseCaches(false);
                         if (conn instanceof JarURLConnection) {
                         jarFile = ((JarURLConnection) conn).getJarFile();
                         } else {
                         jarFile = getAlternativeJarFile(url);
                         }
                         if (jarFile != null) {
                         searchJar(cl, all, jarFile, prefix, suffix);
                         } else {
                         searchDir(all,
                         new File(URLDecoder.decode(url.getFile(),
                         "UTF-8")),
                         suffix);
                         }
                         }
                         }
                         URL[] urlArray = (URL[]) all.toArray(new URL[all.size()]);
                         return urlArray;
                         }
                        
                         private static void searchDir(Set result, File file, String suffix)
                         throws IOException {
                         if (file.exists() && file.isDirectory()) {
                         File[] fc = file.listFiles();
                         String path;
                         URL src;
                         for (int i = 0; i < fc.length; i++) {
                         path = fc.getAbsolutePath();
                         if (fc.isDirectory()) {
                         searchDir(result, fc, suffix);
                         } else if (path.endsWith(suffix)) {
                         // result.add(new URL("file:/" + path));
                         result.add(fc.toURL());
                         }
                         }
                         }
                         }
                        
                         /** For URLs to JARs that do not use JarURLConnection - allowed by
                         * the servlet spec - attempt to produce a JarFile object all the same.
                         * Known servlet engines that function like this include Weblogic
                         * and OC4J.
                         * This is not a full solution, since an unpacked WAR or EAR will not
                         * have JAR "files" as such.
                         */
                         private static JarFile getAlternativeJarFile(URL url) throws IOException {
                         String urlFile = url.getFile();
                         // Trim off any suffix - which is prefixed by "!/" on Weblogic
                         int separatorIndex = urlFile.indexOf("!/");
                        
                         // OK, didn't find that. Try the less safe "!", used on OC4J
                         if (separatorIndex == -1) {
                         separatorIndex = urlFile.indexOf('!');
                         }
                        
                         if (separatorIndex != -1) {
                         String jarFileUrl = urlFile.substring(0, separatorIndex);
                         // And trim off any "file:" prefix.
                         if (jarFileUrl.startsWith("file:")) {
                         jarFileUrl = jarFileUrl.substring("file:".length());
                         }
                         return new JarFile(jarFileUrl);
                         }
                         return null;
                         }
                        
                         private static void searchJar(ClassLoader cl, Set result, JarFile file,
                         String prefix, String suffix) throws IOException {
                         Enumeration e = file.entries();
                         JarEntry entry;
                         String name;
                         while (e.hasMoreElements()) {
                         try {
                         entry = (JarEntry) e.nextElement();
                         } catch (Throwable t) {
                         continue;
                         }
                         name = entry.getName();
                         if (name.startsWith(prefix) && name.endsWith(suffix)) {
                         Enumeration e2 = cl.getResources(name);
                         while (e2.hasMoreElements()) {
                         result.add(e2.nextElement());
                         }
                         }
                         }
                         }
                        
                        }
                        




                        • 9. Re: Facelets scanning for .taglib.xml is broken in trunk
                          starksm64

                          getAlternativeJarFile is broken for vfs urls. It all comes down to no ability to navigate a URL and no ClassLoader.getResources with a regex pattern, so they have to try to guess what type of URL it is. There needs to be a better servlet api to access resources inside of a war for code like this to work in general.

                          Is there any point that the tag lib urls can be overriden?

                          • 10. Re: Facelets scanning for .taglib.xml is broken in trunk
                            alesj

                             

                            "scott.stark@jboss.org" wrote:
                            getAlternativeJarFile is broken for vfs urls. It all comes down to no ability to navigate a URL and no ClassLoader.getResources with a regex pattern, so they have to try to guess what type of URL it is.

                            But why this worked before, with VFS and the new CL both already being used.
                            Why it stopped with your war CL changes?

                            "scott.stark@jboss.org" wrote:

                            There needs to be a better servlet api to access resources inside of a war for code like this to work in general.

                            Couldn't agree more.
                            But we are constantly seeing this problem, so it won't go away soon. :-(

                            "scott.stark@jboss.org" wrote:

                            Is there any point that the tag lib urls can be overriden?

                            Pete or. any other Seam/Facelet guru?

                            • 11. Re: Facelets scanning for .taglib.xml is broken in trunk
                              starksm64

                               

                              "alesj" wrote:

                              But why this worked before, with VFS and the new CL both already being used.
                              Why it stopped with your war CL changes?

                              I would guess because tomcat was rebuilding the URLClassLoader classpath, perhaps using the extracted jar so that they were simple file urls to the jars.

                              This code should be using JarInputStream(InputStream in) rather than a JarFile so that the InputStream can be obtained from an arbitrary URL. JarFile is the least flexible api to be using.


                              • 12. Re: Facelets scanning for .taglib.xml is broken in trunk
                                alesj

                                 

                                "scott.stark@jboss.org" wrote:

                                This code should be using JarInputStream(InputStream in) rather than a JarFile so that the InputStream can be obtained from an arbitrary URL. JarFile is the least flexible api to be using.

                                What's to do here?
                                Have home brew of this on top of VFS?
                                And push for change of making this search either pluggable or using JIS?

                                • 13. Re: Facelets scanning for .taglib.xml is broken in trunk
                                  starksm64

                                  If JarFile supported a JarInputStream I would look at support a JarURLConnection from the handler, but you have to have a path to a file as far as I can see.

                                  I would say hacking the facelets code to create patch Classpath to try to use a JarInputStream to find the taglib descriptiors is the best approach. There will be a patched facelets jars required, and we give back the patch.

                                  • 14. Re: Facelets scanning for .taglib.xml is broken in trunk
                                    alesj

                                    Yeah!
                                    Got it working. :-)
                                    Hacked the Facelets.

                                    I didn't go into even bigger torture, and I simply implemented search on top of VFS.

                                    1 2 Previous Next