Win a copy of Pro Spring MVC with WebFlux: Web Development in Spring Framework 5 and Spring Boot 2 this week in the Spring forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Ron McLeod
  • Paul Clapham
  • Jeanne Boyarsky
  • Liutauras Vilda
Sheriffs:
  • Rob Spoor
  • Bear Bibeault
  • Tim Cooke
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Piet Souris
Bartenders:
  • Frits Walraven
  • Himai Minh

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

 
Ranch Hand
Posts: 86
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Ranch Hand
Posts: 2458
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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 ]
 
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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 ]
 
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
You showed up just in time for the waffles! And this tiny ad:
Building a Better World in your Backyard by Paul Wheaton and Shawn Klassen-Koop
https://coderanch.com/wiki/718759/books/Building-World-Backyard-Paul-Wheaton
reply
    Bookmark Topic Watch Topic
  • New Topic