Red Hat

In Relation To JSF

In Relation To JSF

Draggable RichFaces panel or non-Modal Panel

Posted by    |       |    Tagged as JSF Rich Faces Seam

Today I'd like to post a really simple solution which is frequently asked at RichFaces Users forum threads. Two questions which can be solved by using this solution:

  • Can the RichFaces popup component be non-modal?
  • Can the rich:panel component be draggable/resizable?

As you can guess I'll use the rich:modalPanel component in order to answer both questions, and the solution is really simple and relies on RichFaces special rich css classes.

Standard Modal Panel look and feel

At first we should open RichFaces developer guide and look to the modal panel skinability section. There we could find the rich-mpnl-mask-div style class which is applied to the page blocking div element for all the modal panels.

Now we can just to add

styleClass="noMaskClass"
to the rich:modalPanel component that we want to be non-modal. And then add the next simple css selector to the stylesheet used by the page:
.noMaskClass .rich-mpnl-mask-div{
    display:none;
}
So the richfaces-demo Modal Panel sample (second one) code changed to:
<style>
    .noMaskClass .rich-mpnl-mask-div{
        display:none;
    }
</style>
<rich:modalPanel  id="mp" minHeight="200" minWidth="450" styleClass="noMaskClass"
    height="200" width="500">
        //Panel Content
</rich:modalPanel>
Modal Panel with removed page blocking div

And if as a result panel in first sample opens as modal, and panel in second sample opens as non modal. So we have the panel with the resizability, autosize, moving, show/hide API and so on features..

So far so good.. But after simple tests we could see that this code works fine in all browsers in Windows environment except IE (Js error appears) and typing restricted in the parent page inputs in FF at linux environment.

After short investigation I found that that forgot about the modal panel client side methods which gets invoked in order to control the focus and tabbing. (accessing the parent page controls using tab control gets restricted using the methods.) But we not need these methods to be invoked at all if our panel is non-modal. So we should just override the methods with empty ones in order to get it working fine.

This is code of the function which will get the modal panel JS object and override needed methods:

