How to implement jsf validator? - jsf

HI,
I want to know how to implement Validator in JSF. What is the advantages of declaring the validator-id. When it will be called in the life cycle?. I have implemented the following code. Please find out what is wrong in the code. I am not seeing it called anywhere in the life cycle.
<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC
"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
"http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
<faces-config>
<lifecycle>
<phase-listener>javabeat.net.jsf.JsfPhaseListener</phase-listener>
</lifecycle>
<validator>
<validator-id>JsfValidator</validator-id>
<validator-class>javabeat.net.jsf.JsfValidator</validator-class>
</validator>
<managed-bean>
<managed-bean-name>jsfBean</managed-bean-name>
<managed-bean-class>javabeat.net.beans.ManagedBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<navigation-rule>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>success.jsp</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>
public class JsfValidator implements Validator {
public JsfValidator()
{
System.out.println("Inside JsfValidator Constructor");
}
#Override
public void validate(FacesContext facesContext,
UIComponent uiComponent,
Object object)
throws ValidatorException {
System.out.println("Inside Validator");
}
}

You have to tie this custom validator to some jsf component on the jsf page, and that is where the vaidator-id you have defined is used. for e.g your jsf page might look something like this
<h:inputText id="myInput" value="#{mybean.property}">
<f:validator validatorId="JsfValidator"/>
</h:inputText>
If you are learning jsf validation and conversion then I strongly recommend you to go through this article which clearly explains with examples on in which jsf life cycle phase the validation happens etc.

Related

Faces message stops working after page navigation

