Bind h:selectBooleanCheckbox value to int/Integer instead of boolean/Boolean - jsf

I have a <h:selectBooleanCheckbox value="#{someBean.prop}"> where prop is a property of type int. Is it really not working straight away? Do I have to implement a custom converter to convert Boolean to int? Does anyone happen to have converter code for that at stock? I read that there is some bug in JSF 2.0 that prevents converters for <h:selectBooleanCheckbox> to be processed. Can anyone confirm that?
I use MyFaces 2, Tomahawk and Tomcat 6.

The <h:selectBooleanCheckbox> should, as its name say, be bound to a boolean or Boolean property. Nothing else. That it allows a converter attribute is actually a bug in the spec. It should never have allowed it.
The problem is more in your model, why would you use an int to represent a boolean state? Change your model to let it be a fullworthy boolean.
If changing the model isn't an option for some reason (a 3rd party API, a stupid architect, or stupid business restrictions, etc), then wrap the model getter/setter in the backing bean like follows
public boolean isChecked() {
return someModel.getSomeInt() != 0;
}
public void setChecked(boolean checked) {
someModel.setSomeInt(checked ? 1 : 0);
}
and use it instead as <h:selectBooleanCheckbox value="#{bean.checked}" />.

just to say MySQL doesn't have boolean as field type choice, and it could be an example for this need.

You can set field as tinyint in MySQL. Actually problem is getting method name when you create a boolean variable. Use method name getChecked() instead of isChecked().

Related

How to make a JSF custom component to store a custom type as its value?

Seems basic enough...
I have a custom JSF component and its associated renderer. The renderer does the decode and encodeEnd.
In decode i successfully retrie the submitted value via component.setSubmittedValue(ctx.getExternalContext().getRequestParameterMap().get(c.getClientId()));
In encodeEnd, i basically create the markup and if component.getValue() is not null, i insert its contents in the markup. So far so good.
Problem is that getValue() can be only be String. I have custom class that represents a compound data type and i want to use that as the component's local value. But doesn't work - JSF converts to String.
I also tried using component.getAttributes() - from the decode method, where i put my custom object in keyed to private static final String someKey = "asd". But later at encodeEnd there is no value/key in the map.
I want the users of this component to be able to specify in their backing bean the custom data type and not worry about serialization/deserialization to text representation between client/server. Presumably i have to use a converter for that? But how can i set up a default and immutable converter for the custom component?
The problem has a simple enough of a solution. Inside the Renderer class (or right into the Component class if using that directly):
#Override
public Object getConvertedValue(FacesContext context, UIComponent component, Object submittedValue) throws ConverterException {
SomeCustomObject thing;
//... do magic to create SomeCustomObject based on submittedValue
return thing;
}
Now whenever getValue() is called on that component, SomeCustomObject will be returned and you can safely cast to it. Also in the backing beans can use SomeCustomObject as the type.
Also note when calling component.getValue() in the actual Renderer, it will return SomeCustomObject as well, so if you're restoring state, you must convert back to its String representation.
For more details see and #Kukeltje's answer above and check how the same thing is done for primefaces calendar component here: https://github.com/primefaces/primefaces/blob/master/src/main/java/org/primefaces/component/calendar/BaseCalendarRenderer.java
For another more concise and clear illustration, check #BalusC's answer as well.

When to name a converter in JSF

