Forums Register Login

Problem with f:validator & f:attribute - EL does not evalute in f:attribute

+Pie Number of slices to send: Send
Hi Experts,
I'm to using custom validator in my application.
<h:dataTable value="#{requirementBean.questionList}"
var="questions"
id="questionTable"
columnClasses="none,tableRowOdd"
rowClasses="tableRowEven,tableRowOdd"
cellpadding="1"
cellspacing="1"
width="100%">

...................
.......................
<h:inputText rendered="#{questions.displayType eq 'TextBox'}" id="inputTextid" value="#{questions.defaultAnswerString}">
<f:validator validatorId="dataTypeValidatorId" />
<f:attribute name="dataType" value="#{questions.dataType}"/></h:inputText>


"dataTypeValidatorId" is a custom validator which im using in my application.
The problem is that the f:attribute tag is not working in case of EL expressions, the way i have used above ( <f:attribute name="dataType" value="#{questions.dataType}"/>).
I get value as null in my validator code.
Here's my validator code.

public void validate(FacesContext arg0, UIComponent component, Object value) throws ValidatorException {
Map map = component.getAttributes();
String str = (String) map.get("dataType");
if(str != null && "String".equalsIgnoreCase("str")){
.........
..................
}


But when i put static value in the value attribute of the f:attribute tag , every thing works fine...some thing like this
<f:attribute name="dataType" value="Integer"/>, then i get proper vlaue in the validator code.

Even though the specifications says that f:attribute can take static values as well as EL expressions.

Any ideas? Whats the reason and how to solve it.? It's very important please provide me with some help.

Thanks.
Ved
+Pie Number of slices to send: Send
Nasty stuff .. I've debugged it and it turns out that the f:attribute is called only once per initialisation. And always the first value is retrieved and stored. So all f:attribute elements contains the same value.

I suggest you to use the UIViewRoot in the datatypeValidator class, retrieve the parent datatable from it and finally get the row object from it. Quick example:


[ November 05, 2006: Message edited by: Bauke Scholtz ]
+Pie Number of slices to send: Send
Hi.

Because of lack of examples a lot of people got into the same issue: they add attribute to UIComponent with some EL expression but in the Validator they couldn't get the value by callng component.getAttributes().get("attributeName"). Last one always returned null. But for some reason if the add attribute with plain text value it worked fine.

Today I decided to digg into it and after re-reading specification for JSF 1.2 I got the answer: there are 2 places for attribute values! Here is the quote of the description for section "9.4.2 <f:attribute> (page 9-17)":

"If the associated component already has a component attribute with that name, take no action.
Otherwise, call the isLiteralText() method on the argument value. If it returns
true, store the value in the component�s attribute Map under the name derived above.
If it returns false, store the ValueExpression in the component�s ValueExpression
Map under the name derived above."

In other words we looked for value in wrong place. If value of f:attribute is EL expression we should use component.getValueExpression("attributeName") to get ValueExpression instance and call getValue(elContext) to get theValue.

Here is 2 examples.

Example 1. Value of attribute is plain text.

Page code:

<h:inputText id="userName" value="#{mybean.userName}">
<f:attribute name="payCode" value="regular"/>
<f:validator id="userNameValidator"/>
</h:inputText>
...
faces-context.xml

<validator>
<validator-id>userNameValidator</validator-id>
<validator-class>your.package.UserNameValidator</validator-class>
</validator>
...
Validator code

public class UserNameValidator implements Validator {

public void validate(FacesContext context, UIComponent component, Object value) {
String paycode = component.getAttributes().get("payCode");
...

}

Example 2. Value of attribute is EL (expression language).

Page code:

<h:inputText id="userName" value="#{mybean.userName}">
<f:attribute name="payCode" value="#{otherBean.payCode}"/>
<f:validator id="userNameValidator"/>
</h:inputText>
...
faces-context.xml

<validator>
<validator-id>userNameValidator</validator-id>
<validator-class>your.package.UserNameValidator</validator-class>
</validator>
...
<managed-bean>
<description>Some other bean we get value from. Scope "request" just for example. It could be session or application too or even no scope</description>
<managed-bean-name>otherBean</managed-bean-name>
<managed-bean-class>your.package.OtherBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>

OtherBean code:

public class OtherBean {

private PayCode payCode;
...

public PayCode getPayCode() {
return this.payCode;
}

public void setPayCode(PayCode payCode) {
this.payCode = payCode;
}
}


...
Validator code

public class UserNameValidator implements Validator {

public void validate(FacesContext context, UIComponent component, Object value) {
ValueExpression ve = component.getValueExpression().get("payCode");
PayCode paycode = (ve != null) ? (PayCode)ve.getValue(context.getELContext()) : null;

...

}



I beleive that you could extend my examples for JSF Converters, ValueChangeListeners and ActionListeners. Now you know where look for attribute value!
[ September 03, 2008: Message edited by: Viacheslav Garmash ]
+Pie Number of slices to send: Send
Greetings,

I have the same problem with the <f:attribute> and i need to submit an EL value inside a commandButton, because i tried <f:param> and it doesn't work with the commandButton.
Then i found your solution but unfortunately the function getValueExpression is undefined for UIComponent , so i think i missed something in your solution can you please explain how to get the expression value of the attribute using only the event object inside the actionlistener of a commandButton?

Thanks in advance
If you have a bad day in October, have a slice of banana cream pie. And this tiny ad:
a bit of art, as a gift, the permaculture playing cards
https://gardener-gift.com


reply
reply
This thread has been viewed 12634 times.
Similar Threads
problem with findComponent()
Passing parameters/ attributes to a custom validator
unalbe to pass attribute values to validator
retrieve UIComponent value in custom validator with EL expressions
JSF validation not validating
More...

All times above are in ranch (not your local) time.
The current ranch time is
Apr 16, 2024 08:51:00.