Enum properties are not retrieved by OmniFaces in Spring / JSF projects - jsf

Given the following enum.
package util;
public enum IntegerConstants
{
DATA_TABLE_PAGE_LINKS(10);
private final int value;
private IntegerConstants(int con) {
this.value = con;
}
public int getValue() {
return value;
}
}
The constant given here should be retrieved on an XHTML page like as follows.
<ui:composition template="/WEB-INF/admin_template/Template.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:o="http://omnifaces.org/ui">
<ui:define name="title">Test</ui:define>
<ui:define name="content">
<h:form id="form" prependId="true">
<o:importConstants var="const" type="util.IntegerConstants"/>
DATA_TABLE_PAGE_LINKS : #{const.DATA_TABLE_PAGE_LINKS.value}
</h:form>
</ui:define>
</ui:composition>
This works in an enterprise application having JSF managed beans running on GlassFish 4.0.
This same thing, however does not work in a project that uses Spring (4.0 GA), JSF 2.2.6, PrimeFaces 5.0 final, PrimeFaces Extensions 2.0.0 final running on Tomcat 8.0.3.0.
This should not be related to Spring.
The enum given is available (its class file) in the WEB-INF/classes folder under the application's build folder.
It is difficult to find out the actual cause of the problem because no error or exception is thrown. The page on the browser is just left blank and there is nothing to see on the server terminal.
The OmniFaces version is 1.7.
Given it a try on OmniFaces 1.8-SNAPSHOT but the problem remained stationary.
Partial answer :
This worked, when I changed the value of the var attribute of <o:importConstants> from const to something different like as follows.
<o:importConstants var="literal" type="util.IntegerConstants"/>
DATA_TABLE_PAGE_LINKS : #{literal.DATA_TABLE_PAGE_LINKS.value}
Apparently, the value const appears to have been reserved somewhere but that's too difficult to believe because the same thing with the value const works fine in another application as mentioned above!

This is more related to EL than to JSF/Spring/OmniFaces. The Apache EL implementation as used by Tomcat is indeed quite restrictive as to reserved keywords. So is for example #{bean.class.name} (as in, print bean.getClass().getName()) possible in Oracle EL implementation as used by GlassFish, but not in Apache EL implementation as used by Tomcat. You should instead be writing it as #{bean['class'].name}. All other Java keywords listed in chapter 3.9 of Java Language specification which are not listed in chapter 1.17 of EL specification are also blocked by the Apache EL implementation. The const is indeed among them.
On a side note, it's recommended to start the constants var with an uppercase. This convention allows better distinguishing between managed bean instances and constant references in the EL scope. It also instantly solves your problem as Const is not the same as const.
<o:importConstants var="Const" type="util.IntegerConstants" />
DATA_TABLE_PAGE_LINKS : #{Const.DATA_TABLE_PAGE_LINKS.value}
Or just rename the enum, the var defaults namely to Class#getSimpleName().
<o:importConstants type="util.Const" />
DATA_TABLE_PAGE_LINKS : #{Const.DATA_TABLE_PAGE_LINKS.value}

Related

Why am I able to bind <f:actionListener> to an arbitrary method if it's not supported by JSF?

I'm using Glassfish 3.1.2.2 and JSF Mojarra 2.1.6.
I have the following Facelets page:
<h:form>
<h:commandLink value="link">
<f:actionListener binding="#{backingBean.someMethod(1)}"/>
</h:commandLink>
</h:form>
And the following backing-bean:
#RequestScoped
#ManagedBean
public class BackingBean {
public void someMethod(int i) {
System.out.println("It was called: " + i);
}
}
When I click the link, "Info: It was called: 1" appears in the console.
The documentation for binding reads:
Library: http://xmlns.jcp.org/jsf/core, http://java.sun.com/jsf/core (Jsf Core)
Tag: actionListener
binding
Value binding expression that evaluates to an object that implements javax.faces.event.ActionListener. [emphasis mine]
Also, the accepted answer to this question states that it's not possible for an f:actionListener to call an arbitrary method.
Why is the backing bean method called if this isn't supported?
This is the consequence of the new EL 2.2 feature of calling a method in a value expression via the #{bean.method()} syntax instead of only referencing a property via the #{bean.property} syntax (which should indeed be of the exact type ActionListener). It wouldn't have worked in EL 2.1 or older and it would also not work when you remove the arguments and the parentheses. That document was written when EL 2.2 didn't exist (it's actually not modified as compared to JSF 1.2 version from May 2006; EL 2.2 was introduced December 2009). I however do agree that it needs an update on that part as it's confusing to starters.
The answer you found made its points based on the document, but the answerer however didn't seem to realize based on the question that while binding="#{testController.nodeListener}" failed, the binding="#{testController.nodeListener(event)}" actually worked. This only doesn't give you the opportunity to pass the ActionEvent. The answer was better if it suggested to just use binding="#{testController.nodeListener()}" instead and grab the event information in other way, such as by calling UIComponent#getCurrentComponent() or even by passing #{component} as argument. Only if you really need to have a hand of it, of course.
<h:commandLink value="link">
<f:actionListener binding="#{bean.someMethod(component)}"/>
</h:commandLink>
public void someMethod(UIComponent component) {
System.out.println("It was called on: " + component); // HtmlCommandLink
}
See also:
Invoke direct methods or methods with arguments / variables / parameters in EL
Difference between JSP EL, JSF EL and Unified EL
Differences between action and actionListener

