JSF extending the UIInput does not invoke UPDATE_MODEL on the bean - jsf

I have created a custom components that extendeds UIInput and only overwrites the constructor and getFamily() as follows:
public HtmlInputDateTime() {
super();
setRendererType(RENDERER_TYPE);
}
#Override
public String getFamily() {
return COMP_FAMILY;
}
The I created the appropriate renderer that only overwrites getEndTextToRender. The problem is that although the local value is set and passed among requests (and the value is initially fetched from the model) it never updates the actual backing bean. Any hints why?
Thanks
Using JSF Mojarra 2.2

When creatinf custom components (or any forms in general) it is always a good idea to render h:messages to see if there were any validations that failed.
As it turns out component was working just fine but the since the value was a Date it failed the conversion. After I added <f:convertDateTime/>, it works fine.

Related

How to obtain submitted value from a custom JSF input component? [duplicate]

I have created a custom component. I add a dynamic input text box to it (from the encode function).
The component is correctly is rendered as HTML.
But I want to bind the value of the text box to some property on the Managed Bean. So some other developer can use the component on his jsp with his managed bean.
I want to know, what should I do, so that the value entered in the text box (which my component dynamically creates) is set to the some Managed bean property.
You need to ensure that your custom component class extends UIInput and that you're in the encodeEnd() method of your renderer writing the component's client ID as name attribute of the HTML input element. Then you can in the overriden decode() method of your renderer just grab the submitted value from the request parameter map with the component's client ID as parameter name and set it as UIInput#setSubmittedValue() and let JSF do the remnant of the job of converting, validating and updating the model value.
#Override
public void decode(FacesContext context, UIComponent component) {
// Do if necessary first validation on disabled="true" or readonly="true", if any.
// Then just get the submitted value by client ID as name.
String clientId = component.getClientId(context);
String submittedValue = context.getExternalContext().getRequestParameterMap().get(clientId);
((UIInput) component).setSubmittedValue(submittedValue);
}
Unrelated to the concrete problem, are you aware of the new composite component support in JSP's successor Facelets? I have the impression that you don't necessarily need a custom component for this purpose. Or are you really restricted to using the legacy JSP as view technology in spite of that you're already on JSF 2.x? See also When to use <ui:include>, tag files, composite components and/or custom components?
Well, the problem is solved.
In the encodeEnd() method I added the element as
HtmlInputHidden hidden = new HtmlInputHidden();
hidden.setParent(this);
hidden.setId("someId");
ValueExpression ve = getValueExpression("value");
hidden.setValueExpression("value", ve);
hidden.encodeBegin(context);
hidden.encodeEnd(context);
This seems to have some problem.
Then I changed this to ...
HtmlInputHidden hidden = new HtmlInputHidden();
hidden.setId("someId");
ValueExpression ve = getValueExpression("value");
hidden.setValueExpression("value", ve);
this.getChildren().add(hidden);
hidden.encodeBegin(context);
hidden.encodeEnd(context);
The use of this.getChildren().add(); solved my problem
P.S. Obviously before adding the element, it needs to be checked if the element is already present.

Get ManagedBeans in Custom JSF Validator dynamically

I want to validate values dynamically by using a custom validator that I can be used with several components. The custom validator gets those values from different ManagedBeans depending on its usage.
How to determine which ManagedBean the value is retrieved from? So I can get it, validate it, and put it back into a ManagedBean.
My Custom Validator:
#FacesValidator(value = "valid")
public class DateValidator implements Validator {
#Override
public void validate(FacesContext context, UIComponent component,
Object value) throws ValidatorException {
// Bean bean = ?
}
}
I dont think that is good approach as in validation phase model is still not updated, what you are getting is just input value from view. I wonder why you need bean instance there. If your validation depends on other component in view you can refer link # SO and Validator for multiple fields.
As you refer you need to validate it and put back, thats why validation phase is all about, validate it in your validator and if it fails it will not be passed to managed bean.
Have a look at this link for JSF lifecycle JSF Lifecycle
Hope this helps !!!

