In JSF 1.2, our TLD now includes: <deferred-value><type>String.class</type></deferred-value>
... for any String-typed property. This is all seems well and good, since it means that our runtime is getting String objects instead of needing to manually cast to string. However, section 1.18.2 of the EL spec has some lousy language: 1.18.2 CoerceAtoString ■ If A is String: return A ■ Otherwise, if A is null: return"" ■ Otherwise, i fA is Enum, returnA.name() ■ Otherwise, if A.toString() throws an exception, error ■ Otherwise, return A.toString() Specifically, it's that second bullet. Now, if you have an EL binding to a String, and return null, we're getting the empty string, never null. That's fine if you don't care about the difference, but we almost always do. For example, ResponseWriter.writeAttribute() will actually write out the attribute, so you'd get: <span class="">...</span> if you had an EL binding for styleClass that conditionally returned null. We have two choices: (1) In many, many locations, start checking for the empty string. (2) Don't use String.class as a deferred type, and convert to string in the code (again, at many, many locations). I strongly prefer #2, especially because our code is already good about converting to strings automatically. #1 means we're throwing away information - the empty string is not always the same thing as null - which is never a good idea. -- Adam
