I am new to Java Server Faces. I have a project using JSF 2.0 API to dynamically create a web page. I create an HtmlPanelGrid, then dynamically add input text fields to the grid. I dynamcially add a custom validator to one of the fields. The issue is, that I need an extra value in the custom validator to complete the validation. Is there a way to pass a parameter to the custom validator using the API?
The more JSF-specific your solution is, the more likely it's a bad solution.
JSF was specifically designed to require a minimum of JSF-specific code, using POJO logic wherever it can. JSF-specific solutions tend to be overly-complex and fragile. And JSF is by no means mature enough that it's a good idea to assume that the various internal structures and methods cannot change radically from version to version. It's cheaper, faster, and less likely to cause unpleasant consequences when you work from the POJO perspective.
An ideal JSF webapp has almost nothing JSF-specific in its application code except for Model objects. Plus maybe a few lightweight appendages such as valuechange listeners for cascaded selections. And custom validators when none of the stock options suit.
If I was to make a rule #2, it would be "Never dynamically create any UI component that can be done more simply as a View Template (xhtml)".
You're not doing it right in any event. The way to get access to the View Component Tree is to use the binding attribute of a related Component, not to bull in and plunder straight from the raw internal data structures.
As for the actual problem: JSF doesn't encourage parameterized validators. While some of its built-in validator tags have attributes that control the allowable range, regex patterns or the like, the generic validator tag doesn't allow for such extensions. All it's allowed to do is bind to a validator API that operates in stateless mode. The same validator instance serves all references to that particular validator so setting bean properties is not an option in any event.
In short, there's no simple, clean, safe solution. If you could give details about what sort of tests this custom validator needs to perform and what its parameters would be used for, we might be able to come up with something.
An IDE is no substitute for an Intelligent Developer.
Joined: Aug 09, 2013
Thanks for the reply.
"The way to get access to the View Component Tree is to use the binding attribute of a related Component..."
Could you explain further? I took this project over from someone else and accessing the various components directly is how it was set up. Also what is POJO? Is this a framework?
I had to give K. Tsang a cow for that. I'm proud of him. He's learned his lessons well! :)
To be more precise, the main Controller in JSF is the FacesServlet. There are also sub-Controllers in the various tag implementations. That's not uncommon in a MVC implementation where the View is complex and based on canned components.
In answer to the question on binding, generally what you would do is define an anchor point for the dynamic components in the static View Template. For example, a 1x1 panelGrid works well:
Now if I wanted to be able to dynamically place GUI components within theBox, I'd write JSF bindingMethods like so:
As you can see, this is just POJO-style property access except that the property isn't a value, it's a component. You can then reference "theBox" in order to add/remove/alter child components of theBox without having to muck around in JSF's innards. The bean containing this property, of course, should NOT be Request Scoped. But then Request Scope and JSF don't have much in common at the best of times. Note that as is the case with all backing bean properties, this value is not guaranteed set until @PostConstruct time.
However, now that I've explained binding, I'm going to state that binding is WAY overused, as are actionListeners. Of all the JSF apps I've done, exactly 1 webapp uses binding. And even there, I've had second thoughts. The only real reason for using binding is if you need to dynamically modify part of the UI and you can't do it using one of the stock JSF elements such as a dataTable (which can add and remove rows). And even then, if you can, it's better to use the "rendered=" attribute to show/hide components than to actively modify the component tree itself. Discounting the fact that programmatic modification of the UI Component tree is more complex than working with fixed elements, too much mutability in the visual interface tends to confuse users. As in "This screen doesn't look anything like the screenshot in the manual!"