Commandlink action and #viewscoped weird behaviour

I have some code generated by netbeans wizard 'JSF pages from entity classes'.
For those who don't use netbeans I will briefly describe what the wizard does.
It creates a JSF page List.xhtml which contains a datatable with a fixed size of ten rows and two commandlinks for scrolling its content (prev 10 and next 10).
The JSF page uses a managedbean with session scope and the above mentioned commandlinks return the String 'List'.
If I change the managed bean scope to #viewscoped it is re-created every time I push a commandlink. According to me it is a weird behavior because the view actually doesn't change (it always List.xhtml ) and I would have expected a smarted view scope mechanism.
I then changed the action associated to the commandlinks with a new one which does the same things but returns void. Now the #viewscope mechanism works well but I'm not sure it is correct to use an action method with a signature like this
public void doSomething()
// instead of
public String doSomething()
My concern is that a different JSF implementation can act in an impredictable way with that kind of actions.
Thanks
Filippo
What do you return in public String doSomething()?
If you return null (or an empty String) it should not re-create the view.
If you return a navigation case then the view is re-created, regardless whether it is the same that you are currently in.

#postConstruct in JSF 1.1

How do I simulate the #postConstruct behaviour in JSF 1.1 like as in JSF 1.2 and newer?
Actually, I want to call a bean method automatically during page loading?
I am using IceFaces 1.8 on JSF 1.1.
The point of #PostConstruct is to provide a hook to execute some code after all managed properties (as in <managed-property> or #ManagedProperty) are been set and all dependency injections (e.g. #EJB, #Resource, #Inject and so on) have taken place.
If you don't have any of them, just use the bean's constructor.
public class Bean {
public Bean() {
// Just do your job here. Don't do it the hard way.
}
// ...
}
Or if you actually want to execute it when a specific property has been set, then do the job in the setter while null-checking the current property value.
public class Bean {
private SomeObject someManagedProperty;
public void setSomeManagedProperty(someManagedProperty) {
if (this.someManagedProperty == null && someManagedProperty != null) {
// First-time set, now you can do your job here.
}
this.someManagedProperty = someManagedProperty;
}
// ...
}
Update as per the comments:
I meant to execute the method every time the page is loaded
The #PostConstruct doesn't do that. However, if the bean is request scoped, then you will see the same effect. You seem to be using a session or application scoped managed bean to manage request scoped data. This is in essence wrong. You should convert it to a request scoped bean. Any real session scoped data can be split into a session scoped bean which you then inject by <managed-property>.

How can i send a parameter to be used in the #PostConstruct method of a backing bean?

I need to preload some data to be displayed when the page loads. The initialization steps are performed on a #PostConstruct-annotated method but now i need to use a parameter in order to get the data.
What i'm trying to do:
#PostConstruct
public void init()
{
List data = getDataFromDB(parameter) /*Need to read a parameter created somewhere else*/
}
Is there a way to achieve this?
Thanks in advance
It's kind of hard to say what you mean by "a parameter set somewhere else". I will assume that "somewhere else" means "sent from browser by HTTP". In such case you should create a standard property in your managed bean and:
in JSF 2.0 you could annotate it with #ManagedProperty("#{param.nameOfParameterToRead}")
in JSF 1.2 and less - use managed-property element in your bean description (faces-config.xml).
Like this:
#ManagedBean
#RequestScoped
class MyManagedBean {
#ManagedProperty("#{param.id}")
public Integer id;
#PostConstruct
public void init(){
data = getDataFromDB(id)
}
// setters and getters (mandatory, even though annotation is on an attribute!!!)
}
Careful: injecting properties does not use JSF converters, so it is best to inject strings and take care of conversion in your own code.
how about reading from Properties file, or fetching List from DB ??

Resources