Facelets Tag Completion in Eclipse

December 09, 2006

For those of you who use the Eclipse Web Tools Project (WTP) to develop JSF applications with Facelets, you are likely familiar with the lack of tag library support when editing Facelets compositions. By default, Facelets expects pages to use the *.xhtml file extension, which is the XML variant of HTML. There are two discernible problems with this configuration. For one, Eclipse does not recognize files of this type as pertaining to JSF. As a result, Eclipse does not offer tag completion or validation for the libraries registered in the XML namespaces. The second issue is that these pages contain more than just XHTML content. While it may be possible to get away with masking the signature of most tags using the "jsfc" attribute, it turns out to be more trouble than it is worth.

The solution that I came up with, and one that Rick Hightower recommends in his latest round of JSF tutorials, is to use the XML variant of JSP in your Facelets pages. Since the tag completion in Eclipse WTP is built to support JSPX, and all that Facelets requires is a valid XML page, it is a match made in heaven!

<?xml version="1.0" encoding="ISO-8859-1" ?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:f="http://java.sun.com/jsf/core"
  version="2.0">
  <ui:composition>
    <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
        <title>Page Title</title>
      </head>
      <body>
        <h:outputText value="#{backingBean.property}"/>
      </body>
    </html>
  </ui:composition>
</jsp:root>

Facelets is none the wiser that the XML being used is rooted as JSP. The declarations appearing in the XML namespaces now provide Eclipse with what it needs to offer tag library support while dually informing Facelets which components to load. The only requirement is to ensure that the corresponding TLD file for each tag library is located on the classpath. Even though Facelets does not require TLDs, Eclipse needs them to load the tag libraries definitions, as it does not understand the tag configurations used by Facelets.

If you are going to use this trick, be sure to override the default suffix used by Facelets in the web.xml file.

<context-param>
  <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
  <param-value>.jspx</param-value>
</context-param>

UPDATE: In order to get tag completion, you need to include the Facelets TLD in your WEB-INF/tlds folder. The Facelets TLD is not bundled in the Facelets JAR.

Posted at 11:03 PM in Java | Permalink Icon Permalink

15 Comments from the Peanut Gallery

1 | Posted by Maarten on January 28, 2007 at 11:54 PM EST

This is a great trick, but how do I get the page to produce a DOCTYPE?

2 | Posted by Maarten on January 29, 2007 at 01:13 PM EST

Ok, I think I got it: You have to define another "old school" (ie not with jsp:root) template with the doctype and in it, and put an include in there. Then the rest of your templates can use and simply extend the first one, which will give you a proper doctype. Seems like there should be an easier way though...

3 | Posted by Dan Allen on February 01, 2007 at 11:12 AM EST

Oh, right. I forgot to include how I handle the doctype definition! I agree it is a bit tricky. I would love to see this feature as part of tomahawk.

Create a Facelets tag called t:doctype, with the following content.

<?xml version="1.0" encoding="UTF-8"?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:f="http://java.sun.com/jsf/core"
  version="2.0">
  <ui:composition>
<h:outputText value='&lt;?xml version="1.0" encoding="UTF-8"?&gt;' escape="false"/>
<h:outputText value='&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;' escape="false"/>
  </ui:composition>
</jsp:root>

Next, register this tag in a Facelets taglib definition file.

<tag>
  <tag-name>doctype</tag-name>
  <source>tags/doctype.jspx</source>
</tag>

Now you are ready to include it just inside of the ui:composition tag in the template.

You can, of course, make this tag more flexible by adding option parameters that indicate which doctype and encoding to use. As shown, this tag assumes you want to use xhtml-strict.

4 | Posted by Torsten Liermann on August 20, 2007 at 03:15 PM EST

Hi,

what is facelet doing with the jsp:root-Tag? What is the directive for facelet to do nothing?

Thanks for a tip Torsten

5 | Posted by CuongPC on August 31, 2007 at 01:42 AM EST

Oh ! I got this error, and I really don't know how to solve. Thanks for your post. Alternative, Can I use replace to Is is still done? Thanks agian CuongPC

6 | Posted by Red3 on December 03, 2007 at 03:29 PM EST

Using the JSPX trick doesn't do tag completion for me. I get completion with ICEFaces and JSF tags, but not Facelets. The trick for me was to include the TLD file for Facelets in WEB-INF/tld in my project. Available here: https://facelets.dev.java.net/servlets/ProjectDocumentList?expandFolder=3986&folderID=4190

7 | Posted by Dan Allen on December 07, 2007 at 01:43 AM EST

Oh wow! I completely forgot to mention that you need to put the TLD file in your WEB-INF directory. I feel like a guy giving directions in his home town. I left out one of the steps that I know all too well. Thanks for the tip!

8 | Posted by Luiz Taborda on January 24, 2008 at 02:27 PM EST

Hi, i don't speak english, but, muito bom!!!! valew!!!

9 | Posted by Sara on April 07, 2008 at 03:58 AM EST

Hi! I don't get the ui completion. I've h, f and jsp comletion but doesn't the ui. I've put the TLD file in my WEB-LIB/tld folder but doesn't work. Have I to specify something else in web.xml or in other file?

Thanks

10 | Posted by axel on June 20, 2008 at 06:50 AM EST

Thanks or this trick. I have try it and it runs. But if i call my page an look at the source there is a jsp-root tag instead of a html-tag Is it ok?

11 | Posted by Andrew Lovell on June 29, 2008 at 02:08 PM EST

In Europa (3.3) you are not forced to use .jspx as a file extension... In window->preferences you do 2 things...

1. In General->Content Types you choose text/jsp in the content types and add *.xhtml as a file association

2. In General->Editors->File Associations select the *.xhtml file type and add th JSP Editor as the Default

now just add the TLD to WEB-INF dir of your project and hey presto tag:completion now works for xhtml files.

I picked this up from someone's page somewhere but have lost the link otherwise credit would be given!

12 | Posted by gaurav on August 02, 2008 at 12:57 AM EST

Thanks Andrew,

Thats a cool trick to get facelets working with *.xhtml in eclipse.

13 | Posted by Alex on August 05, 2008 at 02:39 AM EST

For tag completion in xhtml files use jsp:root with xmlns attributes instead html as root tag

14 | Posted by MoNolab on March 10, 2010 at 05:52 AM EST

Thanks Andrew, this is the best solution!

15 | Posted by Fred on April 28, 2011 at 03:50 AM EST

This does not work in Eclipse 3.6. To get it fixed, please vote for this Bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=315892