Referencing ui:params with hyphens in the name

After many years of avoiding JSF, I'm finally diving in but having problems doing the simplest of things. In the JSTL world, it's easy to reference things with hyphens in the name by doing ${requestScope['big-bad-invalid-name']}. However, that doesn't seem to work with a <ui:param> (or I'm simply starting with the wrong object--the likely issue).
I have a simple file that's referencing a template:
<html xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<ui:composition template="/WEB-INF/template/main.xhtml">
<ui:param name="require-data-main" value="/something" />
<ui:define name="content">...</ui:define>
</ui:composition>
</html>
Sadly I can't figure out how to reference my param since #{require-data-main} is going to freak out due to the hyphens. I've tried #{param['require-data-main']}, #{viewScope['require-data-main']}, #{pageScope['require-data-main']}, #{applicationScope['require-data-main']}. My param doesn't seem to exist anywhere.
Update #1 -- I created another param without hyphens (camel case). Nothing managed to resolve the value as I've tried above. A plain #{requireDataMain} did, however. I have a large number of JSPs already written. So I'm not too keen on changing my variable names. I'd still love to find out how to reference the param with the hyphens in the name.
Has anybody seen my param? Is there an alternate way to retrieve the param?
A JSF page should use Managed Bean to access your java code. If you have a controller class for your jsf page, you could inject it to jsf using EL: #{managedbean.field} where managedbean is a following class:
#ManagedBean(name = "managedbean")
public class YourBean {
private String field;
//getter and setter for field
}
Hope that I understood your problem correctly.

h:link with includeViewParams=true does not always include viewparams

For some reason,the does not always append the view parameters to the produced link. I can't figure out why. If I change the outcome to another similar link,then it is processed correctly.
Can anyone point me to some requirement that could not be fulfilled? I didn't find anything relevant in the docs.
I am trying to set up 4 views backed by a single bean. Those views all contains the same view parameters, but only one of them process them. All view use the same template.
So i have in all views
<f:metadata>
<f:viewParam name="param1"
value="#{bean.param1}"/>
<f:viewParam name="param2"
value="#{bean.param2}"/>
</f:metadata>
<ui:composition template="/onpage/template.xhtml">
// ...
And in one of them, i included a <f:viewAction>
In the template I have some links
<h:link outcome="#{bean.outcome1}"
value="Go to view1"/>
<h:link outcome="#{bean.outcome2}"
value="Go to view2"/>
and in the bean:
private String param1; // And get/setters
private String param2; // and get/setters
public String getOutcome1() {
return "/my/path.jsf?some=param&includeViewParams=true";
}
public String getOutcome2() {
return "/my/path2.jsf?some=param2&includeViewParams=true";
}
With this setup, some of the links point to "/my/path.jsf?param1=value1&param2=value2" as expected, while others point to "/my/path2.jsf?some=param2" for no apparent reason, and without any information in the log.
All this running on glassfish 4/JSF 2.2/primefaces 4.
THanks
Answer part of the OP comments:
What happened is that I mixed XML namespace domains. The pages using xmlns:f="java.sun.com/jsf/core were working correctly, while those using xmlns:f="xmlns.jcp.org/jsf/core were not. See The metadata component needs to be nested within a f:metadata tag. Suggestion: enclose the necessary components within <f:metadata> for more details.
Note: JSF 2.2 schemas use the xmlns:f="xmlns.jcp.org/jsf/core namespace.

How to integrate Hibernate Validator into Tomcat 7?

