How to programmatically generate JSF components at run time? - jsf

I've got to create screens to display a lot of JPA entities in the View. It would be great to create one facelet and pass to it a collection of fields e.g. List<Object>.
The facelet/custom component would need to convert each element of the list into the appropriate tag for display e.g. an enum field to h:selectOneMenu, String field to h:inputText, etc. This would need to be done at run time.
What's the easiest way to do this?

Worked on a project previously that created entire pages dynamically from stored configuration. There are two basic things you need
A BackingBean. You'll used this to get access to the UIComponent on the facelet which will act as the parent to the generated UIComponents. Something like a panelGroup. But, you'll need to bind the UIComponent to the backing bean, in order to have a parent against which you'll add the dynamically-created UIComponents
Access to the Application component. Typically FacesContext.getApplication() (I worked on this in JavaEE 5, so it might look a little different with injection). Once you have the Application component, you call the createComponent method, passing in the type of component you want to create.
It then becomes an activity of creating components dynamically, configuring them in code and adding them to the parent UIComponent defined via a binding bean. It can be tricky, but it can be done.

Related

Form from Fragments and different Managed Beans in PrimeFaces Wizard

We're making usage of Primefaces Wizard component and the forms been included within the Wizard's TABs were declared inside some UI Fragments with their respective Managed Beans. Each one of the Managed Beans contains properties representing some Entities.
What we need to achieve is that, for every completed step, we take the above mentioned Entity property that was previously fulfilled and designate the same Entity property inside the Wizard Managed Bean, and later we may present the Entities data like a summary, so the user would decide whether to proceed or not.
I'm wondering whether there are some other options to accomplish that rather than set a Session variable across the Wizard navigation.
Is the JSF #ManagedProperty usage feasible?
Tks.

Can JSF be configured to not invoke Entity setter unless the field actually changed?

When a JSF form field is wired into an entity bean field (which is mapped to a DB field), each setter in the entity bean is called regardless of whether the user changed the form field value in the front end, i.e. the setters on unchanged fields are invoked the same as those that have changed but their new value is the same as the old value.
My question is simple: Is there a way to configure JSF to only call the setters mapped to the fields that have changed in the front end? The reason for this is that I have a requirement by which I have to detect deltas on every persist and log them, more about which can be read in this question.
Maybe I didn't understand you clearly, but why are you mapping directly your entity beans to a JSF view ?! IMHO it would be better if you add managed beans between your JSF pages and the entities in order to better separate your business logic from data access.
Any way, I think the easiest solution to impelement for that case is by making use of Value Change Events which are invoked "normally" after the Process Validations phase (unless you make use of the immediate attribute).
The good news about Value Change Events (regarding your example) is they are invoked ONLY after you force form submit using JavaScript or Command components AND the new value is different from the old value.
So, as an example on how to use value change listeners, you can add valueChangeListner attribute to each of your JSF tags like following:
<h:inputText id="input" value="#{someBean.someValue}"
valueChangeListener="#{someBean.valueChanged} />
Then, implement your valueChanged() method to look something like:
public void valueChanged(ValueChangeEvent event) {
// You can use event.getOldValue() and event.getNewValue() to get the old or the new value
}
Using the above implementation, may help you to separate your logging code (it will be included in the listeners) from your managed properties setters.
NB: Value Change Listeners may also be implemetend otherwise using the f:valueChangeListener Tag, but this is not the best choice for your example (you can find some examples in the section below, just in case)
See also:
Valuechangelistener Doubt in JSF
JSF 2 valueChangeListener example
When to use valueChangeListener or f:ajax listener?

How to get UIComponent value in Java?

I have a method in my JSF controller that is invoked by an ajax tag nested inside a visual component (really irrelevant which one). The method takes a single argument of type AjaxBehaviorEvent, from which I can obtain a Java representation of the invoking HTML visual component as a UIComponent and also downcast it to its specific corresponding type (e.g. h:inputText corresponding to HtmlInputText).
I understand that, in most cases, the value of the HTML visual component would be retrieved easily by referencing either the controller or entity [g|s]etters to which the form fields are mapped in the view. However, in my particular case, I would like to fetch the value of the visual component (in my case a form field) through its Java object rendering. While studying the faces API, I found ways to read various properties of the object, such as the ID or context but not the value that the component currently holds in the view.
Can anybody explain whether I am just not finding the right way to read it or it is so by design? If the latter, can you explain why it is designed like that? Is it to disable "backdoor" access to form fields as opposed to going through the view mapping?
There are a multitude of ways to pull values off a component. Going by what you already have UIInputt#getValue() and UIInput#getSubmittedValue() will provide the value.
The UIInput#getSubmittedValue() is fit for the purpose only between the APPLY_REQUEST_VALUES and VALIDATE phases of the JSF request. All other phases after, use the UIInputt#getValue(). You'll be using UIInput instead of the raw UIComponent you pulled from the event (UIInput extends UIComponent and it's the parent class for all input components that accept user-edited values). What you'll have will eventually look like:
UIInput theInput = (UIInput)event.getSource();
Object theValue = theInput.getValue();
There are other ways (not as clean) to get values within the request lifecycle also

How to access a composite component's sibling via clientId

