How to integrate Hibernate Validator into Tomcat 7? - jsf

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.

Related

JSF button action triggered twice

I already asked this question in the WildFly forum but did not get any answers so far. So I´m trying here.
Since I upgraded from WildFly 8.1 to 8.2 I have problems with a commandButton inside a tabView connected to a bean.
Here is a simple JSF page:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<h:body>
<h:form>
<p:tabView binding="#{testBean.tabView}">
<p:tab title="Tab">
<p:commandButton value="Inside" action="#{testBean.testInside}"/>
</p:tab>
</p:tabView>
<p:commandButton value="Outside" action="#{testBean.testOutside}"/>
</h:form>
</h:body>
</html>
and the bean:
#Named
#SessionScoped
public class TestBean implements Serializable {
private TabView tabView = new TabView();
public TabView getTabView() {
return tabView;
}
public void setTabView(TabView tabView) {
this.tabView = tabView;
}
public void testInside() {
System.out.println("inside");
}
public void testOutside() {
System.out.println("outside");
}
}
Clicking the "Inside" button triggers testInside() two times. The "Outside" button (outside of the tabView) behaves normally and triggers it´s method only once. Removing the tabView binding eliminates the problem. I´m using PrimeFaces 4.0.
Thanks for any ideas
Jan
It's a Mojarra 'issue', introduced by a performance optimization fix in 2.2.7.
this is a Mojarra "issue", I've discovered it when working on RF-13920, it was introduced by JAVASERVERFACES-3193. The components that use binding are not recreated during a request to the server but their children are. With the original children still in place inserting the new children causes the "duplicate id" error.
So it looks like your button is added twice, but since you do not have an explicit id assigned, you do not get the duplicate id error... Might be interesting to give that a try (adding an explicit id)
The JSF specification states that binding should only be used in Request scope, so I don't think it should be treated as a bug if this fails in Conversation scope.
The last remark is the interesting one. As is posted in the next post on the jboss site:
But now I think I have a satisfying solution for this issue and I can confirm, that with request-scoped backing beans for the component binding the exception and duplicate id problem does not occur anymore, even with Mojarra 2.2.8 from Wildfly-8.2.0.Final!
This is even true if the rest of the logic for the page remains in a (say) conversation scoped bean. You just need to have a request-scoped bean for the binding attribute, which then can be referenced in EL and other beans.
Check also this post
You can try doing in other way. Use remoteCommand out of the tab with the same action of the commandButton.
Then use the JavaScript function created by the remoteCommand in the onclick event of the commandButton.
Here is the example using your code.
It's functional.
<h:form>
<p:remoteCommand id="myfun" name="myfun" action="#{testBean.testInside}" />
<p:tabView binding="#{testBean.tabView}">
<p:tab title="Tab">
<p:commandButton value="Inside" onclick="myfun();"/>
</p:tab>
</p:tabView>
</h:form>

How to form #Named Backing Bean in JSF