I've been working with converters in my PrimeFaces SelectOneMenu objects. They work fine if I only tell which class the converter is referring to:
#FacesConverter(forClass = DescriptorVO.class)
public class DescriptorVOConverter implements Converter { ... }
This way, I don't have to explicitly tell the JSF component which converter should be used when it is populated with objects of class DescriptorVO.
However, I made a page that used a p:SelectManyCheckbox and I couldn't for the life of me know why it wasn't calling my converter. Then I gave it a name, like so:
#FacesConverter(forClass = RoleVO.class, value = "roleVOConverter")
public class RoleVOConverter implements Converter { ... }
and passed it as one of the component's properties
<p:selectManyCheckbox id="cbx_roles" required="true" converter="roleVOConverter"
requiredMessage="At least one role must be selected."
value="#{userView.selectedRoles}" layout="responsive">
<f:selectItems value="#{userView.roles}" var="role"
itemLabel="#{role.title}" itemValue="#{role}" />
</p:selectManyCheckbox>
and voi la, it started calling the converter correctly. This raised a question to me regarding when I should name my converters (through the value attribute) and when telling them which class the converter should be used with (with the forClass attribute) is enough. I never had to namy any converters when working with PrimeFaces, only for this particular SelectManyCheckbox component. Do different components have different necessities regarding converters or did I just get the concept of converters wrong?
That can happen when the value of the UISelectMany component references a generic java.util.Collection type like List<Role> instead of an array like Role[]. This is specified in javadoc of UISelectMany (emphasis mine):
Obtain the Converter using the following algorithm:
If the component has an attached Converter, use it.
If not, look for a ValueExpression for value (if any). The ValueExpression must point to something that is:
An array of primitives (such as int[]). Look up the registered by-class Converter for this primitive type.
An array of objects (such as Integer[] or String[]). Look up the registered by-class Converter for the underlying element type.
A java.util.Collection. Do not convert the values.
If for any reason a Converter cannot be found, assume the type to be a String array.
The reason is, the generic type <Role> is lost during runtime and not directly determinable. It works when you're using MyFaces instead of Mojarra as it will in case of a java.util.Collection inspect the actual type by manually iterating over <f:selectItem(s)> and determine the Converter based on first non-null value.
I created spec issue 1422 on this to get this in JSF spec and improve Mojarra too.
See also:
UISelectMany on a List<T> causes java.lang.ClassCastException: java.lang.String cannot be cast to T
Why does JSF put String values in a Map<..., Integer>? And how to work around it?
Use enum in h:selectManyCheckbox

Is it considered idiomatic to always prefer properties over backing fields?

I recently converted an Android project from Java to Kotlin using Android Studio's Kotlin plugin. Post-conversion, many fields in my classes were highlighted, and hovering over them displays the message
This property has a backing field
Should I infer from the existence of this message/warning that it is always considered more idiomatic (in Kotlin) to use properties with explicitly-defined getters and/or setters? Or is the IDE being a little over-zealous with the informational messages? Answers that include references to official sources preferred :)
Idiomatic is to use properties without backing properties. Backing properties are an exception case, as are custom getters and setters. You do need to be aware of the difference between a "Backing Field" and "Backing Property":
In the Kotlin docs, it talks about Backing Fields which are something you sometimes access from custom getters/setters and exist for any given property. There is an implied name for backing fields of field, so in a setter you would access this backing field by that name:
var counter = 0 // the initializer value is written directly to the backing field
set(value) {
if (value >= 0)
field = value
}
A Backing Property on the other hand is something that you define to store the value in another private property and of which you have complete control over. By convention it would be private and be prefixed with an underscore _. This looks like:
private var _table: Map<String, Int>? = null
public val table: Map<String, Int>
get() {
if (_table == null)
_table = HashMap() // Type parameters are inferred
return _table ?: throw AssertionError("Set to null by another thread")
}
Nothing to worry about, it's a known issue with the IDE. The highlighting is there simply for your information, cause backing fields require some extra care in certain cases.
If it troubles you, just turn the inspection off. Or change the highlighting to be not so bright.

JSF, EL, Managed Beans - How to tell what the getter & setter signatures are?

