Hi.

I would like to run an idea by the community to check that I am not
being crazy in doing this stuff. I would appreciate any comments,
criticism, ideas and whether you think that this approach might be worth
including in the MyFaces implementation. 

I was thinking about JSF's error processing mechanism, specifically
about how label text gets associated with an input field. So, I am
talking about this kind of stuff: 

<h:outputLabel for="firstName"
value='#{msgs["applicant.search.firstName"]}: ' /> 
<h:inputText id="firstName"
value='#{applicantDetailsBackingBean.firstName}' required=”true”/> 

If the value is not entered into the input field, we will get an error
message saying: 

’First Name’: is required 

So HtmlMessageRenderer has replaced the field id in the FacesMessage
with the label text by using the association set up with the 'for'
attribute on the label. All of this message "decoration" work happens in
the RENDER phase in a centralized location. I see a couple of weaknesses
in this approach: 

1) It is too late for resolving label text data if the label is inside a
data table 
2) JSF establishes associations between label text and the input fields
by using the label components to point to their input fields. Although
this seems more natural, it limits label text sources to just the label
components present on the current page (or whatever is nested under
them), which makes it impossible to associate input field messages with
label text that does not exist on the page in its entirety. 

Let's look at a couple of hypothetical examples the kinds of which I ran
into in my application: 
1) Consider a situation in which we have a dataTable where every row
consists of a student name and an input field for entering their
assignment mark. The validation on the input field will be restricted to
valid letter grades only. If the user enters an invalid grade, we want
them to see an error message of the form: “The mark entered for <student
name> is invalid”. Since <student name> is dependent on the row in which
the error occurred, this error message would very hard to generate with
bare JSF functionality. 
2) Another situation that gets us in trouble is when the label text we
want in our error message is not on the page (or not in it's entirety).
For example, your page could be split up into multiple parts with those
parts having input fields with the same name. We would want the error
message to include the page part as well as the field name. This is not
easily achieved with the bare JSF functionality. 

So to generalize, any situation where a label component with a static
value throughout the lifecycle is not available will cause difficulty. 

Please correct me if I am wrong on any of these points. 

Since in my app I had a lot of complicated pages to deal with, I decided
to write a very simple framework that I called Message Decorator
Framework (MDF). It enabled me to easily construct much more detailed
error messages than what the standard JSF approach seems to allows for.
MDF provides a mechanism to specify the label text to be applied to a
validation or a conversion message by either a literal, an el expression
or via an id of another ValueHolder. All of these work in data tables. 

The idea is as such, and this is what i would like your opinion on: 

MDF provides more flexible message decoration by adapting the opposite
approach to the one used by JSF: 
1) Message decoration is decentralized. MDF wraps converters and
validators on individual input fields and performs message text
replacement right on the spot in the PROCESS_VALIDATIONS phase, when all
of the pertinent data for resolving the label text is still
available.(i.e the components in data tables would still have the
correct values for the current row being validated) 
2) The label text to be used is specified by the input field, not the
label. This allows the developer to reference any text value, instead of
tying them to a specific label component. 

Pictures are better than words, so here is an architectural diagram:
http://www.imagehosting.com/out.php/i1259440_ArchitectureDiagram.png

The framework consists of two main classes, ConverterMessageDecorator
and ValidatorMessageDecorator. I will just talk about the converter
part, b/c the validator part is very similar but wraps a list of
validators instead of one converter. 

So ConverterMessageDecorator is a JSF converter. Its purpose is to wrap
the converter that is going to do the actual conversion work and
decorate the FacesMessage inside ConverterException if one was thrown. 
The converter to wrap can be either determined automatically based on
the type of the value reference of the input field or specified
explicitly. This converter decorates the message by replacing all
instances of the input field’s id with the resolved label text. The
power of this approach is that not only do you get a much more flexible
way to specify what the label text is (either fieldLabel or
fieldLabelComponent attributes), but now data tables are no longer a
problem. 

Here are some usage examples: 

<h:inputText
value='#{section33SetupBackingBean.contribution.sampleGatePct}'> 
   <md:decorateConverterMessage fieldLabel=
'#{msgs["section.34.setup.contribution.initial.sampling.gate.max.size"]}' /> 
</h:inputText> 
  
…etc… 
  
<h:inputText
value='#{section33SetupBackingBean.payment.sampleGatePct}'> 
   <md:decorateConverterMessage fieldLabel=
'#{msgs["section.34.setup.payment.initial.sampling.gate.max.size"]}' /> 
</h:inputText> 


The two input fields have exactly the same labels on the screen (they
are in two different parts of the page), so if we used their respective
labels, the error messages would look the same for these two input
fields. More complicated example: 

<h:dataTable value="#{paymentCalcBackingBean.currentPaymentPercentages}"
var="currentPercentage" > 
<h:column> 
  <ops:refDataDescription id="provinceLabelTextId"
refDataType="provinceStateType" 

code="${currentPercentage.programProvince.provinceStateTypeCode}" /> 
</h:column> 
<h:column> 
  <h:inputText value="${currentPercentage.federalPercentage}"> 
<md:decorateConverterMessage fieldLabelComponent="provinceLabelTextId"
 valueRequired="true" > 
   <f:converter converterId="ops.PercentageConverter" /> 
</md:decorateConverterMessage> 
<md:decorateValidatorMessage fieldLabelComponent="provinceLabelTextId"
> 
   <f:validator validatorId="ops.PercentageValidator" /> 
</md:decorateValidatorMessage> 
</h:column> 
…etc… 
</h:dataTable> 


This would produce errors shown in this screen shot:
http://www.imagehosting.com/out.php/i1259418_Example3.png

Here is another example that shows off what you can do by referencing
other ValueHolders on the page. 
The code is exactly the same as the snippet shown above, but the
inputText component is referencing a text box, so the label text is
going to be whatever the user types into the text box: 
http://www.imagehosting.com/out.php/i1259467_Example4.png


Does this approach seem reasonable, or am I reinventing the wheel?
Please let me know. 



Val


Reply via email to