We have dynamic menu items in a page and the links for include-source .xhtml stored in the DB, in this scenario if source xhtml is wrongly input or failed to find the application context it throws TagAttributeException with Invalid Path message.
After this event, if we make any ajax request it failed, reason is in the restore-view phase tried to restore with invalid xhtml (include src).
Is there any way to handle this exception at the runtime and change the xhtml src to some default xhtml. So that any further AJAX call will work.
XHTML
<h:form prependId="false">
<p:commandButton actionListener="#{exceptionPF.includePage()}"
ajax="true"
value="Include Wrong Source" />
<p:commandButton actionListener="#{exceptionPF.includeRightPage()}"
ajax="true"
value="Include Right Source" />
<p:panel id="div1" >
<ui:include src="#{exceptionPF.srcPage}" />
</p:panel>
<p:ajaxExceptionHandler type="javax.faces.view.facelets.TagAttributeException"
update="exceptionDialog"
onexception="PF('exceptionDialog').show();" />
<p:dialog id="exceptionDialog" header="Exception '#{pfExceptionHandler.type}' occured!" widgetVar="exceptionDialog"
height="500px">
Message: #{pfExceptionHandler.message} <br/>
Stack-Trace: <h:outputText value="#{pfExceptionHandler.formattedStackTrace}" escape="false" /> <br />
<p:button onclick="document.location.href = document.location.href;"
value="Reload!"
rendered="#{pfExceptionHandler.type == 'javax.faces.application.ViewExpiredException'}" />
</p:dialog>
</h:form>
Bean
#Named
#ViewScoped
public class ExceptionPF implements Serializable {
String srcPage;
public String getSrcPage() {
return srcPage;
}
public void setSrcPage(String srcPage) {
this.srcPage = srcPage;
}
public void includePage()
{
setSrcPage("wrong.xhtml");
RequestContext.getCurrentInstance().update("div1");
}
public void includeRightPage()
{
setSrcPage("correct.xhtml");
RequestContext.getCurrentInstance().update("div1");
}
}
Error
19:38:08,978 INFO [stdout] (default task-14) *****BEFORE **** RESTORE_VIEW
19:38:08,985 INFO [stdout] (default task-14) *****AFTER **** RESTORE_VIEW
19:38:08,986 SEVERE [javax.enterprise.resource.webcontainer.jsf.context]
(default task-14) javax.faces.view.facelets.TagAttributeException:
/index.xhtml #33,62
<ui:include src="#{exceptionPF.srcPage}"> Invalid path : wrong.xhtml
at com.sun.faces.facelets.tag.ui.IncludeHandler.apply(IncludeHandler.jav
There's no way of handling an exception from the view side on when it's the view itself who is causing the exception.
You can use ViewDeclarationLanguage#viewExists() to check if a given view exists. You should do this before setting the srcPage and if necessary get hold of the wrong value in a separate (boolean) variable.
Here's how you can use it in flavor of an utility method:
public static boolean viewExists(String viewId) {
FacesContext context = FacesContext.getCurrentInstance();
return context.getApplication().getViewHandler()
.getViewDeclarationLanguage(context, viewId).viewExists(context, viewId);
}
Related
I created a custom validator which is not getting called when input is null.
My validator code:
#FacesValidator("requiredValidator")
public class RequredValidation implements Validator {
public void validate(FacesContext context, UIComponent component,
Object value) throws ValidatorException {
System.out.println("in valid GGGGGGGG");
}
My xhtml page code:
<p:message for="urlInput" />
<p:inputText id="urlInputv" value="#{coverageBean.firstname}" label="URL" maxlength="2" >
<f:validator validatorId="requiredValidator"></f:validator>
</p:inputText>
<p:message for="urlInputv" />
<p:commandButton value="submit" action="#{loginBean.validateText}" />
Now this is working when I am entering any value in text box, but it is not working when inputtext is null.
The server is using
Tomcat
primefaces 3.5
jsf2.0
Please could anyone tell what the problem is?
By default, JSF does not validate an empty submitted value if Bean Validation (JSR303) is not available in the environment. This behavior can be controlled with the context parameter javax.faces.VALIDATE_EMPTY_FIELDS.
The default value for javax.faces.VALIDATE_EMPTY_FIELDS is auto, meaning that empty fields are validated if Bean Validation (JSR303) is available in the class path.
If you want to validate empty fields anyway without Bean Validation, then explicitly set the context parameter in your web.xml to true like this:
<context-param>
<param-name>javax.faces.VALIDATE_EMPTY_FIELDS</param-name>
<param-value>true</param-value>
</context-param>
It must be said that you normally use required="true" in case you want to validate an input field as required. You don't need to perform that job in your custom validator then.
<p:inputText ... required="true" requiredMessage="Please enter value" />
Or, more abstract with <f:validateRequired>:
<p:inputText ... requiredMessage="Please enter value">
<f:validateRequired />
</p:inputText>
Do note that you can safely use multiple validators on the very same input component.
Did you try to put :
<p:inputText id="urlInputv" required="true"
....
required true is used to avoid null value by user.
If you don't want to have a required input, then initialize your value:
firstname = ""; //or a default value
This is my first time using h:inputFile and I'm having some trouble.
The setter method for the Part attribute in my Managed Bean is never being called, so when the upload method is called, the Part object is always null.
Form and inputFile component
<h:form enctype="multipart/form-data">
<div class="pic add-pic">
<h:inputFile id="upload-test" required="true"
value="#{uploadController.uploadedFile}">
</h:inputFile>
<h:commandLink styleClass="pic add-pic"
action="#{uploadController.addPic()}">
<i class="fa fa-plus"></i>
<span>Add pic</span>
</h:commandLink>
</div>
</h:form>
Managed Bean
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.servlet.http.Part;
#ManagedBean
#ViewScoped
public class UploadController {
private Part uploadedFile;
public Part getUploadedFile() {
return this.uploadedFile;
}
public void setUploadedFile(Part uploadedFile) {
this.uploadedFile = uploadedFile;
}
public void addPic() {
System.out.println("Uploaded a file: " +
uploadedFile.getSubmittedFileName());
}
}
I've tried already with ajax in the inputFile
<h:inputFile id="upload-test" required="true"
value="#{uploadController.uploadedFile}">
<f:ajax execute="#form" listener="#{uploadController.addPic()}" />
</h:inputFile>
and with ajax in the commandLink
<h:commandLink styleClass="pic add-pic">
<i class="fa fa-plus"></i>
<span>Add pic</span>
<f:ajax execute="#form" listener="#{uploadController.addPic()}" />
</h:commandLink>
But neither options worked as well.
PS: I'm using javax.servlet-api version 3.1 and JSF 2.2.12 (Mojarra) and running on Wildfly 9.0.2
PS2: I'm using also Primefaces (not in this case), and I have the fileUpload filter in my web.xml (I've tried to remove it, tested and no success).
After several tries and after deploying a fresh project with only the defaults (just like #BalusC said in the comments of my question), I discovered that the problem was the PrimeFaces FileUploadFilter in web.xml!!
I got rid of it before, but I don't know why didn't worked that time, could've been some problem with the project deployment refresh provided by Eclipse.
But now I tried again and it worked!
Thanks #BalusC for your help!
Thanks BalusC and Diego Marques! I had a similar problem with my application, which was deployed on Tomcat 8 - the h:inputFile value "Part" setter was never called. Your help pointed me to some of my libraries which had already discovered that my issue was actually a Tomcat setting.
In case it helps to have it included here too, Tomcat (and likely Glassfish)needs the following setting to make it "spec-compliant".
<Context allowCasualMultipartParsing="true"
https://github.com/ocpsoft/rewrite/issues/136
Instead of doing the above context setting, you can have your bean marked with #MultipartConfig (and #WebServlet).
sample page.
<tr:outputText value="#{my.name}" id="name"/>
<tr:commandButton text="Click" action="#{my.doaction}" id="test1">
<f:ajax event="click" listener="#{my.myajax}" render="name"></f:ajax>
</tr:commandButton>
</tr:form>
</ui:define>
</ui:composition>
Managed bean...scope request
#PostConstruct
public void init(){
_name = "default";
}
public void doaction(){
System.out.println("In doaction");
}
public void myajax(AjaxBehaviorEvent ae) throws javax.faces.event.AbortProcessingException{
_name = "Ajax";
}
public void myajax() throws javax.faces.event.AbortProcessingException{
_name = "Ajax";
}
i am using trinidad buttons. jsf 2. my listener is not being called. none of the myajax(AjaxBehaviorEvent ae)
myajax()
are called. however my doaction method is being called.
what am i missing. ?
please help.
note: my facesconfig is below. does specifying 2.2 and using trinidad 2.0 and myfaces 2.0 create this problem?
<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>
<default-render-kit-id>org.apache.myfaces.trinidad.core</default-render-kit-id>
</application>
</faces-config>
You cannot mix an action called in ajax with an action refreshing the page in h:commandButton.
You have to choose.
Did you try like this ?
<tr:commandButton text="Click" id="test1">
<f:ajax event="click" listener="#{my.doaction}" render="name" />
<f:ajax event="click" listener="#{my.myajax}" render="name" />
</tr:commandButton>
I created a custom validator which is not getting called when input is null.
My validator code:
#FacesValidator("requiredValidator")
public class RequredValidation implements Validator {
public void validate(FacesContext context, UIComponent component,
Object value) throws ValidatorException {
System.out.println("in valid GGGGGGGG");
}
My xhtml page code:
<p:message for="urlInput" />
<p:inputText id="urlInputv" value="#{coverageBean.firstname}" label="URL" maxlength="2" >
<f:validator validatorId="requiredValidator"></f:validator>
</p:inputText>
<p:message for="urlInputv" />
<p:commandButton value="submit" action="#{loginBean.validateText}" />
Now this is working when I am entering any value in text box, but it is not working when inputtext is null.
The server is using
Tomcat
primefaces 3.5
jsf2.0
Please could anyone tell what the problem is?
By default, JSF does not validate an empty submitted value if Bean Validation (JSR303) is not available in the environment. This behavior can be controlled with the context parameter javax.faces.VALIDATE_EMPTY_FIELDS.
The default value for javax.faces.VALIDATE_EMPTY_FIELDS is auto, meaning that empty fields are validated if Bean Validation (JSR303) is available in the class path.
If you want to validate empty fields anyway without Bean Validation, then explicitly set the context parameter in your web.xml to true like this:
<context-param>
<param-name>javax.faces.VALIDATE_EMPTY_FIELDS</param-name>
<param-value>true</param-value>
</context-param>
It must be said that you normally use required="true" in case you want to validate an input field as required. You don't need to perform that job in your custom validator then.
<p:inputText ... required="true" requiredMessage="Please enter value" />
Or, more abstract with <f:validateRequired>:
<p:inputText ... requiredMessage="Please enter value">
<f:validateRequired />
</p:inputText>
Do note that you can safely use multiple validators on the very same input component.
Did you try to put :
<p:inputText id="urlInputv" required="true"
....
required true is used to avoid null value by user.
If you don't want to have a required input, then initialize your value:
firstname = ""; //or a default value
I am trying to make a commandButton enabled/disabled by using a checkbox. The commandbutton is disabled initially. When user checks the checkbox, the commandbutton turns into enabled. But it does not response when clicked the button.
If I make the commandbutton independent from checkbox, it works fine. But with checkbox, I get the problem that I mentioned above. Please help me
Here are codes.
index.xhtml
<h:form>
<h:selectBooleanCheckbox value="#{formSettings.licenseAccepted}" id="cb">
<f:ajax event="click" render="suB cb"/>
</h:selectBooleanCheckbox>
<h:outputText value="#{formSettings.msg}"/><br/>
<h:commandButton id="suB" disabled="false" value="Save" action="loginSuccessfull"/>
</h:form>
FormSettings.java
package classes;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
#ManagedBean
#RequestScoped
public class FormSettings
{
private boolean licenseAccepted = false;
private String msg = "Accept License";
public FormSettings(){};
public boolean isLicenseAccepted(){return this.licenseAccepted;};
public void setLicenseAccepted(boolean licenseAccepted){this.licenseAccepted = licenseAccepted;};
public String getMsg(){return this.msg;};
public void setMsg(String msg){this.msg = msg;};
}
faces-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<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">
<navigation-rule>
<from-view-id>/index.xhtml</from-view-id>
<navigation-case>
<from-outcome>loginSuccessfull</from-outcome>
<to-view-id>/login.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>
The bean has to be placed in the view scope in order to get it to work.
#ManagedBean
#ViewScoped
public class FormSettings {}
Enabling the button by ajax counts as one HTTP request. Submitting the form with the button thereafter counts as another HTTP request. As your bean is request scoped, it get freshly created on every HTTP request and garbaged by the end of request. As the boolean property defaults to false, the button get effectively disabled again when JSF is about to process the form submit on the second request.
See also:
How to choose the right bean scope?