Why is #FacesConverter(forClass=String.class) not working - jsf-2

I followed the example here: Why does <h:inputText required="true"> allow blank spaces? to create a "Global" converter to trim all input fields. However, the converter is not being invoked when input fields are submitted.
#FacesConverter(forClass=String.class)
...
<p:inputText value="#{controller.inputValue}"/>
but when I change to:
#FacesConverter("StringTrimmer")
...
<p:inputText value="#{controller.inputValue}" converter="StringTrimmer"/>
it works.
Using Mojarra 2.1.7 and PrimeFaces 3.2

A converter with a forClass will only be invoked whenever the type of the property is an instance of the specified class. In your particular case, that can only mean that the #{controller.inputValue} is not of type String.

If you checked that the bound variable is of type String and the converter still doesn't get called, you may also check the following:
If the input component is encapsulated inside a composite component, you may have this issue. In that case, converters would not be called correctly, resulting in your custom method to be never reached. Calling the converter explicitly on the input component solves this.
If you add both value="someName" and forClass="someClass" to the #FacesConverter annotation, the forClass attribute will be ignored. This has been reported here.

This didnt work because the inputValue was not actually of type String. Once changed to type String-- it worked.

Related

JSF and EL, I don't understand this code (an array?)

I was reading some code and I found the next EL expression inside a JSF file:
${text['somefield']}
How is it work?.
Since I don't have access to the whole code, I can check what it is. Is it "text" a managed bean?.
Because I could understand the next code:
${someBean.text['somefield']}
(accessing a field array inside a bean but it's not the case.
text can be a managed bean, a CDI dependency (these are the 2 most likely)
text['somefield'] is reading somefield field of text object. text is likely to be a map, but it could be a normal bean too. It's equivalent to text.somefield
In the documentation, you can also find similar exampes:
${customer.address["street"]}
Which is similar to:
${customer.address.street}

Data type converter not working with embedded object in Struts 2

I'm creating a data type converter within Struts 2 framework and got the problem below:
in the action conversion property file, I need to specify a property like this:
foo.field1.field2 = coverterClassName
field1 is embedded object within foo, which has field2 as one of the fields.
I have tried everything and couldn't make this working unless I put the property file
into same package as class Foo, which hooks up the struts2 with model class.
Has anyone had this problem before and is there any other solution for it?
Because you are doing a class wide conversion, your conversion property file should be
in the same location of the classpath as the target bean.
if your target bean is an action bean, then it should be in the same package as the action class. More about it Applying a Type Converter to a bean or model.
You might also see this answer for how to apply application wide conversion to your field type. Note, you can do the same type conversion using annotations.

Why can JSF resource bundle var be used differently with f:loadBundle and faces-config

I have one property file linked both ways (using f:loadBundle and faces-config.xml) both with different var names. So it would look like the following:
datatypes.properties:
A=first
B=second
C=third
faces-config.xml:
<resource-bundle>
<base-name>datatypes</base-name>
<var>myProp</var>
</resource-bundle>
myPage.xhtml:
<f:loadBundle basename="datatypes" var="prop"/>
in myPage.xhtml I make a list of all the keys from the property file. What I can't seem to understand is that when I use #{prop} in the code below it works but when I replace it with #{myProp} the list no longer displays.
<h:form>
<h:selectManyListbox id="list">
<f:selectItems value="#{myProp}"></f:selectItems>
</h:selectManyListbox>
</h:form>
I figure this means the variables in both cases are not the same behind the scenes but I would appreciate it if someone could explain (or point me to an explaination) in what way they are different. I would ideally like to just use #{myProp} without having to pull the keys out in code and store them in a list.
Thanks.
Both <f:loadBundle> and <resource-bundle> are different ways to load properties with difference being in their access scopes. The latter has by the way the additional benefit that the bundle is also injectable in a managed bean by #ManagedProperty("#{myProp}")
Using <resource-bundle> in faces-config.xml creates a global resource bundle which can be accessed anywhere in your application. This is implemented through a java.util.ResourceBundle instance.
Using <f:loadBundle> in your view creates a view-specific resource bundle which is accessible only within that view. The tag handler implements this using an internal implementation of a Map. This is as specified in the VDL of the tag:
Load a resource bundle localized for the Locale of the current view,
and expose it as a java.util.Map in the request attributes of the
current request under the key specified by the value of the "var"
attribute of this tag.
Now since you're trying to use the values from datatypes.properties through <f:selectItems>, you'll get the said exception. This is because the value attribute for the tag should evaluate to a Collection or an array.
Value expression pointing at any Collection or array. The member
elements may be instances of SelectItem or any Java Object.
So in order to use the global bundle instance, you first have to convert the same into a List<SelectItem> inside your backing bean before using it.
NOTE: You can verify the above cases by setting a breakpoint in the initializeItems(Object) method in the com.sun.faces.renderkit.SelectItemsIterator class. This is, of course, assuming that you're using the Mojarra implementation.

JSF component binding without bean property

How does exactly the following code work:
#{aaa.id}
<h:inputText id="txt1" binding="#{aaa}"/>
I mean, usually the component binding works, by specifying a property (of type UIComponent) in a bean. Here, there's no bean nor property but nevertheless the name "aaa" gets bound correctly (displaying the component id - "txt1"). How does it work/where is it specified?
Thanks
UPDATE: The JSF2.0 Spec [pdf] (Chapter 3.1.5) says:
"A component binding is a special value expression that can be used to facilitate “wiring up” a component instance to a
corresponding property of a JavaBean... The specified ValueExpression must point to a read-write JavaBeans property of type UIComponent (or
appropriate subclass)."
It's been put in the default EL scope during building of the view tree (that's when all binding attributes -- and attributes of tag handlers like JSTL <c:xxx> and JSF <f:xxx> -- are being evaluated). It's being shown by normal EL means during rendering of the view tree. Rendering of the view tree happens after building of the view tree, so it works that way. It's not that this code runs "line by line" as you seemed to expect from the source.
I can't point you out a single reference where it's been specified as there is none. You'd have to read both the EL spec and JSF spec separately and do a 1+1=2.
By the way, to avoid confusion among new developers and to avoid clashes with existing variables in the EL scopes, you can use a java.util.HashMap in the request scope which is been declared as follows in faces-config.xml:
<managed-bean>
<description>Holder of all component bindings.</description>
<managed-bean-name>components</managed-bean-name>
<managed-bean-class>java.util.HashMap</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
and is been used as follows
#{components.aaa.id}
<h:inputText id="txt1" binding="#{components.aaa}"/>
which is more self-documenting.
See also:
How does the 'binding' attribute work in JSF? When and how should it be used?

OGNL exceptions setting Struts2 checkbox value

After adding a s:checkbox to my form, I get OGNL errors in the ParamsInterceptor:
WARN [OgnlValueStack] Error setting expression '__checkbox_filter.findRejected' with value '[Ljava.lang.String;#dc926f'
ognl.OgnlException: target is null for setProperty(null, "findRejected", [Ljava.lang.String;#dc926f)
I am aware that the extra hidden field with underscores in its name (__checkbox_filter.findRejected) was correctly added by Struts2.
I don't understand, however, why the ParametersInterceptor is trying to set this property, that was added by Struts2, on my Action (which obviously doesn't contain a '__checkbox_filter' property).
It is normal to see this OGNL error coming from with Struts2 checkboxes? How can I avoid it?
I've just stumble across the very same problem.
You need to place the Checkbox Interceptor BEFORE the Parameters Interceptor in your interceptor stack.
This is the case by default, so I guess that you're using a custom stack...
Most of the time the mistake in such cases is that we forget to write getters and setters for the attributes. So check whether the getters and setters are at their place.

Resources