function removeTabHandlingFromPanel(modalPanelComponent){
     modalPanelComponent.lastOnfocus = function(event){};
     modalPanelComponent.firstOnfocus = function(event){};
     modalPanelComponent.processAllFocusElements = function(event){};
     modalPanelComponent.processTabindexes = function(event){};
     modalPanelComponent.restoreTabindexes = function(event){};
     modalPanelComponent.preventFocus = function(event){};
     modalPanelComponent.restoreFocus = function(event){};
}
And now we will call this function for the panel which marked as non modal with noMask styleClass
removeTabHandlingFromPanel(#{rich:component('mp')});
So, finally solution is done and works fine within all the browsers supported with RichFaces.

On Thursday, April 9th I will be presenting an introduction and preview of Java Server Faces 2.0 at the New England Java Users Group (NEJUG). The talk will be given at Sun's Burlington Massachusetts campus.

I will be covering many the major features in JSF 2.0 including:

  • New annotation paradigms
  • Integrated Ajax support
  • Facelets integration
  • Page Parameters
  • Resource Handling
  • and more...

We will wrap up the discussion with some thought on the future of JSF, JSR 299, and RichFaces. Plus I'll have some goodies for the raffle.

Registration is required, and more information can be found at the NEJUG website.

Hope to see you there!!

RichFaces 3.3.1 BETA1 Available

Posted by    |       |    Tagged as JSF Rich Faces

RichFaces 3.3.1.BETA1 has been deployed to: jboss repository and ready for community preview.

New components:

There are several new components in 3.3.1, There are the much anticipated set of layout components and a color picker component that are new for this release.

<rich:page/>

Provides a an easy way to format and break up you page structure. You can set facets for header, footer, and even sidebar. We're also introducing a Theme mechanism that can help to setup and precofigure page layouts and skinning interactions.

<rich:layout/> and <rich:layoutPanel/>

Allows nestable page layouts using Yahoo's UI CSS Grid under the hood to providing lots of flexibility.

For more information see Layouts design wiki page.

<rich:colorPicker/>

Often requested Color picker component,

New features

Here are some new features too.

Stability Improvements

Out selenium based automation suite keeps growing, and numerous issues fixed.

Please let know if you find any issues, or have any comments.

[JIRA] [User Forums] [Design Forums]

It's time for Facelets to start using XSD

Posted by    |       |    Tagged as Discussions JSF

I've had this idea for a while now about using XSDs in Facelets templates. I believe we should stop pretending that Facelets templates are XHTML documents and start treating them as unrestricted XML. This would give us the freedom to extend the XML dialect with XML Schema and take full advantage of the type enforcement, syntax recognition, and tooling support that XML Schema provides.

I tried to communicate this idea to the JSF EG at JSFOne, but I fear that I did not articulate it well enough as it never took hold. I want to explain the approach here in detail to see if others agree it has merit. In this entry, I outline a way to take better advantage of Facelets' strengths today and propose a change in JSF 2.1 to support this usage. Right now, all I'm doing is putting the idea out there in the open.

A brief intro to Facelets

Anyone familiar with JSF must have heard about Facelets by now. Facelets is the alternative view handler and view definition language to JSP for JSF, and a far superior one at that. But Facelets is more than just an alternative. I truly believe that Facelets saved JSF, for if it weren't for something elegant like Facelets to come along and give developers a reason to give JSF a chance, they would have abandoned the framework long ago. Facelets really is that significant. As a recognition of its influence, Facelets is set to become the standard page declaration language in JSF 2.0--so if you have been living under a rock, you'll have to come out of hiding soon enough.

What makes Facelets successful

There are two features of Facelets that make it a more palatable choice than JSP for UI development:

  1. The XML markup gets translated directly into JSF UI components
  2. The XML markup must be well-formed

The first point is important because it means that the middleman in the view template to component tree build process has been ousted. JSF was originally designed so that it could leverage JSP pages and in turn JSP tag handlers. Each JSF component was mapped one-to-one with a JSP tag handler. That meant JSF didn't have to be in the business of consuming and parsing XML (or pseudo-XML in the case of classic JSP syntax). Instead, JSP would feed UI components to the JSF component tree build process.

While this sounded good from a reuse perspective, it turned out to be a terrible nightmare for developers. The JSP tag handlers duplicated the properties of the combined UIComponent and component renderer classes for each component. This meant one more class for the developer to write and one more class to maintain. Not to mention the burden of having to keep the tag library descriptor (TLD) metadata in sync with the class to make the JSP parser happy. To minimize the effort, many developers turned towards code generation, in this case an indication of a badly broken design.

Enter Facelets. Facelets offers its own XML compiler and tag handlers. Only in this case, the tag handlers are generic and require minimal configuration. Facelets can introspect the UIComponent and component renderer classes to determine how to map the information from the XML document into objects in the JSF component tree, both of which the Facelets builder creates. Facelets effectively cuts out the middleman. What's more, by having control over the compile process, Facelets was able to introduce its own advanced templating mechanism (called compositions) that allow one Facelets template to become the template of another, almost resembling a LISP dialect.

While building direct is an important reason for Facelets' success, the second point listed above is the one most relevant to this entry. Facelets put its foot down by enforcing valid XML syntax, finally doing away with that ridiculous pseudo-XML syntax that classic JSP supported. Even the JSP taglib directives were removed in favor of using XML namespace declarations to import a component set.

Facelets == XML

If you have so much as an undeclared entity in your template, Facelets will abort processing and throw up a pretty (no, really!) error page. And when Facelets reports the error, it can do so with precision (e.g., line number and column) since it uses a SAX compiler to parse the template prior to building the component tree.

Now I'll convince you why using valid XML is a good thing.

Leveraging the XML ecosystem

XML is ubiquitous. As a result, there are probably as many XML editors available as there are e-mail clients. By Facelets enforcing valid XML syntax, it means I don't have to wait around for a vendor to create me an editor to support a proprietary syntax, as was the case with JSP. Instead, Facelets opens the door to using any one of the available XML tools to create/modify/translate a Facelets view template. That's a very important benefit.

But there's a catch...well, really just a snag. In an attempt to support an experimental design-time technique, Facelets veered off course and did not take full advantage of the tooling benefit that XML has to offer. Let me explain what Facelets' creator was going for and then show you how to take advantage of what he missed.

By parsing the template directly, Facelets is able to work around one of the most horrible monstrosities of the early JSF-JSP integration, the <f:verbatim> tag. You see, every character in a JSF response must be yielded by a JSF component. That means that all static HTML markup must somehow get attached to a component. The only way to accomplish this in JSP was to introduce a wrapper tag, <f:verbatim>. However, this tag not only makes the template look ugly and verbose, it also makes creating valid XML nearly impossible because it ignores the HTML structure.

Once again, Facelets saved the day. Any time Facelets comes across static markup, it automatically creates a UIComponent to wrap the markup and output it during encoding. This also means that Facelets templates can match the recipe of JSP pages: static HTML markup with dynamic parts intermixed.

But Facelets goes a little too far by assuming (in the general case) that the document itself is an HTML template interspersed with JSF components. It became conventional to include an XHTML DOCTYPE at the top of the page (at least the top-level template), which Facelets then passes on to the response when the component tree is encoded. Facelets even takes measure to hide the JSF components by allowing them to be defined on a standard XHTML tag using the proprietary jsfc attribute (the name of the JSF component tag is defined as the value of the attribute). The theory here is that when the template is opened in an HTML viewer, it renders just like any other static HTML document, thus allowing the designer to preview the page. In theory.

<ul jsfc="ui:repeat" var="_name" value="#{bean.names}">
    <li>#{_name}</li>
</ul>

In reality, this theory simply doesn't scale. Unless all you are doing is developing a mostly static website with a handful of dynamic parts scattered across a subset of pages, you eventually get to the point where the pretend HTML documents become a handicap for both the page designer and the developer. It especially hurts the developer because it limits his/her ability to reuse template logic or roll it up into a custom component. I have done a lot of web development and the only way that this relationship works is if you are using a tool, such as the JBoss Tools visual designer, which can provide a runtime view of the page at design time. Otherwise, the designer should simply work on his/her own mockups and deliver them to the developer when they are ready to be integrated into the application.

Cutting the XHTML shackles

While Facelets templates are valid XML, most developers treat them as XHTML documents. The problem is, the XHTML vocabulary is not extensible, particularly when the document is tied to a DOCTYPE. That means all those JSF component tags in the document are seen as foreign bodies and cause the XHTML parser to complain loudly. Once again, you have to wait on that vendor to create an editor which supports this proprietary syntax. And what does that support look like? Well, likely the editor is going to have to parse the TLD files and provide some sort of code assistance (i.e., tag auto-completion) based on that metadata. Proprietary, proprietary, proprietary. Yuck.

But wait, didn't we just finish emphasizing that a Facelets template is valid XML? Of course! Well, there's a perfectly good vocabulary extension system for XML called XML Schema. XML Schema associates an XML dialect with an XML namespace. Unlike DTD, this contract permits multiple vocabularies to be imported into a single document, thus allowing it to be extended infinitely. In addition, the specificity of XML Schema goes way beyond what DTD allows. In fact, XML Schema is so detailed that with its support, you could call XML a type-safe language. This type system translates into code assistance and validation, drastically reducing the pain involved with using XML.

And guess what? Many of the configuration files for the Java frameworks you use today rely on XML Schema Documents (XSDs) to describe, extend, modularize, and document the permissible elements and attributes. Here are a couple of examples:

  • Seam's component descriptor (components.xml, .component.xml)
  • Seam's page descriptor (pages.xml, .page.xml)
  • Faces configuration resources (faces-config.xml)
  • Web application descriptor (web.xml)
  • Spring configuration file

So why not add Facelets to this list? Nothing is stopping us! All we have to do is author an XSD for each JSF component library we use (e.g., Facelets UI, JSF core, HTML basic, etc) and import the types defined in the XSD by associating it with the component library's XML namespace.

Creating XSDs for each component library sure would be a tedious task. You'd have to define an element for each component tag and then list all of the component-specific and renderer-specific attributes. We'll, don't throw away those TLD files just yet! As Mark Ziesemer points out, a TLD file is XML too. So you can work smarter, not harder, by writing an XSLT document to transpose the TLD into an XSD. And fortunately for us, Mark did that for us already! I used his XSLT script to create XSDs for the standard JSF component sets. Once created, I match them up with namespaces in the xsi:schemaLocation attribute as shown below. Note that to use this attribute, it's necessary to declare the namespace for XML Schema.

<?xml version="1.0" encoding="UTF-8"?>
<f:view xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://java.sun.com/jsf/facelets facelets-ui-2.0.xsd
        http://java.sun.com/jsf/core jsf-core-2.0.xsd
        http://java.sun.com/jsf/html html-basic-2.0.xsd">
    <html>
        <body>
            <h2>My name is Duke. What's yours?</h2>
            <h:form id="helloForm" prependId="false">
                <h:graphicImage url="/wave.png"/>
                <h:inputText id="name" value="#{HelloBean.name}"/>
                <h:commandButton id="submit" action="success" value="Submit"/>
            </h:form>
            <h2>Folks who stopped by to say "Hi!"</h2>
            <ul>
                <ui:repeat var="_name" value="#{GuestBook.names}">
                    <li>#{_name}</li>
                </ui:repeat>
            </ul>
        </body>
    </html>
</f:view>

If you were to open this document in any XML editor that is capable of digesting XSD and providing code assistance (which is pretty much any XML editor) you now get tag completion for standard JSF component elements and attributes in addition to standard HTML attributes! Try it out for yourself by downloading the sample code[1] attached.

The only slight drawback is that the root tag is not <html>, so you don't get the out of the box preview with a standard HTML viewer. Assuming that matters to you, the problem with making <html> the root tag is that HTML does not accommodate other vocabularies in the document. The schema for HTML lacks <xs:any> declarations that would allow foreign tags to be present. And unfortunately, the HTML schema is pretty much fixed in stone. There is an effort for modularizing XHTML, but it still isn't widely adopted. For now, it's easier just to interweave HTML tags into the <f:view> document root than it is the other way around.

Now, you might be thinking that creating the XSDs is just one more step in a long process to create a JSF component library. I'm here to say that the transformation from TLD to XSD should be a migration away from TLD in favor of XSD. XML Schema is an incredibly comprehensive at defining XML dialects and there is absolutely nothing that TLD can describe that XML Schema cannot. Unlike TLD, XSD even has the ability to declare which facet names a component supports. Scrap TLDs!

What's your type, Doc?

There's one shortcoming in this setup. We had to remove the DOCTYPE definition at the top of the document so that the XML editor doesn't complain about the presence of the JSF component tags (which are obviously not declared in the XHTML DOCTYPE). XML Schema is a replacement for DOCTYPE and as such, the two are mutually exclusive. But if you think about it, the DOCTYPE is not there to validate the syntax of the template. It's really part of the output, meant to instruct the browser how to render the page. Therefore, the DOCTYPE should be rendered by a component tag just like any other markup-producing area of the template.

Unfortunately, the standard HTML component library does not include a tag that outputs a DOCTYPE. But you can quickly define a prototype of this tag using a JSF 2.0 composite component (or you can go all the way and create a real UIComponent). The following fragment from the file resources/meta/doctype.xhtml defines the <meta:doctype> tag as a composite component:

<comp:interface name="doctype" 
    displayName="XHTML DOCTYPE"
    shortDescription="Produces an XHTML DOCTYPE declaration">
    <comp:attribute name="type" required="true"/>
</comp:interface>
<comp:implementation>
    <h:outputText value='&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 #{
        fn:toUpperCase(fn:substring(compositeComponent.attrs.type, 0, 1))}#{fn:substring(compositeComponent.attrs.type, 1, -1)
        }//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-#{compositeComponent.attrs.type}.dtd"&gt;' escape="false"/>