I read somewhere that it's better to use CDI #Named instead of JSF #ManagedBean, because of CDI, so I'm trying to convert some of my code.
I'm trying to use #Named in JSF, but it's always unreachable.
When using #ManagedBean there was no problem.
I'm using it like #ManagedBean, as below
CustomerBacking.java
package com.wordpress.marczykm.backing;
import javax.ejb.EJB;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
#Named("customer")
#RequestScoped
public class CustomerBacking {
#EJB
private CustomerService customerService;
public CustomerBacking() {
}
public String addCustomer(Customer customer) {
customerService.addCustomer(customer);
return "customer_overview";
}
public Customer getCustomer(){
return customerService.getCustomer();
}
}
index.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>EJB 3.0 Test</title>
</h:head>
<h:body>
<h:outputText value="#{customer.firstname}"/>
<h:form>
<h:outputText value="Imię"/>
<h:inputText id="firstname" name="firstname" value="#{customer.firstname}" /><br/>
<h:outputText value="Nazwisko"/>
<h:inputText id="lastname" name="lastname" value="#{customer.lastname}" /><br/>
<h:commandButton value="Dodaj" actionListener="#{customer.addCustomer}"/>
</h:form>
</h:body>
</html>
To sum up, looking at Netbeans sample CDI app, the bean which needs to be accesible by JSF page needs to:
have #Named annotation (javax.inject.Named)
have scope annotation (like #SessionScoped, #RequestScoped, #ViewScoped), but imported from javax.enterprise.context.*
doesn't have to have empty, non-argument constructor
and the thing that wasn't in my code is that, that the bean needs to implement Serializable (java.io.Serializable)
last thing is that if your app is a web application it needs a beans.xml (can be completly empty) in WEB-INF directory, if it is a bean app it have to be in META-INF directory
You don't mention which servlet container/application server and which CDI implementation version you're using.
I have no clue what Spring Tool Suite assumes as default, presumably it's Tomcat, Spring and no CDI at all, so you have to add and configure a CDI implementation (e.g. Weld or OpenWebBeans).
For CDI 1.0, you'll have to add a WEB-INF/beans.xml descriptor (which may be empty) to have your beans discovered. This is no longer necesary for CDI 1.1.

Why <f:validateBean /> won't work?

I use JSF 2.0, hibernate-validator4.2.jar validation-api.jar tomcat and Eclipse.
I put #Size(min=3, message="xxx") annotation in a #ManagedBean and <f:validateBean /> between <h:inputText value="#{user.name}"></h:inputText>
When I try to run the project i get this error...
exception
javax.servlet.ServletException: Expression Error: Named Object: javax.faces.Bean not found.
javax.faces.webapp.FacesServlet.service(FacesServlet.java:606)
root cause
javax.faces.FacesException: Expression Error: Named Object: javax.faces.Bean not found.
com.sun.faces.application.ApplicationImpl.createValidator(ApplicationImpl.java:1593)
com.sun.faces.facelets.tag.jsf.ValidatorTagHandlerDelegateImpl.createValidator(ValidatorTagHandlerDelegateImpl.java:244)
com.sun.faces.facelets.tag.jsf.ValidatorTagHandlerDelegateImpl.applyAttachedObject(ValidatorTagHandlerDelegateImpl.java:132)
com.sun.faces.facelets.tag.jsf.ValidatorTagHandlerDelegateImpl.applyNested(ValidatorTagHandlerDelegateImpl.java:211)
com.sun.faces.facelets.tag.jsf.ValidatorTagHandlerDelegateImpl.apply(ValidatorTagHandlerDelegateImpl.java:87)
javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120)
javax.faces.view.facelets.DelegatingMetaTagHandler.applyNextHandler(DelegatingMetaTagHandler.java:137)
why? (this only appears when i put tag)
User.java
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.validation.constraints.Size;
#ManagedBean(name="user")
#SessionScoped
public class User{
#Size(min=3, message="At least 3 characters!")
private String name;
public String getName() {
return nume;
}
public void setName(String name){
this.name=name;
}
}
adduser.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<ui:composition template="/templates/master_layout.xhtml">
<ui:define name="text_header" >Panou de control: Adauga user </ui:define>
<ui:define name="content">
<h:panelGrid columns="3">
<h:outputText value="Name"></h:outputText>
<h:inputText value="#{user.name}">
<f:validateBean />
</h:inputText>
<h:commandButton value="Inregistreaza" action="index.xhtml"></h:commandButton>
</h:panelGrid>
</ui:define>
</ui:composition>
</html>
It should work perfectly fine, although the empty <f:validateBean/> tag is entirely superfluous in this context. It's supposed to be used to "finetune" validation more, such as grouping of validation and/or disabling the implicit bean validation on a per-input basis by specifying the desired tag attributes. You have however no attributes on that tag, so just remove that tag altogether. On a default JSF 2 + JSR 303 project setup, it's supposed to kick in fully transparently without adding more JSF tags whenever there's a JSR 303 annotation on the property such as #Size and likes.
But I don't think that removing the tag will solve this particular exception. Your problem lies thus deeper. This validator is supposed to be auto-registered on startup. However, the exception basically tells that the validator is not registered at all. With the information given so far, it's not possible to give a targeted answer. I can think of the following possible causes:
There's a bug in the JSF implementation which you're using. Upgrade it to a newer version.
You have multiple JSF libraries of different versions in your classpath. Cleanup it.
The faces-config.xml root declaration is not declared conform JSF 2.x. Fix it.

