2 Replies Latest reply: Dec 12, 2012 10:45 PM by jmsjr RSS

    Using a composite component from an xhtml that is included in another xhtml

    jmsjr
      JBoss 7.1.1
      JSF 2.1

      I have the following composite component:
      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      <ui:component xmlns="http://www.w3.org/1999/xhtml"
              xmlns:h="http://java.sun.com/jsf/html"
              xmlns:composite="http://java.sun.com/jsf/composite"
              xmlns:f="http://java.sun.com/jsf/core"
              xmlns:ui="http://java.sun.com/jsf/facelets"
              xmlns:rich="http://richfaces.org/rich">
              <composite:interface>
                  <composite:attribute name="for" required="true" />
              </composite:interface>
              <composite:implementation>
                  <rich:panel styleClass="aas-msg-tt-p">
                      <rich:message id="#{cc.attrs.for}-msg"
                          for="#{cc.attrs.for}" />
                      <rich:tooltip id="#{cc.attrs.for}-msg-tt">
                          <rich:message for="#{cc.attrs.for}"
                              styleClass="aas-rf-det-tooltip" />
                      </rich:tooltip>
                  </rich:panel>
              </composite:implementation>
      </ui:component>
      It is in WebContent/resources/aas-composite/messagetooltip.xhtml ( where WebContent is the root directory or root context directory of the deployed WAR )

      h3. *1. Using the composite component and working as expected*

      If I use the composite component directly as follows, it all works:

      1) Create test.xhtml in WebContent
      2) Content of test.xhtml as follows:
      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      <html xmlns="http://www.w3.org/1999/xhtml"
            xmlns:h="http://java.sun.com/jsf/html"
            xmlns:f="http://java.sun.com/jsf/core"
            xmlns:ui="http://java.sun.com/jsf/facelets"
            xmlns:a4j="http://richfaces.org/a4j"
            xmlns:rich="http://richfaces.org/rich"
            xmlns:aas="http://java.sun.com/jsf/composite/aas-composite"> 
      <h:head>
          <meta http-equiv="X-UA-Compatible" content="IE=8" />
      </h:head>
      <h:body>
          <h:outputStylesheet library="css" name="richfacesoverrides.css"/> 
          <h:form id="testform">
             <table>
                  <tr>
                      <td><aas:messagetooltip for="id2"/></td>
                      <td><h:outputLabel>Input 2: </h:outputLabel></td>
                      <td><h:selectOneMenu id="id2"
                              required="true"
                              requiredMessage="Cause of Death is required" 
                              value="${death.causeOfDeath}">
                             <f:selectItem itemValue="" itemLabel="-- Select One --" /> 
                             <f:selectItem itemValue="COD01" itemLabel="Cancer" />
                             <f:selectItem itemValue="COD02" itemLabel="Diabetes" />
                             <f:selectItem itemValue="COD11" itemLabel="Other" />
                          </h:selectOneMenu>
                      </td>
                  </tr>
             </table>
             <h:commandButton id="submit" value="Submit"/><br/>
      </h:form> 
       
      </h:body> 
      </html>
      3) Deploy and test, all good


      h3. *2. Using the composite component but NOT working as expected*

      Now if I use the composite component as follows:

      4) Create XHTML file called includeThisFromRoot.xhtml under WebContent directory

      5) with content as follows:
      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      <html xmlns="http://www.w3.org/1999/xhtml"
            xmlns:h="http://java.sun.com/jsf/html"
            xmlns:f="http://java.sun.com/jsf/core"
            xmlns:ui="http://java.sun.com/jsf/facelets"
            xmlns:a4j="http://richfaces.org/a4j"
            xmlns:rich="http://richfaces.org/rich"
            xmlns:aas="http://java.sun.com/jsf/composite/aas-composite">
      
          <ui:composition>
             <table>
                  <tr>
                      <td><aas:messagetooltip for="id2"/></td>
                      <td><h:outputLabel>Input 2: </h:outputLabel></td>
                      <td><h:selectOneMenu id="id2"
                              required="true"
                              requiredMessage="Cause of Death is required" 
                              value="${death.causeOfDeath}">
                             <f:selectItem itemValue="" itemLabel="-- Select One --" /> 
                             <f:selectItem itemValue="COD01" itemLabel="Cancer" />
                             <f:selectItem itemValue="COD02" itemLabel="Diabetes" />
                             <f:selectItem itemValue="COD11" itemLabel="Other" />
                          </h:selectOneMenu>
                      </td>
                  </tr>
             </table>
             <h:commandButton id="submit" value="Submit"/><br/>
          </ui:composition>
      </html>
      6) Make a copy test.xhtml, but call the new one testWithInclude.xhtml, with content as follows:
      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      <html xmlns="http://www.w3.org/1999/xhtml"
            xmlns:h="http://java.sun.com/jsf/html"
            xmlns:f="http://java.sun.com/jsf/core"
            xmlns:ui="http://java.sun.com/jsf/facelets"
            xmlns:a4j="http://richfaces.org/a4j"
            xmlns:rich="http://richfaces.org/rich"
            xmlns:aas="http://java.sun.com/jsf/composite/aas-composite"> 
      <h:head>
          <meta http-equiv="X-UA-Compatible" content="IE=8" />
      </h:head>
      <h:body>
          <h:outputStylesheet library="css" name="richfacesoverrides.css"/> 
          <h:form id="testform">
              <ui:include src="includeThisFromRoot.xhtml" />
          </h:form> 
       
      </h:body> 
      </html>
      h3. Summary of change

      You can see here that I simply moved all of the content between the form tags from the original XHTML to a separate XHTML, and included that separate XHTML using <ui:include>.

      h3. Result

      7) Deploy and access testWithInclude.jsf from browser, and I get:
      15:17:55,310 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/richfacestest].[Faces Servlet]] (http--0.0.0.0-8081-5) Servlet.service() for servlet Faces Servlet threw exception: javax.faces.view.facelets.TagException: /includeThisFromRoot.xhtml @13,52 <aas:messagetooltip> Tag Library supports namespace: http://java.sun.com/jsf/composite/aas-composite, but no tag was defined for name: messagetooltip
              at com.sun.faces.facelets.compiler.CompilationManager.pushTag(CompilationManager.java:304) [jsf-impl-2.1.7-jbossorg-2.jar:]
              at com.sun.faces.facelets.compiler.SAXCompiler$CompilationHandler.startElement(SAXCompiler.java:266) [jsf-impl-2.1.7-jbossorg-2.jar:]
              at org.apache.xerces.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:496)
              at org.apache.xerces.parsers.AbstractXMLDocumentParser.emptyElement(AbstractXMLDocumentParser.java:180)
              at org.apache.xerces.impl.dtd.XMLDTDValidator.emptyElement(XMLDTDValidator.java:810)
              at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:275)
              at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(XMLDocumentFragmentScannerImpl.java:1653)
              at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:324)
              at org.apache.xerces.parsers.XML11Configuration.parse(XML11Configuration.java:845)
              at org.apache.xerces.parsers.XML11Configuration.parse(XML11Configuration.java:768)
              at org.apache.xerces.parsers.XMLParser.parse(XMLParser.java:108)
              at org.apache.xerces.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1196)
              at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:555)
              at org.apache.xerces.jaxp.SAXParserImpl.parse(SAXParserImpl.java:289)
              at javax.xml.parsers.SAXParser.parse(SAXParser.java:195) [rt.jar:1.7.0_09]
              at com.sun.faces.facelets.compiler.SAXCompiler.doCompile(SAXCompiler.java:434) [jsf-impl-2.1.7-jbossorg-2.jar:]
              at com.sun.faces.facelets.compiler.SAXCompiler.doCompile(SAXCompiler.java:410) [jsf-impl-2.1.7-jbossorg-2.jar:]
              at com.sun.faces.facelets.compiler.Compiler.compile(Compiler.java:124) [jsf-impl-2.1.7-jbossorg-2.jar:]
              at com.sun.faces.facelets.impl.DefaultFaceletFactory.createFacelet(DefaultFaceletFactory.java:305) [jsf-impl-2.1.7-jbossorg-2.jar:]
              at com.sun.faces.facelets.impl.DefaultFaceletFactory.access$100(DefaultFaceletFactory.java:93) [jsf-impl-2.1.7-jbossorg-2.jar:]
              at com.sun.faces.facelets.impl.DefaultFaceletFactory$1.newInstance(DefaultFaceletFactory.java:160) [jsf-impl-2.1.7-jbossorg-2.jar:]
      What gives ? Am I missing something simple ?
        • 1. Re: Using a composite component from an xhtml that is included in another xhtml
          jmsjr
          I think I may have found a workaround.
          In the XHTML file that is included and using the composite component, add the namespace as part of the custom component, like so:
          <aas:messagetooltip xmlns:aas="http://java.sun.com/jsf/composite/aas-composite" for="id2"/>
          So that it now becomes:
          <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
          <html xmlns="http://www.w3.org/1999/xhtml"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns:ui="http://java.sun.com/jsf/facelets"
                xmlns:a4j="http://richfaces.org/a4j"
                xmlns:rich="http://richfaces.org/rich"
                xmlns:aas="http://java.sun.com/jsf/composite/aas-composite">
          
              <ui:composition>
                 <table>
                      <tr>
                          <td><aas:messagetooltip xmlns:aas="http://java.sun.com/jsf/composite/aas-composite" for="id2"/></td>
                          <td><h:outputLabel>Input 2: </h:outputLabel></td>
                          <td><h:selectOneMenu id="id2"
                                  required="true"
                                  requiredMessage="Cause of Death is required" 
                                  value="${death.causeOfDeath}">
                                 <f:selectItem itemValue="" itemLabel="-- Select One --" /> 
                                 <f:selectItem itemValue="COD01" itemLabel="Cancer" />
                                 <f:selectItem itemValue="COD02" itemLabel="Diabetes" />
                                 <f:selectItem itemValue="COD11" itemLabel="Other" />
                              </h:selectOneMenu>
                          </td>
                      </tr>
                 </table>
                 <h:commandButton id="submit" value="Submit"/><br/>
              </ui:composition>
          </html>
          I tried this after finding a similar bug about nested composite components, which I do not use, but thought I would give it a try:

          http://stackoverflow.com/questions/10898906/myfoo-tag-library-supports-namespace-http-java-sun-com-jsf-composite-mycom
          http://stackoverflow.com/questions/9735593/nested-composite-component-broken-in-jboss-7-1-1

          Have to keep track of all these workarounds that I am doing.
          • 2. Re: Using a composite component from an xhtml that is included in another xhtml
            jmsjr
            Marking as answered as per workaround.