I have a composite component that bundles some input fields. The component will be used multiple times on a page and contains a button to copy the values of another of these components. For this I would need to access one of those siblings via its clientId as a target for an
<f:ajax execute=":XXX:siblingId" render="...">
My problem lies in constructing this ID. I have the name of the sibling and I can make sure that it is located in the same naming container as the component that contains the copy button, but I can't control the complete nesting hierarchy, so it might be :form:foo:bar:parent:child or just form:parent:child. So essentially I would want to get the prefix of the current composite component, but without the component's own ID and then attach the ID of the component from which to copy.
This is similar to these questions:
How to address the surrounding naming container in jsf
How to access the parent naming container of composite
However, both answers make use of PrimeFaces-sepcific features like #parent and widgetVar, which does not apply to my project.
When experimenting with EL's implicit objects I basically tried the same things as the poster of the second question - with the same results: cc.parent.clientId is always empty. I also tried cc.namingContainer.clientId and some combinations of the two, alas - no success. Especially the fact that parent does not work as expected confuses me...
So: Is there a component-library-agnostic way to access the "path" of containing naming containers for a composite component? How is the parent object supposed to work, especially: when can we use it and when not?
PS: I was thinking about using the composite's full clientId and then trimming its actual ID with fn:split, however, if there was a more direct way I'd be happy to use it.
The #{cc.parent} resolves to UIComponent#getCompositeComponentParent() which returns the closest parent composite component. In other words, it returns only non-null when the composite component is by itself nested in another composite component.
The #{cc.namingContainer} simply refers to #{cc} itself, fully conform as specified in UIComponent#getNamingContainer():
Starting with "this", return the closest component in the ancestry that is a NamingContainer or null if none can be found.
Composite components namely implicitly implement NamingContainer themselves.
So your attempts unfortunately won't work. I also do not see any "standard API" ways to achieve the concrete functional requirement. The CompositeComponentAttributesELResolver causes that the #{cc.parent} doesn't resolve to UIComponent#getParent() which is what you ultimately want.
You can however provide a custom UIComponent implementation for the composite which adds an extra getter with an unique name which in turn properly delegates to UIComponent#getParent().
Here's a kickoff example:
#FacesComponent("myComposite")
public class MyComposite extends UINamingContainer {
public UIComponent getParentComponent() {
return super.getParent();
}
}
If you register it as follows in the composite interface:
<cc:interface componentType="myComposite">
then you'll be able to use
#{cc.parentComponent.clientId}
to get the client ID of the real parent UIComponent.
Ultimately you should be able to use the following construct to refer the sibling:
process=":#{cc.parentComponent.clientId}:siblingId"

Refreshing a component bind to request-scoped bean

Does anyone have a solution for such a problem:
In my app I'm using a complex, programmatically build dashboard based on the primefaces dashboard. To overcome problems with nonunique id's of the panels building the dashboard, I'm binding this component to a request-scoped bean. I'd also like to rebuild the dashboard based on some changable parameters after clicking a commandButton.
The problem is, that the getter for the dashboard is fired in the Apply Request Values phase, way before the actionListener of the commandButton is fired (in the Invoke Application phase). So, although the dashboard is rebuild eventually, it's not beeing refreshed in the rendered response.
On the other hand, if I try to set immediate attribute of the button to true, the actionListener is fired in the Apply Request Values phase, but still after the getter. Than the lifecycle goes directly to the Render Response phase, and the outcome is the same.
Anyone?
Thank you for the answer. Let me add a bit detail to my problem.
I store a model of a sports tournament as a property of a session scoped bean. It goes like this: the bean has a property "tournament". This class has a list of groups, each with it's table of matches. The idea was to use three different programmatically built components as renderers of this tournament model.
The dashboard would be used for drag-and-drop edition of contestant placement in groups. For viewing match tables and editing their matches I use a tab panel, with panel grid for every table. Finally, I use a panel grid to show a tournament tree. Every of those three components render some part of the model for the user to edit.
Since the model (and therefore those rendering components) are dynamically build depanding on chosable parameters like number of groups for example, i had a problem with id uniqnes when binding them to a session-scoped bean. So I bound them to a request scoped bean. With every request changing the model (mostly ajax) I wanted to rerender those components depending on the parameters set by the user (also stored in the session scoped bean).
The problem is, that when I rebuild the model in the invoke application phase (in a action listener fired by the "rebuild-my-model" button), the components bound to a request-scoped bean have already been "get-ed" from the bean (or so it seems), and they do not refresh on the page.
I would be very gratefull for a clue to what i'm doing wrong, and perhaps a suggestion, if the approach mentioned above is completelly stupid :)
The problem is, that the getter for the dashboard is fired in the Apply Request Values phase, way before the actionListener of the commandButton is fired
I'm not sure why exactly that forms a problem for you. Perhaps you're incorrectly doing business logic in the getter method instead of in the action listener method? Or perhaps you're manually creating the component instead of referencing the JSF-created one and thus always overridding the one in the JSF view?
A proper JSF getter method basically look like this:
public UIComponent getDashboard() {
return dashboard;
}
It should not contain any other line of code. The same applies to the setter method by the way. Any actions wherein you need to manipulate the component's children needs to be done in an action(listener) method, not in a getter/setter method.

Resources