JSF Backing Bean constructor called multiple times

I'm trying out JSF 2.0 (after using ICEfaces 1.8 for the past few months) and I'm trying to figure out why in JSF 2.0 my backing bean constructor gets called multiple times.
The bean is supposed to be instantiated once upon creation, but the "Bean Initialized" text shows up whenever I click the commandButton, indicating a new Bean object being instansiated.
The facelet page:
<?xml version='1.0' encoding='UTF-8' ?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:body>
<div id="content">
<h:form id="form">
<h:commandButton value="Toggle" action="#{bean.toggleShowMe}"/>
</h:form>
<h:panelGrid rendered="#{bean.showMe}">
<h:outputText value="Show me!"/>
</h:panelGrid>
</div>
</h:body>
</html>
The backing bean:
#ManagedBean
#RequestScoped
public class Bean {
private boolean showMe = false;
public boolean isShowMe() {
return showMe;
}
public void setShowMe(boolean showMe) {
this.showMe = showMe;
}
public void toggleShowMe(){
System.out.println(showMe);
if(showMe==true){
showMe=false;
}else{
showMe=true;
}
}
/** Creates a new instance of Bean */
public Bean() {
System.out.println("Bean Initialized");
}
}
Thats all it is. Just a simple test. The same behaviour shows itself if I use ICEfaces 2.0 and in place of the panelGrid I use:
<ice:panelPopup visible="#{bean.showMe}">
I'd appreciate any help here. I'm at a loss to explain it.
Update: In response to Aba Dov, I #SessionScoped the bean, figuring it wouldn't be calling the constructor upon each request and ran into the same behavior. What am I missing?
You have declared the bean to be placed in the request scope and you're firing a new HTTP request everytime by the command button. Truly the bean will be created on every request.
If you want that the bean lives as long as the view itself (like as IceFaces is doing under the covers for all that ajax stuff), then you need to declare the bean view scoped (this is new in JSF 2.0).
#ManagedBean
#ViewScoped
public class Bean implements Serializable {}
In my case the problem was I imported "javax.faces.bean.ViewScoped" instead of importing "javax.faces.view.ViewScoped".
Hope it could help someone.
The bean is called every time there is a request from the page.
when you click the <h:commandButton> the form is submitted and a request is sent to the server
in order to prevent it you can use <t:saveState> or <a4j:keepAlive> tags for your been.
for example <a4j:keepAlive beanName="YourBean" />
those tags stores the bean instance in the component tree .
also make sure that your class implements Serializable. so it can be serialized
Hope this helps
The bean should be in the ViewScoped.

Why does #PostConstruct callback fire every time even though bean is #ViewScoped? JSF

