I have sample Spring Boot project for PrimeFaces and looking for a way to make awesomefont to work as shown in PF Showcase.
So I created awesomefont-test.xhtml
<?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.org/ui">
<h:head>
<title>Awesomefont Test</title>
</h:head>
<h:body>
<p:commandButton value="Edit" icon="fa fa-fw fa-edit" type="button"/>
</h:body>
</html>
and the result is (no icon)
I tried several things:
1.) web.xml
I created web.xml and I tried to put it next to faces-config.xml (which is in jsf-primefaces-spring-boot/src/main/resources/META-INF/).
I tried to put it to jsf-primefaces-spring-boot/src/main/resources/WEB-INF/ not working too.
I do not know how to check it is read.
content:
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<context-param>
<param-name>primefaces.FONT_AWESOME</param-name>
<param-value>true</param-value>
</context-param>
</web-app>
2.) SpringBootServletInitializer
package com.codenotfound.primefaces;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.support.SpringBootServletInitializer;
#SpringBootApplication
public class SpringPrimeFacesApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(SpringPrimeFacesApplication.class, args);
}
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.setInitParameter("primefaces.FONT_AWESOME", "true");
super.onStartup(servletContext);
}
}
source: How to set context-param in spring-boot
3.) application.properties
From same source I tried to set property in application.properties
server.context_parameters.primefaces.FONT_AWESOME=true
also I tried variant with
server.servlet.context-parameters.primefaces.FONT_AWESOME=true
4.) webjars
This is a workaround, I just wanted to give it a try.
I also tried to add webjars dependencies (and modify xhtml) as described here - http://www.littlebigextra.com/add-bootstrap-css-jquery-to-springboot-mvc/
but none of those approaches worked for me.
After defining the dependency in pom.xml:
<dependency>
<groupId>org.webjars</groupId>
<artifactId>font-awesome</artifactId>
<version>4.7.0</version>
</dependency>
You need to add config into application.yml:
jsf:
primefaces:
FONT_AWESOME: true
or if use application.properties add:
jsf.primefaces.FONT_AWESOME=true
You don't need to create a web xml, just add the dependency and in your application.properties add this:
jsf.primefaces.font-awesome=true
And if you what to configure a theme add this:
jsf.primefaces.theme= theme-name
Related
I'm new to Java and tried to follow this tutorial. Since it's outdated, I've made some changes to use newer versions:
Netbeans 14
Glassfish 6
Java EE7
Jakarta Faces 3
Mojarra 3.0.1
The tutorial consists of a form where a user submits a message and gets the total count. However, when I submit, I get
Any clue of what I'm missing?
Here are the Glassfish logs
When app runs
WELD-000411: Observer method [BackedAnnotatedMethod] public
org.glassfish.jersey.ext.cdi1x.internal.ProcessAllAnnotatedTypes.processAnnotatedType(#Observes
ProcessAnnotatedType, BeanManager) receives events for all
annotated types. Consider restricting events using #WithAnnotations or
a generic type with bounds.|#] WELD-000411: Observer method
[BackedAnnotatedMethod] public
org.glassfish.jms.injection.JMSCDIExtension.processAnnotatedType(#Observes
ProcessAnnotatedType) receives events for all annotated types.
Consider restricting events using #WithAnnotations or a generic type
with bounds.|#] WELD-000411: Observer method [BackedAnnotatedMethod]
org.glassfish.sse.impl.ServerSentEventCdiExtension.processAnnotatedType(#Observes
ProcessAnnotatedType, BeanManager) receives events for all
annotated types. Consider restricting events using #WithAnnotations or
a generic type with bounds.|#] WELD-000146:
BeforeBeanDiscovery.addAnnotatedType(AnnotatedType) used for class
com.ibm.jbatch.container.cdi.BatchProducerBean is deprecated from CDI
1.1!|#] Initializing Soteria 2.0.1 for context '/mavenproject1'|#] Initializing Mojarra 3.0.1 for context '/mavenproject1'|#]
Monitoring jndi:/server/mavenproject1/WEB-INF/faces-config.xml for
modifications|#] Loading application [mavenproject1] at
[/mavenproject1]|#] mavenproject1 was successfully deployed in 4,055
milliseconds.|#]
When I click submit
/index.xhtml #15,103 value="#{messageView.message.message}": Target
Unreachable, identifier 'messageView' resolved to null
jakarta.el.PropertyNotFoundException: /index.xhtml #15,103
value="#{messageView.message.message}": Target Unreachable, identifier
'messageView' resolved to null at
com.sun.faces.facelets.el.TagValueExpression.getType(TagValueExpression.java:64)
at
com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getConvertedValue(HtmlBasicInputRenderer.java:69)
at
jakarta.faces.component.UIInput.getConvertedValue(UIInput.java:1040)
at jakarta.faces.component.UIInput.validate(UIInput.java:955) at
jakarta.faces.component.UIInput.executeValidate(UIInput.java:1232) at
jakarta.faces.component.UIInput.processValidators(UIInput.java:721)
at jakarta.faces.component.UIForm.processValidators(UIForm.java:217)
at
jakarta.faces.component.UIComponentBase.processValidators(UIComponentBase.java:901)
at
jakarta.faces.component.UIComponentBase.processValidators(UIComponentBase.java:901)
at
jakarta.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1254)
at
com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:49)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:72) at
com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:159)
at
jakarta.faces.webapp.FacesServlet.executeLifecyle(FacesServlet.java:681)
at jakarta.faces.webapp.FacesServlet.service(FacesServlet.java:437)
at
org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1540)
at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:217)
at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:119)
at
org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:611)
at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:550)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:75) at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:114)
at
org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:332)
at
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:199)
at
com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:440)
at
com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:144)
at
org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:174)
at
org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:153)
at
org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:196)
at
org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:88)
at
org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:246)
at
org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:178)
at
org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:118)
at
org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:96)
at
org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:51)
at
org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:510)
at
org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:82)
at
org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:83)
at
org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:34)
at
org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:101)
at
org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:535)
at
org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:515)
at java.base/java.lang.Thread.run(Thread.java:833) Caused by:
jakarta.el.PropertyNotFoundException: Target Unreachable, identifier
'messageView' resolved to null at
com.sun.el.parser.AstValue.getTarget(AstValue.java:148) at
com.sun.el.parser.AstValue.getType(AstValue.java:62) at
com.sun.el.ValueExpressionImpl.getType(ValueExpressionImpl.java:160)
at
org.jboss.weld.module.web.el.WeldValueExpression.getType(WeldValueExpression.java:93)
at
com.sun.faces.facelets.el.TagValueExpression.getType(TagValueExpression.java:62)
... 42 more
Here are some of the related files
index.xhtml
<?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://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
</h:head>
<h:body>
<f:view>
<h:form>
<h:outputLabel value="Message:"/><h:inputText value="#{messageView.message.message}"/>
<h:commandButton action="#{messageView.postMessage}" value="Post Message"/>
</h:form>
</f:view>
</h:body>
</html>
MessageView.java
package my.presentation;
import boundary.MessageFacade;
import entities.Message;
import javax.ejb.EJB;
import javax.inject.Named;
import javax.enterprise.context.RequestScoped;
#Named(value = "messageView")
#RequestScoped
public class MessageView {
#EJB
private MessageFacade messageFacade;
private Message message;
public MessageView() {
this.message = new Message();
}
public Message getMessage(){
return message;
}
public int getMessagesCount(){
return messageFacade.findAll().size();
}
public String postMessage(){
this.messageFacade.create(message);
return "theend";
}
}
faces-config.xml
<?xml version='1.0' encoding='UTF-8'?>
<faces-config xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-facesconfig_3_0.xsd"
version="3.0">
</faces-config>
beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/beans_3_0.xsd"
version="3.0" bean-discovery-mode="annotated">
</beans>
pom.xml
<dependencies>
<dependency>
<groupId>jakarta.faces</groupId>
<artifactId>jakarta.faces-api</artifactId>
<version>3.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.5.1</version>
</dependency>
</dependencies>
glassfish-web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<!--
Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
http://www.eclipse.org/legal/epl-2.0.
This Source Code may also be made available under the following Secondary
Licenses when the conditions for such availability set forth in the
Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
version 2 with the GNU Classpath Exception, which is available at
https://www.gnu.org/software/classpath/license.html.
SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
-->
<glassfish-web-app error-url="">
<class-loader delegate="true"/>
<jsp-config>
<property name="keepgenerated" value="true">
<description>Keep a copy of the generated servlet class' java code.</description>
</property>
</jsp-config>
</glassfish-web-app>
Already checked this and this with no luck.
I try to configure jersey-mvc-freemarker on TomEE 1.7.2. But I can't ...
Configure Jersey
#ApplicationPath("resources")
public class JerseyConfig extends ResourceConfig{
public JerseyConfig() {
packages("my.pack.controllers")
.property(MvcFeature.TEMPLATE_BASE_PATH, "/WEB-INF/classes/my/pack")
.register(org.glassfish.jersey.server.mvc.freemarker.FreemarkerMvcFeature.class);
}
}
Controller
#Path("main")
public class MainController {
#Inject
private TestBean bean;
#GET
public Viewable getIt() {
return new Viewable("test");
}
}
web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<display-name>ui</display-name>
</web-app>
I put my test.ftl to my.pack
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>test</title>
</head>
<body>
test
</body>
</html>
When I go to http://localhost:8080/resources/main I get message
No message body writer has been found for response class Viewable.
Thanks you
UPDATE:
I configured tracing in Jersey and got:
javax.servlet.ServletException: Error processing webservice request
org.apache.tomee.webservices.CXFJAXRSFilter.doFilter(CXFJAXRSFilter.java:98)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
root cause
java.lang.NullPointerException
org.apache.openejb.server.cxf.rs.CxfRsHttpListener.doInvoke(CxfRsHttpListener.java:227)
org.apache.tomee.webservices.CXFJAXRSFilter.doFilter(CXFJAXRSFilter.java:94)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
note The full stack trace of the root cause is available in the Apache Tomcat (TomEE)/7.0.62 (1.7.2) logs.
First of all, I'm sorry for my bad English.
I´m new working with JSF, so I am sure that this is really stupid question but I couldn't find any post that help me. I´m using ajax poll in my project because I need refresh components in the page. I founded an example in the primefaces 5 showcase. In this example there is a counter that increments every 3 seconds. I used the code of the example in the exactly same way but the counter never increments. I think that this could be a bad configuration that I used in my project. Also, its showed the next message in the Eclipse console (I don´t know if this has something to do with my problem):
Información: No state saving method defined, assuming default server
state saving
Here is my sorce code:
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"></meta>
<title>Insert title here</title>
</h:head>
<h:body>
<h:form>
<h:outputText id="txt_count" value="#{globalCounterView.count}"/>
<p:poll interval="3" listener="#{globalCounterView.increment}" update="txt_count"/>
</h:form>
</h:body>
</html>
In the bean:
import java.io.Serializable;
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
import javax.faces.event.ActionEvent;
#ManagedBean
#ApplicationScoped
public class GlobalCounterView implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private int count;
public int getCount() {
return count;
}
public void increment(ActionEvent actionEvent) {
count++;
}
public void setCount(int count) {
this.count = count;
}
}
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>SAEGraph</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
In the end, the thing what I want to do is update a primeface component from backing bean periodically. Also, Can you tell me if exists any other way to do this not using poll ????
Thanks and sorry again for the bad english.
I'm using primefaces 5.0, Tomcat 7, Eclipse Version: 4, JDK 7
Just remove the argument in increment method.
public void increment(ActionEvent actionEvent) {
count++;
}
to:
public void increment() {
count++;
}
I am new to jsf and trying to implement autocomplete box.
So here is what i did.
home.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
<h:form>
<rich:autocomplete mode="ajax" layout="table" autocompleteMethod="#{searchCity.searchCityByMatchChar}" autocompleteList="#{searchCity.listOfCity}"
var="city" fetchValue="#{city.cityName}">
<rich:column>
#{city.cityName}
</rich:column>
</rich:autocomplete>
</h:form>
</ui:composition>
SearchCity.java
package com.cheapesto.cheapbilly.model;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import com.cheapesto.cheapbilly.dto.City;
#ManagedBean(name = "searchCity")
#SessionScoped
public class SearchCity {
private List<City> listOfCity;
public List<City> getListOfCity() {
return listOfCity;
}
public void setListOfCity(List<City> listOfCity) {
this.listOfCity = listOfCity;
}
public List<City> searchCityByMatchCharforauto() {
City city1 = new City();
city1.setCityId(1l);
city1.setCityName("New York");
City city2 = new City();
city2.setCityId(1l);
city2.setCityName("New Jesrsey");
City city3 = new City();
city3.setCityId(1l);
city3.setCityName("Seattle");
List<City> listOfCity = new ArrayList<City>();
listOfCity.add(city1);
listOfCity.add(city2);
listOfCity.add(city3);
return listOfCity;
}
}
faces-config.xml
<faces-config
xmlns="http://java.sun.com/xml/ns/javaee"
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_2_0.xsd"
version="2.0">
</faces-config>
I am getting error as :
SEVERE: Servlet.service() for servlet [Faces Servlet] in context with path [/MyFirstFaces] threw exception [/faces/home.xhtml: Property 'searchCityByMatchChar' not found on type com.cheapesto.cheapbilly.model.SearchCity] with root cause
javax.el.ELException: /faces/home.xhtml: Property 'searchCityByMatchChar' not found on type com.cheapesto.cheapbilly.model.SearchCity
at com.sun.faces.facelets.compiler.AttributeInstruction.write(AttributeInstruction.java:91)
at com.sun.faces.facelets.compiler.UIInstructions.encodeBegin(UIInstructions.java:78)
at com.sun.faces.facelets.compiler.UILeaf.encodeAll(UILeaf.java:179)
at javax.faces.render.Renderer.encodeChildren(Renderer.java:164)
I am not getting why it is considering method as a property. can someone please help me with correct changes and explanation.
RichFaces is not properly installed. Your RichFaces tag is basically interpreted as plain text, which is recognizable as UIInstructions in the stack trace:
at com.sun.faces.facelets.compiler.UIInstructions.encodeBegin(UIInstructions.java:78)
It's essentially the same problem as when you would do e.g.
<p>#{searchCity.searchCityByMatchChar}</p>
EL in template text is by default resovled as a property value expression, requiring a getter method.
Verify if you installed RichFaces right. It are 7 JAR files in /WEB-INF/lib.
There is not method searchCityByMatchChar on your bean. It's called searchCityByMatchCharforauto. This may be the root cause of your error.
I found that disabled attribute for any validator I use in JSF2 is evaluated only in the first cycle if my managed bean is ViewScoped.
But I would like to make use of disabled attribute for my validators based on data I get from 4th update phase. So I would expect it reevaluated in all cycles performed on the same view.
Example xhtml page:
<!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:f="http://java.sun.com/jsf/core">
<h:head></h:head>
<h:body>
<h:form>
<h:panelGrid id="pnlGrid">
<h:inputText id="someValueId" value="#{testPageBean.someValue}">
<f:validateLength minimum="2" maximum="4"
disabled="#{testPageBean.disableValidateLength}"/>
</h:inputText>
<h:messages for="someValueId"/>
<h:commandButton action="#{testPageBean.doSomething}"
value="Do something" />
</h:panelGrid>
</h:form>
</h:body>
</html>
and its view scoped managed bean
package cz.kamosh;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class TestPageBean implements Serializable {
boolean disableValidateLength = false;
private String someValue;
public TestPageBean() {
System.out.println("Constructor TestPageBean");
}
public String getSomeValue() {
return someValue;
}
public void setSomeValue(String someValue) {
this.someValue = someValue;
}
/**
* Some action without any navigation as a result
*/
public void doSomething() {
disableValidateLength = !disableValidateLength;
System.out.printf(
"DoSomething, someValue: %1$s, disableValidateLength: %2$b\n",
someValue, disableValidateLength);
}
public boolean isDisableValidateLength() {
System.out.printf("IsValidateLength, disableValidateLength: %1$b\n",
disableValidateLength);
return disableValidateLength;
}
}
I know that I should blame implementation com.sun.faces.facelets.tag.jsf.ValidatorTagHandlerDelegateImpl:
private void applyNested(FaceletContext ctx,
UIComponent parent) {
// only process if it's been created
if (!ComponentHandler.isNew(parent)) {
return;
}
...
}
These three rows cause validator not being reevaluated its disabled attribute when I perform action:-(
Could some please give me a hint, what was the motivation for JSF2 guys to implement this way or even better how to solve my problem?
EDIT:
Version of JSF2: 2.0.3-SNAPSHOT
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>JSF2Testing</display-name>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>
</web-app>
EDIT2 Attempt to follow BalusC' suggestion
Changes on page:
<h:inputText id="someValueId" value="#{testPageBean.someValue}">
<f:validator validatorId="myLengthValidator"/>
<f:attribute name="disableMyLengthValidator" value="#{testPageBean.disableValidateLength}"/>
<f:attribute name="minimum" value="2" />
<f:attribute name="maximum" value="4" />
</h:inputText>
Own validator used instead of standard :
import java.io.Serializable;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.LengthValidator;
import javax.faces.validator.ValidatorException;
#FacesValidator("myLengthValidator")
public class MyLengthValidator extends LengthValidator implements Serializable {
public MyLengthValidator() {
System.out.println("MyLengthValidator constructor");
}
#Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
if((Boolean)component.getAttributes().get("disableMyLengthValidator")) {
return;
}
setMinimum(Integer.valueOf((String)component.getAttributes().get("minimum")));
setMaximum(Integer.valueOf((String)component.getAttributes().get("maximum")));
super.validate(context, component, value);
}
}
My notes about this solution:
requires own implementation even if for standard validators
is dependent on attributes on component (inputText) level
validator is triggered even if it should not be
I am pretty sure it will not behave as we expect when client side validation is provided for validator
I consider is as very ugly and not following JSF2 :-(
You've become another victim of the chicken-egg issue with partial state saving and view scoped beans as described in issue 1492 which is to be fixed in the upcoming Mojarra 2.2.
You should also immediately have realized that something's not entirely right when you saw the constructor of a view scoped bean being invoked on every request instead of only once at the first request of a view.
One of the ways to fix it is to disable the partial state saving altogether:
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>
See also:
Communication in JSF 2 - #ViewScoped fails in tag handlers
Why does f:validateDoubleRange only work for #SessionScoped?