</comp:implementation>

Then you simply add this tag directly inside of <f:view>.

<?xml version="1.0" encoding="UTF-8"?>
<f:view xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:meta="http://java.sun.com/jsf/composition/meta"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://java.sun.com/jsf/facelets facelets-ui-2.0.xsd
        http://java.sun.com/jsf/core jsf-core-2.0.xsd
        http://java.sun.com/jsf/html html-basic-2.0.xsd">
    <meta:doctype type="strict"/>
    <html>
        ...
    </html>
</f:view>

It's pretty clear that the standard HTML component library should include a component tag capable of producing all of the valid HTML and XHTML doctypes. There's no reason a developer should have to assume the burden of something that is so fundamental to web page development.

Breakout

Tell me what you think of this idea. Do you think it will help development? Do you think it will lead to better tooling? If it's worth pursuing, I think the XSDs should be built automatically from the metadata in the standard faces-config.xml and through reflection of the component classes/renderers so that you, the developer, don't have to worry about creating them and making them available on the file system. And of course, the tooling should help you get the XSDs added to the template.

Attachments

  1. facelets-xsd.zip

Step right up and select your time zone

Posted by    |       |    Tagged as Discussions JSF

Prior to revision 2.0, the JavaServer Faces specification states that all dates and times should be treated as UTC, and rendered as UTC, unless a time zone is explicitly specified in the timeZone attribute of the <f:convertDateTime> converter tag. This is an extremely inconvenient default behavior. This open proposal, targeting the 2.1 release, extends the Locale configuration to accommodate a default time zone preference that is used by default when a date is rendered.

