Actually, I think I got it to work with JSF 1.1 + jsp (and facelets)
fairly well (at least it worked on all of the pages of the JSP
application and the Facelets applications I tested it on).
I handled the addition of a converter or validators into the wrapper by
having my custom tag push a dummy UIInput tag onto the tag stack that
UIComponentTag uses and then having the wrapped converter/validators set
themselves up in the dummy component on the top of the stack as they
usually do (no changes there). Then when we come back up to the
doEndTag() of my wrapper custom tag, I simply steal all the
validator/converter info from my dummy UIInput and apply it to the
wrapper, which then applies itself to the actual parent UIInput. So this
adds a level of indirection, but it is entirely handled by the custom
tag during page compilation. This way it works out to be fairly non
intrusive.
I used a similar approach for Facelets, but it was of course much easier
to do via a custom MetaTagHandler.
What problems with JSF 1.1 + jsp did you have in mind?
Also, a question on mailing list protocol, if you don't mind. This is my
first attempt at participating in developer mailing lists so I am
uncertain what would be a more appropriate way to show this thing to
Tomahawk guys - reposting the whole thing in the tomahawk list, or
referencing the post I made here?
Thanks.
Val
On Wed, 2007-24-10 at 11:57 -0400, Mike Kienenberger wrote:
> It would definitely be a Tomahawk thing rather than a MyFaces Core change.
>
> I haven't looked at your architecture in detail, but trying to wrap a
> validator or converter is problematic, at least under JSF 1.1 + jsp.
> It will probably work for JSF 1.2 or JSF 1.1 with facelets, though, if
> I remember right.
>
> =====================================================
> On 10/24/07, Val <[EMAIL PROTECTED]> wrote:
> > Hi, Martin.
> >
> > The change I am proposing is completely independent from Tomahawk. Since
> > the message decoration happens in the wrapper converter/validator, we
> > get to decorate any JSF message with or without Tomahawk. In fact, this
> > should work with any bare JSF implementation and it supersedes
> > Tomahawk's error-message decoration functionality.
> >
> > Do you think this approach would be useful for MyFaces or is this
> > something that is more down Tomahawk's alley?
> >
> > Val
> >
> > On Wed, 2007-24-10 at 09:46 +0200, Martin Marinschek wrote:
> > > Hi Val,
> > >
> > > I was just referring to your code snippet, which didn't show you were
> > > using Tomahawk. So you don't want to change JSF
> > > error-message-handling, but Tomahawk message-handling?
> > >
> > > regards,
> > >
> > > Martin
> > >
> > >
> > >
> > > On 10/19/07, Val <[EMAIL PROTECTED]> wrote:
> > > > Yes, I am using tomahawk 1.1.2. Specifically, I use the <t:messages> tag
> > > > to display my errors, which uses
> > > > org.apache.myfaces.renderkit.html.ext.HtmlMessagesRenderer.
> > > >
> > > > The code that does the replacement of input field id with the associated
> > > > label's value is in
> > > > org.apache.myfaces.renderkit.html.ext.HtmlMessagesRenderer. Both
> > > > getSummary() and getDetail() methods look up the associated label and
> > > > use its value if found...
> > > >
> > > > Why do you think that there should be no error processing?
> > > >
> > > > Val
> > > >
> > > > On Fri, 2007-19-10 at 09:53 +0200, Martin Marinschek wrote:
> > > > > You are not reinventing the wheel - first, are you using tomahawk?
> > > > > Cause if you use the standard-components you said you use, I wonder
> > > > > why you get this error-handling at all, you should only see the client
> > > > > id, so like this:
> > > > >
> > > > > > 'firstName': is required
> > > > >
> > > > > regards,
> > > > >
> > > > > Martin
> > > > >
> > > > >
> > > > > On 10/18/07, Val <[EMAIL PROTECTED]> wrote:
> > > > > > 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
> > > > > >
> > > > > >
> > > > > >
> > > > >
> > > > >
> > > >
> > > >
> > >
> > >
> >
> >