I am using datatable on page and using binding attribute to bind it to my backing bean. This is my code :-
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.prime.com.tr/ui">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form prependId="false">
<h:dataTable var="item" value="#{testBean.stringCollection}" binding="#{testBean.dataTable}">
<h:column>
<h:outputText value="#{item}"/>
</h:column>
<h:column>
<h:commandButton value="Click" actionListener="#{testBean.action}"/>
</h:column>
</h:dataTable>
</h:form>
</h:body>
</html>
This is my bean :-
package managedBeans;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.component.html.HtmlDataTable;
#ManagedBean(name="testBean")
#ViewScoped
public class testBean implements Serializable {
private List<String> stringCollection;
public List<String> getStringCollection() {
return stringCollection;
}
public void setStringCollection(List<String> stringCollection) {
this.stringCollection = stringCollection;
}
private HtmlDataTable dataTable;
public HtmlDataTable getDataTable() {
return dataTable;
}
public void setDataTable(HtmlDataTable dataTable) {
this.dataTable = dataTable;
}
#PostConstruct
public void init(){
System.out.println("Post Construct fired!!");
stringCollection = new ArrayList<String>();
stringCollection.add("a");
stringCollection.add("b");
stringCollection.add("c");
}
public void action(){
System.out.println("Clicked!!");
}
}
Please tell me why is the #PostConstruct firing each and every time i click on button? It should fire only once as long as i am on same page beacause my bean is #ViewScoped. Further, if i remove the binding attribute then everything works fine and #PostConstruct callback fires only once. Then why every time when i use binding attribute? I need binding attribute and want to perform initialisation tasks like fetching data from webservice, etc only once. What should i do? Where should i write my initialisation task?
Interesting, when you're using component binding on a view scoped bean, the view scope breaks.
I am not sure if that is a bug in JSF2, I would have to read the entire JSF2 specification first. As far now your best bet is to drop the component binding for now and pass the selected item via new EL 2.2 method argument syntax:
<h:dataTable var="item" value="#{testBean.stringCollection}">
<h:column>
<h:outputText value="#{item}"/>
</h:column>
<h:column>
<h:commandButton value="Click" action="#{testBean.action(item)}"/>
</h:column>
</h:dataTable>
See also:
How can I pass selected row to commandLink inside dataTable?
Invoke direct methods or methods with arguments / variables / parameters in EL
Benefits and pitfalls of #ViewScoped
Update (Dec 2012): this is indeed a bug in JSF2. It's a chicken-egg issue. The view scoped beans are stored in the JSF view state. So the view scoped beans are only available after restore view phase. However, the binding attribute runs during restore view phase, while the view scoped beans are not available yet. This causes creation of a brand new view scoped bean instance, which is then later replaced by the real view scoped bean which was stored in the restored JSF view state.
This is reported as JSF issue 1492 and JSF spec isssue 787 which will be fixed for JSF 2.2. Until then, your best bet is to use binding on request scoped beans exclusively, or to look for alternate ways for the particular functional requirement.
Update (Mar 2015): The JSF 2.2 fix was backported to Mojarra 2.1.18. So if you're still using JSF 2.0/2.1, you'd best upgrade to at least that version. See also a.o. What is component binding in JSF? When it is preferred to be used? and JSTL in JSF2 Facelets... makes sense?
As other said, I would say that the best thing to do is to drop component binding (you don't need it here).
But I would add that you can achieve the same as you're trying to do in a more object-oriented fashion by using action parameters, like this:
<h:commandButton value="Click" action="#{testBean.action(item)}"/>
... and in your java code:
public void action(Item item){
System.out.println("Clicked!!" + item);
}
If you have a viewscoped bean and if you want to retain values that were entered on the form or don't want postconstruct fired, you should return null from your action method.
If you return some outcome (e.g. invalid) and then point the invalid outcome to the same page using faces-config.xml, then the viewscoped bean gets recreated and thus it causes postconstruct to fire again.
Other solution:
Binding the HtmlDataTable in a request scope bean.
Inject this request scope bean in the view scope bean.
JBoss Seam use this solution for binding JSF componentes to a conversation scope component.
The balusc's answer helped me a lot, i would like to say that i had that bug with mojarra version 2.1.7, i am currently using 2.1.29-01 released in january-2015 and this bug is fixed, my problem was binding a tabview to a viewscoped bean. With this version I dont have that bug and binding and postconstruct is working fine.
I use Jboss 5.2 and i have to use mojarra 2.1.x so i hope this answer help other people in the same situation.
http://mvnrepository.com/artifact/com.sun.faces/jsf-api/2.1.29-01
http://mvnrepository.com/artifact/com.sun.faces/jsf-impl/2.1.29-01

Resources