Note: Dates are always assumed to be defined using UTC, so this proposal merely addresses the display offset.

Making the system time zone the default

The JavaServer Faces 2.0 (proposed) specification offers a way to override the standard time zone setting of the JavaServer Faces application so that it uses the time zone where the application server is running (which happens to be the default behavior for Java SE according to java.util.TimeZone) rather than UTC. This override is activated using the following web.xml context parameter declaration, documented in section 11.1.3:

<context-param>
    <param-name>javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE</param-name>
    <param-value>true</param-value>
</context-param>

Before diving into the implications of using the system time zone, I want to first suggest either renaming this parameter or removing it in favor of a comparable setting defined in faces-config.xml. Assuming the context parameter remains the preferred way of making the system time zone the default, there's no way anyone except JSF experts will be able to commit this parameter to memory due to its unnecessarily long name. I would like to put forth an alternate, simpler name:

javax.faces.USE_SYSTEM_TIMEZONE

In addition to name being shorter, it's much less specific, opening the door for other areas of JSF to take advantage of this setting. (An alternative configuration defined in faces-config.xml is proposed further down).

Naming aside, this setting is important because it allows the developer to restore the default time zone behavior of the JVM. However, it does not address the real problem that JSF was attempting to solve, which is that the time zone used by the application should not be affected by the geographic location of the deployment. Optimally, the default time zone should reflect the time zone preference of the user (i.e., it should be a user time zone).

