I try to validate a p:selectOneMenu using the validator attribute, but in the validate method the value of object is null. I don´t understand why it is null, somebody could help me. I´m using PrimeFaces 6.2.
My xhtml is:
<p:selectOneMenu id="somFieldType"
widgetVar="somFieldType"
converter="entityConverter"
required="false"
value="#{paramDetail.article_field_type}"
validator="#{detailArticleBean2.isTypeValid}"
... >
<f:selectItem itemLabel="#{i18n['avocado.general.seleccionar']}" itemValue="0"/>
<f:selectItem itemLabel="#{i18n['avocado.general.texto']}" itemValue="1"/>
...
</p:selectOneMenu>
In my bean I´m only printing the value:
public void isTypeValid(FacesContext ctx, UIComponent component, Object value) throws ValidatorException {
System.out.println(value.toString());
}
The console returns an error:
javax.el.ELException: /Ref/Art/artDetail.xhtml #165,67 validator="#{detailArticleBean2.isTypeValid}": java.lang.NullPointerException
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:111)
I´d appreciate your help.
Your value is null, so you cannot apply .toString(). Use something like:
public void isTypeValid(FacesContext ctx, UIComponent component, Object value) throws ValidatorException {
if (value == null) {
// Value is unset; don't validate
return;
}
// Value is set; do validation
...
}
See also:
What is a NullPointerException, and how do I fix it?
Related
JVM Version: 14.0.2+12-46
myfaces-api 2.3.9
myfaces-impl 2.3.9
apache-tomee-webprofile-8.0.4
I am using the following converter for an simple entity class:
package view;
import entities.Chain;
import managed.Chains;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import javax.inject.Inject;
import javax.inject.Named;
#Named
#FacesConverter(value = "chainConverter", managed = true)
public class ChainConverter implements Converter<Chain> {
#Inject
Chains chains;
#Override
public Chain getAsObject(FacesContext context, UIComponent component, String value) {
if (value != null && !value.trim().isEmpty()) {
Chain found = chains.getAvailable().stream()
.filter(chain -> chain.getAbbreviation().equals(value))
.findFirst()
.orElse(null);
return found;
}
return null;
}
#Override
public String getAsString(FacesContext context, UIComponent component, Chain chain) {
if (chain != null && !chain.toString().isEmpty()){
return chain.getAbbreviation();
}else{
return null;
}
}
}
Given the example at: https://www.primefaces.org/showcase/ui/input/oneMenu.xhtml
I try to use the converter as follows:
<p:selectOneMenu id="chain" value="#{chains.chain}" var="c" converter="chainConverter">
<f:selectItem itemLabel="== Selecte Chain ==" />
<f:selectItems value="#{chains.available}" var="chain" itemLabel="#{chain.name}" itemValue="#{chain}" />
<p:column>
#{c.name}
</p:column>
<p:ajax event="valueChange" listener="#{inventories.refreshSurvey}" update="#form" />
</p:selectOneMenu>
The above "converter=" reference produces the following error:
org.primefaces.application.exceptionhandler.PrimeExceptionHandler.logException null
java.lang.NullPointerException
at org.apache.myfaces.cdi.converter.FacesConverterCDIWrapper.getAsString(FacesConverterCDIWrapper.java:69)
at org.primefaces.renderkit.SelectRenderer.getOptionAsString(SelectRenderer.java:207)
at org.primefaces.component.selectonemenu.SelectOneMenuRenderer.encodeOption(SelectOneMenuRenderer.java:561)
at org.primefaces.component.selectonemenu.SelectOneMenuRenderer.encodeSelectItems(SelectOneMenuRenderer.java:524)
at org.primefaces.component.selectonemenu.SelectOneMenuRenderer.encodeHiddenSelect(SelectOneMenuRenderer.java:211)
If I change the converter reference to an el expression as follows:
converter="#{chainConverter}"
I get the error:
org.primefaces.application.exceptionhandler.PrimeExceptionHandler.logException Cannot convert [entities.Chain#928f] of type [class java.lang.String] to [class entities.Chain]
javax.el.ELException: Cannot convert [entities.Chain#928f] of type [class java.lang.String] to [class entities.Chain]
at org.apache.el.lang.ELSupport.coerceToType(ELSupport.java:548)
at org.apache.el.parser.AstValue.setValue(AstValue.java:203)
at org.apache.el.ValueExpressionImpl.setValue(ValueExpressionImpl.java:263)
at org.apache.webbeans.el22.WrappedValueExpression.setValue(WrappedValueExpression.java:93)
at org.apache.webbeans.el22.WrappedValueExpression.setValue(WrappedValueExpression.java:93)
However, the weirdest thing is that in one project it works while in the other project it does not. For example in this sample project it works as expected: https://github.com/dannymk/PrimefacesTest
I have a nagging suspicion that there is a difference in a library version someplace in this project. However, I really can't pinpoint the problem even after changing the pom file to match a working projects pom file. This is definitely a head scratcher to me.
I search for long time to this issue.But still i didn't get the solution.Kindly help me to this problem.
I have one JSP file and using struts for my application.When i try to load the page in browser it throws this error.
javax.servlet.jsp.JspException: No getter method for property reqKickOffMeet of bean org.apache.struts.taglib.html.BEAN.
Everything is fine.There is no case sensitive issue also .But this code is not working.Kindly help me to fix this.
JSP:
<TD class="fontclr1" colspan="2">Requirements Kick-off meeting:</TD>
<TD align="center"><html:select name="CdrQueryForm"
property="test0"
onchange="javascript:select('reqKickOffMeet','Requirements Kick-off meeting',this,1);">
<html:option value="EqualTo">Equal to</html:option>
<html:option value="GreaterThan">Greater than</html:option>
<html:option value="LessThan">Less than</html:option>
<html:option value="Between">Between</html:option>
</html:select></TD>
and my class file
private String reqKickOffMeet;
public String getReqKickOffMeet() {
return reqKickOffMeet;
}
public void setReqKickOffMeet(String reqKickOffMeet) {
this.reqKickOffMeet = reqKickOffMeet;
}
From the error it seems you are trying to load some property reqKickOffMeet from bean in the jsp. Check if the getter and setter methods are there in the class which holds this property.
Also you would like to check the signature of the getter and setters are correct.
Like
for property reqKickOffMeet
public String getReqKickOffMeet(){
return reqKickOffMeet;
}
public void setReqKickOffMeet(String reqKickOffMeet){
this.reqKickOffMeet = reqKickOfMeet;
}
Also if it still doesnt work, try renaming your variable to reqKickoffmeet (starting from smaller case and just one upper case letter in between)
I believe property element of html:select must match reqKickOffMeet. I had the same issue, my scenario was:
<html:select property="dontVerifyDependents" styleClass="body">
<html:options collection="dontVerifyDependentsOptions"
labelProperty="listValue" property="listId" />
</html:select>
Instead of dontVerifyDependents I had dontVerifyDependency and was getting the same error.
My class file:
private String dontVerifyDependents;
public void setDontVerifyDependents(String dontVerifyDependents) {
this.dontVerifyDependents = dontVerifyDependents;
}
public String getDontVerifyDependents() {
return dontVerifyDependents;
}
You should replace property="test0" for property="reqKickOffMeet".
Hope it works!
What I want to do is read a http-parameter on my login page, e.g. login.html?param=value, and then pass value to my AuthenticationProvider. My idea was to somehow save value in a hidden parameter, but I still don't know how to pass it on.
Is this possible? How do I go about to do it?
Edit: Following Sanath's advice and after doing some reading I was finally able to solve the problem -- look below if you're interested in how I did it.
I did the following and finally it worked like a charm.
In my bean configuration file I had to enter:
<http auto-config="true>
...
<form-login ... authentication-details-source-ref="myWebAuthDetSource"/>
...
</http>
<beans:bean id="myWebAuthDetSource" class="com.my.pack.age.MyWebAuthDetSource"/>
...
then I've set up my WebAuthenticationDetailsSource implementation like this:
public class MyWebAuthDetSource implements AuthenticationDetailsSource<HttpServletRequest, MyWebAuthDets> {
public MyWebAuthDetSource buildDetails (HttpServletRequest context) {
return new MyWebAuthDets(context);
}
}
then I've got my AuthenticationDetails implementation like:
public class MyWebAuthDets extends WebAuthenticationDetails {
private final String parameter;
public MyWebAuthDets(HttpServletRequest request) {
super(request);
this.parameter = request.getParameter("paramId");
}
}
And then I overlook the most simple fact, that the authentication process processes only what it gets on submit from the login form, so I simply had to add the following in login.jsp:
...
<form id="j_spring_security_check" ... >
<input type="hidden" name="paramID" value="${param['paramID']}" />
...
</form>
...
And that was all. Now I can add an authenticationProvider and get my parameter with .getDetails() from the authenticationToken.
Thanks again #Sanath.
I have made a new Seam validator:
package validators;
import java.io.Serializable;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.faces.Validator;
import org.jboss.seam.annotations.intercept.BypassInterceptors;
import org.jboss.seam.log.Log;
import org.jboss.seam.log.Logging;
#Name("roCountyValidator")
#Validator
#BypassInterceptors
public class RoCountyValidator implements javax.faces.validator.Validator,
Serializable {
/**
*
*/
private static final long serialVersionUID = -3876319398131645955L;
Log log = Logging.getLog(RoCountyValidator.class);
public void validate(FacesContext context, UIComponent component,
Object value) throws ValidatorException {
log.info("validating....!");
if (String.valueOf(value).equals("Arad"))
((UIInput) component).setValid(true);
else {
((UIInput) component).setValid(false);
FacesMessage message = new FacesMessage();
message.setDetail("Invalid county");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(message);
}
}
}
The problem is that I do not know how to use it directly from jsf...
The following does not work....
I have declared it in a special taglib file: myvalidators.taglib.xml
<facelet-taglib>
<namespace>http://example.com/jsf/my/validators</namespace>
<tag>
<tag-name>roCountyValidator</tag-name>
<validator>
<validator-id>roCountyValidator</validator-id>
</validator>
</tag>
and tried to use it like:
<h:inputText id="someField" value="#{booking.creditCardName}"
required="true" label="County">
<my:roCountyValidator/>
<h:message for="someField"/>
</h:inputText>
Can you tell me where I am wrong?
Thanks.
Two ways to solve this.
One, is to use as #BalusC has written.
You don't need to define anything in faces-config.xml
<h:inputText id="cc" required="true" value="#{booking.creditCardName}">
<f:validator validatorId="roCountyValidator"/>
<f:attribute name="oldCreditCardNumber" value="#{booking.creditCardName}" />
<s:validate />
</h:inputText>
Here you can even bind the old credit card number, if you want to check that also.
Then in your validate method:
public void validate(FacesContext context, UIComponent component,
Object value) throws ValidatorException {
log.info("validating....!");
String oldCreditcard = String.valueOf(component.getAttributes().get("oldCreditCardNumber"));
String newCreditCard = (String) value;
if(SomeClass.isCorrectCreditcard(newCreditCard)) {
//You don't need to setValid(false), this is done automatically
Map<String, String> messages = Messages.instance();
throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, messages.get("wrongCreditCardNumber"), messages
.get("wrongCreditCardNumber")));
}
}
The other way, is to use the validator tag in <h:inputText>
You don't even need to create a #Validator class, as long as it's a seam component and if you use the same method signature.
I use a validator component for all my general validators
#Name("validator")
#Scope(ScopeType.EVENT)
#BypassInterceptors
public class Validator {
public void positiveInteger(FacesContext context, UIComponent toValidate, Object value) {
String val = (String) value;
try {
int v = Integer.parseInt(val);
if (v < 0)
throw new NumberFormatException();
} catch (NumberFormatException e) {
((UIInput) toValidate).setValid(false);
FacesMessages.instance().addToControlFromResourceBundle(toValidate.getId(), "invalid.integer");
}
}
}
Now you can add the validator:
<h:inputText value="#{foo.bar}" required="true" validator="#{validator.positiveInteger}">
<s:validate/>
<h:inputText>
I have no idea about the Seam part, it might have different approaches for this, but in standard JSF, you normally define it as <validator> in faces-config.xml.
<validator>
<validator-id>roCountyValidator</validator-id>
<validator-class>validators.RoCountyValidator</validator-class>
</validator>
and use it as follows:
<h:inputText>
<f:validator validatorId="roCountyValidator" />
</h:inputText>
Solution found:).
Forget about taglibs and stuff!
Use it like:
<h:inputText id="someField" value="#{booking.creditCardName}"
required="true" label="County" validator="roCountyValidator">
<h:message for="someField"/>
</h:inputText>
Please remark that
validator="roCountyValidator"
it shouldn't be used like EL expression !!! (my first wrong decision)
So the advantage of using Seam + #Validator: Seam will transform that component in the background to a jsf validator so you do no longer need jsf validator tags or any other configuration in faces-config.xml.
I have the following exception at the time of running JSF program.
org.apache.jasper.JasperException: An exception occurred processing JSP page /pages/general/internalServerErrorPage.jsp at line 44
41: <link rel="shortcut icon" href="<%=request.getContextPath()%>/resources/images/infomindzicon.ico" type="image/x-icon" />
42: </head>
43: <body id="sscmsMainBody">
44: <h:form id="internalServerErrorPageForm" binding="#{ServerErrorBean.initForm}">
45: <rich:page id="richPage" theme="#{LayoutSkinBean.layoutTheme}"
46: width="#{LayoutSkinBean.layoutScreenWidth}"
47: sidebarWidth="0">
Caused by: javax.servlet.ServletException: javax.servlet.jsp.JspException: java.lang.IllegalStateException: Parent was not null, but this component not related
at org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:858)
at org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:791)
at org.apache.jsp.pages.general.internalServerErrorPage_jsp._jspService(internalServerErrorPage_jsp.java:207)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:377)
What is the meaning of this exception and how can I resolve this?
Update: My code is below,
public HtmlForm getInitForm() {
validateSession();
return initForm;
}
The validate session method is
private void validateSession() {
HttpSession session = null;
try {
FacesContext facesContext = FacesContext.getCurrentInstance();
actionPanelRendered = false;
if (facesContext != null) {
session = (HttpSession) facesContext.getExternalContext().getSession(false);
if (session != null) {
if (session.getAttribute(SessionAttributes.USER_LOGIN_NAME.getName()) != null) {
actionPanelRendered = true;
}
}
}
} catch(Exception e) {
logger.info("Exception arise in server error bean");
e.printStackTrace();
}
}
It's thus coming from the following line:
<h:form id="internalServerErrorPageForm" binding="#{ServerErrorBean.initForm}">
You've bound the form to the bean for some unknown reason. The exception indicates that this component has a parent, but that this is actually not a parent at all as per the component tree in the JSP page. This in turn indicates that you're doing something like the following in the bean before or during the call of getInitForm() method:
form.setParent(someComponent);
If this is true, then you should remove this line.
Update: another possible cause is that you're forgotten to put a <f:view> around the HTML with the JSF components.
Update 2: one more cause is that you're binding multiple and physically different <h:form> components to one and same bean property. They should each be bound to their own unique property (or in this particular case, not be bound at all, this can be done better, see below).
Unrelated to the problem, as to your validateSession method, the entire method can be simplified to the following single EL expression in the view:
rendered="#{not empty user.name}"
assuming that SessionAttributes.USER_LOGIN_NAME equals to user.