I've successfully integrated JSF (Mojarra) and CDI (Weld), but can't get Hibernate Validator to work.
The following jars are added to WEB-INF/lib:
validation-api-1.1.0.Final.jar
hibernate-validator-5.1.0.Final.jar
jboss-logging-3.1.3.GA.jar
classmate-1.0.0.jar
Tomcat 7 comes with EL 2.2 jars so I didn't add them.
My JSF page:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Test</title>
</h:head>
<h:body>
<h:form>
<h1><h:outputText id="hello" value="Hello, #{testController.name}!"/></h1>
<p:inputText id="name" value="#{testController.name}"/>
<h:message id="error" for="name"/>
<h:commandButton value="Change Name">
<f:ajax execute="name" render="hello error"/>
</h:commandButton>
</h:form>
</h:body>
</html>
And my backing bean:
#Named
#ApplicationScoped
public class TestController {
#NotNull
#Size(min = 3, max = 5)
private String name;
#PostConstruct
private void init() {
name = "Bill";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
It's expected that when the size of the name is smaller than 3 or bigger than 5, an error message is shown, but it turns out to be not. Seems the Hibernate Validator is not working . I did see it's detected but was no longer logged:
Mar 11, 2014 9:31:40 PM org.hibernate.validator.internal.util.Version <clinit>
INFO: HV000001: Hibernate Validator 5.1.0.Final
Is there anything wrong?
Update
Finally I figured out it's a Mojarra regression. The Hibernate Validator works now with MyFaces.
Just to avoid confusion (as I have been confused, looking for the error despite it had already been solved because I didn't see the update section at the end of the post), let me add the answer on behalf of the OP:
It seems the OP used a Mojarra version that was broken. They solved the problem by migrating to MyFaces (see the update to their question). FWIW, I tried their example using Mojarra 2.2.12, and it worked fine.
When you say you integrated with Tomcat 7, how did you do that? There is some glue code in application servers which make sure that for example the ValidatorFactory is visible to JSF. Not sure whether something like this would be required for you as well.
Have you enabled debug/trace logging to verify whether Validator bootstraps or get called?
Also you could try to add to the JSF page, but this should be optional.
Aren't you missing the <f:validateBean> tag on the page? I think you might also need to call the Validator.validate(bean) method in order to get it to fire.

PrimeFaces 3.5 parameter.DIR dynamically

Trying to make the new RTL Support in PrimeFaces 3.5 work dynamically, I appended the following in web.xml:
<context-param>
<param-name>primefaces.DIR</param-name>
<param-value>#{facesBean.direction}</param-value>
</context-param>
As you can see, the parameter value is an EL expression, evaluated from the bean property : direction:
private String direction = "ltr";
//......
public String getDirection() {
if (FacesContext.getCurrentInstance().getViewRoot().getLocale().getLanguage() == "ar") {
direction = "rtl";
} else {
direction = "ltr";
}
return direction;
}
However this does not work (I am too naive to believe it could work that simple way, since web.xml is not loaded the same way as xhtml files...)
If I tell explicitly for example ACCORDION to react to direction value, it does successfully (If locale language is changed to ar, dir receives rtl value, and if it is changed to fr or en, value received by dir attribute is ltr):
<p:accordionPanel dir="#{facesBean.direction}" id="accordion_services" dynamic="true" cache="true"
style="text-align: justify;" >
<p:tab title="#{i18n.seep}">
<h:panelGrid columns="2" cellpadding="10">
<!-- Remainder of code here ...... -->
I could apply that latter solution to every PrimeFaces component that has the DIR attribute, but that is anti-productive and would consume great amount of time.
The application scope DIR parameter is the ideal solution and it's claimed that it supports EL expressions. So I am interested in making it work.
Any clues?
Thanks.
JBoss AS 7.1
Mojarra 2.1
PrimeFaces 3.5
Latest Firefox/Chrome
Reference: Page 491 from PrimeFaces 3.5 user guide:
*Global Configuration
Using primefaces.DIR global setting to rtl instructs PrimeFaces RTL aware components such as datatable, accordion, tabview, dialog, tree to render in RTL mode.*
`<context-param>
<param-name>primefaces.DIR</param-name>
<param-value>rtl</param-value>
</context-param>`
Parameter value can also be an EL expression for dynamic values. In upcoming PrimeFaces releases, more components will receive built-in RTL support. Until then if the component you use doesn’t provide it, overriding css and javascript in your application would be the solution.
491
RTL currently does NOT support EL in web.xml (I am using PF 3.5)
I have created a feature request for PF team
I have posted this question again in PF forum and I got an answer here
See also:
using JSF EL expression inside web.xml
UPDATE
its fixed and will be available in the upcoming Primefaces 4.1

Resources