Setting the default time zone in JSF

Time zones are extremely important in data-driven web applications. That's why the JSF runtime should make it easy for the developer to get the time zone setting correct. Both the UTC and the system default time zone choices are inadequate. The UTC default is annoying because it forces every developer to deal with the time zone issue on day one (no good default). The system default is risky because it's dependent on the geographic location where the application is deployed.

Let's consider a scenario where the system default is inadequate.

If I am deploying my application to a server in California and servicing New York customers, the default time zone is not what the customers expect. Now, I could start my application server instance with the time zone of New York. But what if I have a separate application on that server that services customers in California? Then I have a major conflict.

The correct solution is to allow the time zone to be set per JSF application, configured in faces-config.xml. In fact, there is already an ideal place to define this configuration: within the <locale-config> element, complementing the default locale. The developer would specify a time zone ID in the new <default-time-zone-id> element and JSF would resolve a TimeZone object from this ID. Here's an example showing the default time zone set to New York.

<application>
    <locale-config>
        <default-time-zone-id>America/New_York</default-time-zone-id>
    </locale-config>
</application>

However, a static value is not always sufficient since the users of an application may reside in different time zones. Therefore, while a static value is permitted, this element should also accept a ValueExpression that is resolved when the time zone value is needed (i.e., such as during encoding). The permitted use of a ValueExpression allows the default time zone to be dynamic, but still a default since it can be overridden by the <f:convertDateTime> component tag.

<application>
    <locale-config>
        <default-time-zone-id>#{userPreferences.timeZoneId}</default-time-zone-id>
    </locale-config>
</application>