With JSF, Managed Beans, & EL 2.2 I know generally that an expression of the form:
#{bean.value}
Will map to a corresponding set of functions in a managed bean class like so:
#ManagedBean
class Bean {
private String value;
public String getValue() { return value; }
public void setValue( String s ) { value = s; }
}
It is also possible to get and set properties of a map:
#{bean.value['key']}
Backed by something like:
#ManagedBean
class Bean {
private Map<String, Boolean> kvMap;
public boolean getValue( String key ) { return kvMap.get( key ); }
public void setValue( String key, boolean value ) { kvMap.put( key, value ); }
}
So far so good.
I'm finding as I spend more time with JSF however that I'm trying to write reusable chunks of code. Specifically, small blocks of xhtml in <ui:composition> blocks that I can include via <ui:include>. What's more, many of the more useful things for me are things like nested sets of checkboxes (our UI designer is just gaga over them ;-), and there <ui:repeat> becomes very handy.
Invariably, in order to use <ui:repeat> and <ui:include> without an ungodly amount of typing, I've been using aliases, either created via <ui:param> or inline with something like the var attribute of <ui:repeat>.
As I've been writing more and more nested UIComponents, particularly things that get their values from maps within maps, I'm finding it harder and harder to deduce the correct setter method signature that JSF will look for when submitting a form (for some reason writing getters seems to be more natural).
My question for you gurus then is:
Is there some way to get JSF to tell me what it expects a setter signature to look like? Since JSF generally doesn't complain about an expression that resolves to a getter-only (thinking it is a read-only property), I find the lack of feedback frustrating and it seems to require a lot of fiddling with different method signatures before I finally hit that magic right one.
I'm hoping there's some technique, say a FacesContext... query at runtime or looking in some compiled intermediate like a class file that would point me to the correct setter signature for a deeply nested property. If there is such a thing I think it would save me a lot of time trying to figure out how to get a setter constructed by trial and error.
Hopefully I've articulated clearly enough what I'm after, thanks in advance for your replies.
I understand that your question basically boils down to "How should a setter for a Map look like?".
The answer is simple: you don't need any one. EL uses the put() method on the Map itself. You only need to provide a getter for the whole Map. On getting map values, EL will use the get() method of the Map itself. This is all behind the scenes done by the builtin MapELResolver.
So this should do:
#ManagedBean
class Bean {
private Map<String, Boolean> kvMap;
public Map<String, Boolean> getValue() { return kvMap; }
}
which is to be used as #{bean.value['key']} or #{bean.value.key} if the key doesn't contain periods. You can just use it in input components as well.
<h:selectBooleanCheckbox value="#{bean.value.key}" />
As to the tooling, well, the JBoss Tools plugin for Eclipse has good EL autocomplete support for normal javabeans, but it can't autocomplete map keys. Further Eclipse has its own facilities to autogenerate bean properties along with getters and setters based on a list or existing properties.

What is the correct way to bind input value to JSF managed bean property?

I am new to JSF and managed beans. I have a managed bean with some private property with public setter and Getter methods. Now when I add the managed bean's properties to JSF forms, should I add the private methods directly or should I use call the property by Getter methods?
For example:
<h:inputText value="#{BeanName.userName}"/>
<h:inputText value="#{BeanName.getUserName()}"/>
Which one is correct in above?
Assuming that you're using JBoss EL or EL 2.2+, both ways would work fine in the initial display. But the first one is actually more correct because the second one would only get the value, but never set the value. If you want to collect input values, you should always go for the first way. The EL (Expression Language) will then automatically locate the getUserName() and setUserName() methods whenever needed.
The second way will never work when you're using standard JSF EL implementation since it doesn't support direct method calls.
To learn more about JSF, start at our JSF wiki page.
If in your java class you have something like
....
private String coolStuff;
public String getCoolStuff() {
return coolStuff;
}
....
Then in your jsf page you access it like so:
#{myBackingBean.coolStuff}
The framework automatically looks for a method called getCoolStuff()
Hope that helps
number 1 is correct from above it is the private field that you connect if you are using EL with JSF in your form.
You still need the getter and the setter which the managed bean calls to get the values so you can save them in a database ....etc

Resources