I have a problem with faces message rendering in portlet, deployed on HCL portal 9.5, which is on top of Websphere Application Server 9.0.5.7. Portlet has two pages and when I made first page navigation, faces message stops rendering.
First page html:
<div xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:portlet="http://java.sun.com/portlet_2_0"
xmlns:p="http://primefaces.org/ui">
<f:view>
<f:metadata>
<f:event listener="#{pc_TestJSF22View.init}" type="preRenderView"></f:event>
</f:metadata>
<h:head>
<h:outputScript library="primefaces" name="jquery/jquery.js" />
</h:head>
<h:body>
<h:form id="formMain" styleClass="form">
<p:commandButton id="btnTest" value="Test"
action="#{pc_TestJSF22View.doBtnTest}" />
<p:commandButton id="btnSecondPage" value="Second page"
action="#{pc_TestJSF22View.doBtnSecondPage}" ajax="false" />
<p:messages id="msgGlobal" globalOnly="true" showIcon="false">
<p:autoUpdate />
</p:messages>
</h:form>
</h:body>
</f:view>
First page request bean:
public class TestJSF22View extends PageCodeBase {
private TestSess testSess;
public void init() {
if (PrimeFaces.current().isAjaxRequest()) {
return;
}
try {
System.out.println("INIT method");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
// button action
public String doBtnSecondPage() {
return "testView2";
}
public String doBtnTest() {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("page 1 msg updated"));
return null;
}
protected TestSess getTestSess() {
if (testSess == null) {
testSess = (TestSess) getManagedBean("testSess");
}
return testSess;
}
}
Second page html:
<div xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:portlet="http://java.sun.com/portlet_2_0"
xmlns:p="http://primefaces.org/ui">
<f:view>
<f:metadata>
<f:event listener="#{pc_TestJSF22View2.init}" type="preRenderView"></f:event>
</f:metadata>
<h:head>
<h:outputScript library="primefaces" name="jquery/jquery.js" />
</h:head>
<h:body>
<h:form id="formMain" styleClass="form">
<p:commandButton id="btnFirstPage" value="First page"
action="#{pc_TestJSF22View2.doBtnFirstPage}" ajax="false" />
<p:commandButton id="btnMsg" value="Show message"
action="#{pc_TestJSF22View2.doBtnMsg}" />
<p:messages id="msgGlobal2" globalOnly="true" showIcon="false">
<p:autoUpdate />
</p:messages>
</h:form>
</h:body>
</f:view>
Second page request bean:
public class TestJSF22View2 extends PageCodeBase {
private TestSess2 testSess2;
public void init() {
if (PrimeFaces.current().isAjaxRequest()) {
return;
}
try {
System.out.println("INIT2 method");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
// button action
public String doBtnFirstPage() {
System.out.println("doBtnFirstPage method");
return "testView";
}
public String doBtnMsg() {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("page 2 msg updated"));
return null;
}
protected TestSess2 getTestSess2() {
if (testSess2 == null) {
testSess2 = (TestSess2) getManagedBean("testSess2");
}
return testSess2;
}
}
faces-config :
<?xml version='1.0' encoding='UTF-8'?>
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
version="2.2">
<application>
<view-handler>com.ibm.faces20.portlet.FaceletPortletViewHandler</view-handler>
<el-resolver>com.ibm.faces20.portlet.PortletELResolver</el-resolver>
<resource-handler>com.ibm.faces20.portlet.httpbridge.PortletResourceHandler</resource-handler>
</application>
<factory>
<exception-handler-factory>org.primefaces.application.exceptionhandler.PrimeExceptionHandlerFactory</exception-handler-factory>
</factory>
<component>
<component-type>com.ibm.faces20.portlet.component.PortletActionURL</component-type>
<component-class>com.ibm.faces20.portlet.component.PortletActionURL</component-class>
</component>
<component>
<component-type>com.ibm.faces20.portlet.component.PortletResourceURL</component-type>
<component-class>com.ibm.faces20.portlet.component.PortletResourceURL</component-class>
</component>
<component>
<component-type>com.ibm.faces20.portlet.component.PortletRenderURL</component-type>
<component-class>com.ibm.faces20.portlet.component.PortletRenderURL</component-class>
</component>
<component>
<component-type>com.ibm.faces20.portlet.component.PortletParam</component-type>
<component-class>com.ibm.faces20.portlet.component.PortletParam</component-class>
</component>
<component>
<component-type>com.ibm.faces20.portlet.component.PortletProperty</component-type>
<component-class>com.ibm.faces20.portlet.component.PortletProperty</component-class>
</component>
<component>
<component-type>com.ibm.faces20.portlet.component.PortletNameSpace</component-type>
<component-class>com.ibm.faces20.portlet.component.PortletNameSpace</component-class>
</component>
<managed-bean>
<managed-bean-name>pc_TestJSF22View</managed-bean-name>
<managed-bean-class>pagecode.TestJSF22View</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>testSess</managed-bean-name>
<managed-bean-class>beans.TestSess</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>pc_TestJSF22View2</managed-bean-name>
<managed-bean-class>pagecode.TestJSF22View2</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>testSess2</managed-bean-name>
<managed-bean-class>beans.TestSess2</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<render-kit>
<renderer>
<component-family>javax.faces.Output</component-family>
<renderer-type>com.ibm.faces20.portlet.tag.render.ActionURLTagRender</renderer-type>
<renderer-class>com.ibm.faces20.portlet.tag.render.ActionURLTagRender</renderer-class>
</renderer>
</render-kit>
<render-kit>
<renderer>
<component-family>javax.faces.Output</component-family>
<renderer-type>com.ibm.faces20.portlet.tag.render.ResourceURLTagRender</renderer-type>
<renderer-class>com.ibm.faces20.portlet.tag.render.ResourceURLTagRender</renderer-class>
</renderer>
</render-kit>
<render-kit>
<renderer>
<component-family>javax.faces.Output</component-family>
<renderer-type>com.ibm.faces20.portlet.tag.render.RenderURLTagRender</renderer-type>
<renderer-class>com.ibm.faces20.portlet.tag.render.RenderURLTagRender</renderer-class>
</renderer>
</render-kit>
<render-kit>
<renderer>
<component-family>javax.faces.Output</component-family>
<renderer-type>com.ibm.faces20.portlet.tag.render.PortletNameSpaceTagRender</renderer-type>
<renderer-class>com.ibm.faces20.portlet.tag.render.PortletNameSpaceTagRender</renderer-class>
</renderer>
</render-kit>
<navigation-rule>
<from-view-id>/*</from-view-id>
<navigation-case>
<from-outcome>testView</from-outcome>
<to-view-id>/TestJSF22View.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/*</from-view-id>
<navigation-case>
<from-outcome>testView2</from-outcome>
<to-view-id>/TestJSF22View2.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>
So, if I illustrate my problem: When I first open portlet and first page is displayed, I click "Test" button, that displays faces message. Next, I navigate to second page and I click "Show message" button, which should display another message on second page, but it doesn't. I get the following warning:
There are some unhandled FacesMessages, this means not every FacesMessage had a chance to be rendered.
These unhandled FacesMessages are:
- page 2 msg updated
Even if I go back to the first page again and hit "Test" button one more time, message is not displayed and the same warning is what I get.
I never had problems with faces messages when I deployed portlets on IBM Websphere Portal Server 7 with JSF 2.0, but now when I run it on HCL portal 9.5 (JSF 2.2), I noticed this strange behavior.
Did I miss something while migrating to HCL portal?
Primefaces version is 7.0, p:messages usage seems ok to me. Could HCL portlet bridge cause that problem? Does anyone have experience with deploying JSF portlets on HCL Portal?
EDIT1:
I've just tried to deploy web application with identical code on Websphere Application Server 9 and it works like a charm. Based on that I believe there's some problem with HCL Portal.

PrimeFaces actionListener not calling bean

I am trying to mimic the PrimeFaces Dialog example. For some reason that I am not able to find, my PrimeFaces button does not seem to call the required managed bean method:
<h:form>
<p:commandButton value="Open" icon="ui-icon-extlink" actionListener="#{myController.createDialog()}" />
</h:form>
Managed bean:
#Named(value = "myController")
#ViewScoped
public class MyController implements Serializable {
public void createDialog() {
System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%");
...
The print statement is never executed, like if the Listener was not working. When I click the button, no response is given. No backend error, no JS error, nothing. I only see that some request is done because I log when a user passes the authorization layer. So something happens but seems to fail silently.
What I have tried:
Move the button to other places in the page
Use an id:
<p:commandButton id="ex" value="Open" icon="ui-icon-extlink" actionListener="#{myController.createDialog()}" />
<h:message for="ex" />
Remove the ViewScoped
Require a javax.faces.event.ActionEvent in the method
public void createDialog(ActionEvent event) {
System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%");
Change the method signature
action="#{myController.createDialog(5)}"
and
public void createDialog(int s) {
System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%");
I even tried to create a WEB-INF/faces-config.xml (which I would prefer not to, and according to PrimeFaces documentation I do not need it) with:
<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">
<application>
<action-listener>org.primefaces.application.DialogActionListener</action-listener>
<navigation-handler>org.primefaces.application.DialogNavigationHandler</navigation-handler>
<view-handler>org.primefaces.application.DialogViewHandler</view-handler>
</application>
<lifecycle>
<phase-listener>org.primefaces.component.lifecycle.LifecyclePhaseListener</phase-listener>
</lifecycle>
Other answers I have checked are: 1, 2, 3, 4, 5, 6
Apparently the use of actionListeners in PrimeFaces is not as correct as it should be... Is there another way to use PrimeFaces components?
This Dialog Framework code works for me:
index.xhtml
<p:commandButton id="openDialogButton" value="open dialog" action="#{myBean.openDialog('origin')}">
<!-- dialogReturn event: data could be passed, see page 587 in PF 6.1 manual. -->
<p:ajax event="dialogReturn" listener="#{myBean.doSthOnDialogReturn}"/>
</p:commandButton>
myDialogPage.xhtml
<p:commandButton id="closeButtonDialog" value="close dialog"
action="#{myBean.closeDialog('false')}"/>
<p:commandButton id="closeButtonDialog2" value="close dialog 2"
action="#{myBean.closeDialog('true')}"
ajax="false" validateClient="true"/>
Note: Example shows how to pass parameter from dialog. You can also notice, that the first button does just return while the second one does validation at first. I think these things can be useful.
myBean.java
public void openDialog(String origin) {
RequestContext.getCurrentInstance().openDialog("myDialogPage",
options, null);
}
public void closeDialog(Boolean param) {
RequestContext.getCurrentInstance().closeDialog(param);
}
public void doSthOnDialogReturn(SelectEvent event) {
if ((Boolean) event.getObject()) { // retrieve param value
doSth();
}
}
WEB-INF/faces-config.xml
<application>
<action-listener>
org.primefaces.application.DialogActionListener
</action-listener>
<navigation-handler>
org.primefaces.application.DialogNavigationHandler
</navigation-handler>
<view-handler>
org.primefaces.application.DialogViewHandler
</view-handler>
</application>
Finally I got to see some error:
SEVERE - /page.xhtml #159,146 actionListener="#{myController.createDialog()}": Target Unreachable, identifier 'myController' resolved to null
The trick to enable the display of error messages was to add the following in faces-config.xml:
<factory>
<exception-handler-factory>org.primefaces.application.exceptionhandler.PrimeExceptionHandlerFactory</exception-handler-factory>
</factory>
After checking this, I realised that my beans.xml file had been somehow deleted (??)

Can't upload file & validation message not appear

i'm new in java & jsf framework. I have a situation and make me realy confused. I'm trying to create upload form in jsf, the backing bean is request scoped, user must login for using this form. when I test to submit form, the validation message its not appear, the form just refresh without any validation/required message. I try to find the answer in google or stackoverflow but it not works. However i can upload my files when i try create simple application like my form below, without login function.
My form is look like this:
<h:form id="frMember" enctype="multipart/form-data">
<h:inputText id="username" value="#{memberForm.email}" required="true" requiredMessage="username_required_message" pt:placeholder="username"/><br/><br/>
<h:inputFile value="#{memberForm.fileFoto}" required="true" requiredMessage="file_required_message"/><br/>
<h:commandButton value="upload" action="#{memberForm.upload()}" class="btn btn-danger"/>
</h:form>
I'm using glassfish 4, JSF 2.2.7, Netbeans 8 and i'm not used 3rd party like tomahawk fileupload. I also have try googling and searching through stackoverflow for solving my problem, but still i can't solved it.
updated
this is my controller
public class MemberFormView implements Serializable {
private Part fileFoto;
/**
* Creates a new instance of MemberFormView
*/
public MemberFormView() {
}
public void upload() throws IOException {
String fileName = FilenameUtils.getName(fileFoto.getName());
String contentType = fileFoto.getContentType();
try (InputStream input = fileFoto.getInputStream()) {
Files.copy(input, new File("/var/AppFile/tmp/", fileFoto.getName()).toPath());
}
}
}
and this is my faces-config.xml
<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">
<managed-bean>
<managed-bean-name>memberForm</managed-bean-name>
<managed-bean-class>controller.member.MemberFormView</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
</faces-config>

#Named #Produces getter not recognized with bean-discovery-mode="annotated"

I am trying to get samples running of the book "Java EE 7 Development with WildFly". Now I face the following question/problem:
TheatreInfo.java:
#Model
public class TheatreInfo {
...
#Produces
#Named
public Collection<Seat> getSeats() {
return Lists.newArrayList(seats);
}
...
}
Seat.java:
#Dependent
#Named
public class Seat {
...
public String getName() {
return name;
}
...
}
index.xhtml:
<?xml version="1.0" encoding="UTF-8" ?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
template="/WEB-INF/templates/default.xhtml">
<ui:define name="content">
<h1>TicketBooker Machine</h1>
<h:form id="reg">
<h:panelGrid columns="1" border="1" styleClass="smoke">
<h:dataTable var="_seat" value="#{seats}" rendered="#{not empty seats}" styleClass="simpletablestyle">
...
</h:dataTable>
</h:panelGrid>
</h:form>
</ui:define>
</ui:composition>
beans.xml:
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="1.1" bean-discovery-mode="all/annotated">
</beans>
This perfectly works - I see a table of seats in my web-brower - as long as I use bean-discovery-mode="all" in my beans.xml. As soon as I use bean-discovery-mode="annotated" in my beans.xml I don't see the table of seats anymore in my browser respectively I see an empty table but no error occurs.
In the book they use bean-discovery-mode="all" but I prefer to see which classes are managed beans an which are not. To use bean-discovery-mode="annotated" I had to add #Dependent to some classes but I have not been able to fix the issue with the names producer method. Can anyone help?
Hm, it runs if I use
#Named
#RequestScoped
public class TheatreInfo {
...
instread of
#Model
public class TheatreInfo {
...
Don't understand why, #Named and #RequestScoped is included in the #Model stereotype!? Does anyone know?
Thanks, Dominic

JSF action not triggered

I am trying to do a simple test before I dive into a large activity. But, here is where I was stuck. The test is to submit the JSF form, but the managed bean action never gets triggered.
<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"
xmlns:ice="http://www.icesoft.com/icefaces/component">
<f:view>
<head>
<title>A B C</title>
</head>
<body>
<h:form id="test">
<h:inputText value="demo"/>
<h:commandButton type="submit" value="A button" action="#{User.better}" immediate="true" />
</h:form>
</body>
</f:view>
</html>
Here is my managed bean
public class User {
public String send() {
System.out.println("Submitting data.....");
return null;
}
public void better() {
System.out.println("In better...");
}
}
I have set all the configurations correctly. I could be able to see the page. But,the control never gets into action method. How come? Any suggestions would be great.
UPDATE:
Here is my faces-conig.xml
<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
<application>
<view-handler>com.icesoft.faces.facelets.D2DFaceletViewHandler</view-handler>
</application>
<managed-bean>
<managed-bean-name>User</managed-bean-name>
<managed-bean-class>com.srk.beans.User</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
</faces-config>
I have changed the managed-bean-name from User to user(small case) and changed the same in the .xhtml page as well, but seems to be same problem still.
Try user instead of User.Thus, try put user.better instead of User.better. Are you using jsf 2 or no? Also, post your faces-config file
Support for an action method with a void return type did not show up in JSF until v2.x. You must specify a return type of at least Object for better
public Object better() {
System.out.println("In better...");
return null;
}

Resources