This configuration setting provides three important features:

  1. Provides a good application default (which may be customized to the user's preference using a ValueExpression)
  2. Remains stable across deployment locations (doesn't change just because the application is deployed to a different time zone, as is the case with the system default)
  3. Isolated per application running on the same server

With this feature available, JSF will perform the following time zone resolution algorithm.

If a default time zone ID is specified in a configuration resources (i.e., faces-config.xml), then the TimeZone resolved from the specified ID is used as the default time zone in the JSF application. If one is not specified, JSF will use the system default time zone if the javax.faces.USE_SYSTEM_TIMEZONE context parameter value is true or UTC otherwise.

But instead of relying on a context parameter to set the time zone to the system default, it may be better to introduce the <system/> element as a possible value for <default-time-zone-id> to keep the time zone setting contained within the JSF configuration. (Context parameters in the web.xml configuration should only be used for defining implementation-specific settings).

The addition of the <default-time-zone-id> child element in <locale-config> requires the following API additions to javax.faces.application.Application.

/**
  * <p>Return the default <code>TimeZone</code> for this application. This
  * method resolves the Value Expression returned by {@link Application#getDefaultTimeZoneId}
  * and uses that value to look up a <code>TimeZone</code> instance. If the
  * resolved time zone id is null, the <code>TimeZone</code> for UTC is returned.</p>
  */
public abstract TimeZone getDefaultTimeZone();

/**
 * <p>Set the default time zone for this application as a value expression that
 * is expected to resolve to a time zone id.</p>
 *
 * @param timeZoneId The new default time zone
 *
 * @throws NullPointerException if <code>timeZone</code>
 *  is <code>null</code>
 */
public abstract void setDefaultTimeZoneId(ValueExpression timeZoneId);

/**
 * <p>Return the default time zone for this application as a value expression
 * that is expected to resolve to a time zone id.<p>
 */
public abstract ValueExpression getDefaultTimeZoneId();

What about auto-detecting the user's time zone?

The main challenge is that browsers don't send a preferred timezone header like they do a preferred language header. And you can't rely on a geo-IP address resolution since VPNs and other network configurations can move the source address across timezones. For now, it's the application's responsibly to collect the user's preference and store it in either the database or a browser cookie. The ValueExpression defined in the <default-time-zone-id> element is expected to return this stored value.

Provide your feedback

Let me know what you think about this solution. Does it seem adequate? Do you think the configuration is simple enough? Am I missing something? (Please see the JSF 2.1 page on the Seam Wiki for the latest revision of this proposal).

I encourage you to start participating now in these and other issues so that JSF can continue to improve as a result of community participation and feedback. JSF 2 is a big step in the evolution of JSF, but it is by no means the last.

The first part of my new article, published today on JSFCentral, explains how you can increase the rendering performance of a data-driven, JSF-based Seam application by two orders of magnitude! The article originated out of a contract job I did over the summer (before joining Red Hat). I worked for a group of scientists to develop a data-driven application using Seam, JSF, and RichFaces. That means it comes straight to you from the real-world ;)

In the article, I point out several easy-to-fall-into traps that can hinder the performance of your application and go on to present several best practices that ensure your JSF-based Seam application can give the responsiveness of a desktop application a run for it's money. Go see for yourself! Sadly, you'll have to wait for part 2 to unfold to discover all the secrets and realize the full benefit.

You might be wondering what else I've been up to lately. JSF2, JSF 2, and more JSF 2. Over the course of the last several weeks I have been working on submitting proposals and implementations to port features from Seam to JSF 2. It's hard work because we're not just throwing the features over the fence, but working with the expert group to improve on them and ensure they integrate well with JSF, rather than just tacked onto the side. If things move along smoothly, I should be rolling out some blog entries about what is changing and how to use the new features.

JSF 2.0. Test Drive PDL. Part 4a. Happy End

Posted by    |       |    Tagged as JSF Rich Faces

In the previous article we spoke about annoying issue of the Mojarra 2.0.0 PR when the empty attributes are rendered to the final html code. The issue was posted to the Mojarra project: https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=940

Now, it is fixed. Let's take a new version of Mojarra 2.0.0 . It is not a PR release, but the SNAPSHOT dated 01/27/08.

The SNAPSHOT has two more surprises.

First, we can use c:if to have a conditional insert now. We speak about it in the Part 2.

Second, there is no composite:insertChildren any more. This tag was replaced with composite:renderUsingPageChildren. It is more correct semantically, but requires some time to memorize.

Ok, this is code of the component that works:

<!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:c="http://java.sun.com/jsp/jstl/core"
      xmlns:composite="http://java.sun.com/jsf/composite">
 <head>
  <title>panel</title>
 </head>
<body>
 
<composite:interface>
    <composite:attribute name="style" required="false"/>
    <composite:attribute name="styleClass" required="false"/>
    <composite:attribute name="headerClass" required="false"/>
    <composite:attribute name="bodyClass" required="true"/>
</composite:interface>
 
<composite:implementation>
    <h:outputStylesheet name="rich/css/panel.css" />
 
 <div class="rich-panel #{compositeComponent.attrs.styleClass}"
   style="#{compositeComponent.attrs.style}"
   onclick="#{compositeComponent.attrs.onclick}" 
   ondblclick="#{compositeComponent.attrs.ondblclick}"
   onkeydown="#{compositeComponent.attrs.onkeydown}"
   onkeypress="#{compositeComponent.attrs.onkeypress}"
   onkeyup="#{compositeComponent.attrs.onkeyup}"
   onmousedown="#{compositeComponent.attrs.onmousedown}"
   onmousemove="#{compositeComponent.attrs.onmousemove}"
   onmouseout="#{compositeComponent.attrs.onmouseout}"
   onmouseover="#{compositeComponent.attrs.onmouseover}"
   onmouseup="#{compositeComponent.attrs.onmouseup}">
  <c:if test="#{! empty compositeComponent.facets.header}">
   <div class="rich-panel-header #{compositeComponent.attrs.headerClass}">
    <composite:insertFacet name="header"/>
   </div>
  </c:if>
 
  <div class="rich-panel-body #{compositeComponent.attrs.bodyClass}" > 
   <composite:renderUsingPageChildren />
  </div> 
 
 </div>
</composite:implementation>
</body>
</html>

This is a deployed example: http://livedemo.exadel.com/richfaces4-panel-4a/home.jsf

If you look at the result html code, you can see what no more empty attributes inserted.

JSF 2.0. Test Drive PDL. Part 4. PassThru attributes

Posted by    |       |    Tagged as JSF Rich Faces

Every JSF component has some specific attribute set unique for it. At the same time, almost all UI components have attributes that are common for all of them. For example, onclick, ondblclick, onblur, onmouseover, onmouseout, onmousedown and so on. They are named PassThru because they are rendered one-to-one to the final html layout.

RichFaces CDK uses a special meta-attribute x:passThruWithExclusions. Like:

<div x:passThruWithExclusions="id,value,styleClass,class" ....>

This attribute directs to insert all PassThru attributes as attributes to this particular div except ones that are explicitly mentioned. Just one attribute, short and not so hard. Let see how JSF 2.0 PDL might help.

In the first article about PDL, we define only four style kind attributes for the sake of simplicity.

<composite:interface>
    <composite:attribute name="style" required="false"/>
    <composite:attribute name="styleClass" required="false"/>
    <composite:attribute name="headerClass" required="false"/>
    <composite:attribute name="bodyClass" required="false"/>
</composite:interface>

Now, we are going to complete the missing part. According to the rich panel TLD documentation, it has 10 PathThru onxxxxxx attributes. To test how they work let's add the following to the test page:

  <rich4:panel onmouseover="this.style.backgroundColor='#F9F9FF'"
      onmouseout="this.style.backgroundColor='#FFF'">
   <f:facet name="header">
    <h:outputText value="This is a header"/>
   </f:facet>
   <h:outputText value="panel with header"/>
  </rich4:panel>

BTW, the composite:interface above contains explicit declaration for four style attributes. What happen if we remove them like that:

<composite:interface>
</composite:interface>

Actually, nothing is changed. The component and its styling work without any changes. This is because of the Facelets feature when Facelets implicitly pass any attributes defined by the end developer, instead of classic JSP where missing an attribute name in the TLD file is a big deal. Let's consider this Facelets feature as an advantage, at least for the size of the component code.

One drop of poison infects the whole tun of wine - if you have a typo in the attribute name, figuring it out is your personal problem. No any warning. However, declaring the attribute explicitly in the composite:interface, even the required="true" does not help. Still the same silence.

Does the composite:interface make sense at all. Yes!!! Do not forget about the most fabulous keyword of the JSF market - the Tools. The JSF tool, if it is smart enough, prompts you with the list of possible attribute sorting them by priority, helps with signature of the method and so one. According to the pdldoc for composite:attribute, it has a lot of useful (for the tools) attributes.

Let's return to the topic. Does the ability to implicitly declare attributes work for our onmouseover, onmouseout? ...Partly. We do not need to declare them implicitly in the composite:interface section (ok, ok. we still need to be kind to the future tools). However, PDL has no idea where to insert them in the composite:interface section. Thus, the test example does not work yet.

Mojarra implementation of PDL has nothing to shortcut the size of required code. Copy/Paste is a way to go. We will add the following as attributes of the top div:

onclick="r#{compositeComponent.attrs.onclick}"
ondblclick="r#{compositeComponent.attrs.ondblclick}"
onkeydown="r#{compositeComponent.attrs.onkeydown}"
onkeypress="r#{compositeComponent.attrs.onkeypress}"
onkeyup="r#{compositeComponent.attrs.onkeyup}"
onmousedown="r#{compositeComponent.attrs.onmousedown}"
onmousemove="r#{compositeComponent.attrs.onmousemove}"
onmouseout="r#{compositeComponent.attrs.onmouseout}"
onmouseover="r#{compositeComponent.attrs.onmouseover}"
onmouseup="r#{compositeComponent.attrs.onmouseup}"

Now, we can see how it works: http://livedemo.exadel.com/richfaces4-panel-4/home.jsf

Looks like we are all set. However, let's look what is actually rendered:

 <div class="rich-panel " style="" onclick="" ondblclick="" onkeydown="" 
        onkeypress="" onkeyup="" onmousedown="" onmousemove="" 
        onmouseout="this.style.backgroundColor='#FFF'" 
        onmouseover="this.style.backgroundColor='#F9F9FF'" onmouseup="">
   <div class="rich-panel-header ">This is a header
   </div>
 
  <div class="rich-panel-body ">panel with header
  </div> 

 </div>

We have a bunch of empty attributes out. Even the browser can have a deal with that, it is not acceptable result the end application developers will be happy with. The attribute should not appear in the result code if it is empty. So far, I did not find a solution how to avoid it in Mojarra 2.0.0 PR. The issue is posted.

JSF 2.0. Test Drive PDL. Part 3. Resources

Posted by    |       |    Tagged as JSF Rich Faces

If you compare the look-n-feel of our new panel after step #2 and the one on the richfaces-demo, you can see one important difference. Our new panel misses the gradient in the header background.

Let's try to find a solution using JSF 2.0 PDL.

RichFaces components have one important peculiarity. They are skinnable based on the predefined set of skin paramaters. Most graphic images used in the components, such as the gradient background image of the rich panel, are not static, but generated with the java classes using the same set of skin-parameters.

In the JSF 2.0 PDL, we can refer to a resource such as an image using the following expression:

#{resources['foo/bar/foobar.gif']}

According to the Mojarra spurce code, it reads only the static resource from the classpath and hardcodded folder 'resources' from the web root. Mojarra does not presume that resource can be generated dynamically. Thus, for the sake of simplicity, let's drop the idea of skinnability for now and take the gradient for default blueSky skin.

We have drop the static image to the {webroot}/resources/img/ folder and add just three lines to the css file:

.rich-panel-header{
 ....... 
 background-position:left top;
 background-repeat:repeat-x;
 background-image: url(#{resource['rich/img/panel_header.png']})
}

That is it. We can see the gradient in the panel header background now. The new panel after step #3 looks like that:

http://livedemo.exadel.com/richfaces4-panel-3/

JSF 2.0. Test Drive PDL. Part 2. Conditional Insert

Posted by    |       |    Tagged as JSF Rich Faces

As it was mentioned previously, rich:panel shows the header only if the facet name="header" is defined. Otherwise, it is just omitted.

In case the header presents, its content is wrapped with div:

  <div class="rich-panel-header #{compositeComponent.attrs.headerClass}">
   <composite:insertFacet name="header"/>
  </div>

What happens in the code above if panel has no header facet on the xhtml page? PDL processor just inserts nothing inside the div without any notes (the same happens, BWT if you have a typo in the facet name). However, it is not what we need, as we need to omit the whole div.

In general, it looks like a common use case: if facet is missing, the whole block that represents the facet in the final layout is omitted. I did not find anything like that in the pdldocs. The second idea was to use a conditional operation.

The following EL returns true if header facet presents. Otherwise, it returns false.

#{! empty compositeComponent.facets.header}

Thus, the following snippet is a solution:

<c:if test="#{! empty compositeComponent.facets.header}">
  <div class="rich-panel-header #{compositeComponent.attrs.headerClass}">
   <composite:insertFacet name="header"/>
  </div>
</c:if>

However, it does not work. There is a good explanation why it does not work in this article:

http://www.ilikespam.com/blog/c:foreach-vs-ui:repeat-in-facelets

When the c:if test is evaluated the compositeComponent.facets is always empty. Hence, a header is not shown even when it presents. The solution is also in that article. We will use ui:fragment. The final code that is sensible to a header facet is following:

<!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:c="http://java.sun.com/jstl/core"
      xmlns:composite="http://java.sun.com/jsf/composite">
<head>

<title>panel</title>

</head>

<body>

<composite:interface>
    <composite:attribute name="style" required="false"/>
    <composite:attribute name="styleClass" required="false"/>
    <composite:attribute name="headerClass" required="false"/>
    <composite:attribute name="bodyClass" required="false"/>
</composite:interface>



<composite:implementation>
    <h:outputStylesheet name="rich/css/panel.css" />

 <div class="rich-panel #{compositeComponent.attrs.styleClass}"
            style="#{compositeComponent.attrs.style}">

  <ui:fragment rendered="#{! empty compositeComponent.facets.header}">
   <div class="rich-panel-header #{compositeComponent.attrs.headerClass}">
    <composite:insertFacet name="header"/>
   </div>
  </ui:fragment>
 
  <div class="rich-panel-body #{compositeComponent.attrs.bodyClass}" > 
   
   <composite:insertChildren />
  </div> 

 </div>
</composite:implementation>

</body>

</html>
update January 19, 2009:

Today we have been notified that it will be possible to use c:if as well as other jstl like tags for conditional operations inside the templates.

back to top