[jboss-user] [JBoss Seam] - NPE in Expressions.java doing model validation
matt.drees
do-not-reply at jboss.com
Fri Feb 23 17:40:28 EST 2007
My app needs to render a list of questions whose type is database-driven. I'm using a few facelets TagHandlers to accomplish this. The view looks like this:
| <s:validateAll>
|
| <f:facet name="aroundInvalidField">
| <s:span styleClass="errors"/>
| </f:facet>
|
| <h:panelGrid id="questionPanel" columns="3">
|
| <crs:customQuestions
| registrationType="#{registrationType}"
| questionTextVar="questionText"
| questionNumberVar="i"
| requiredVar="required">
|
|
| <h:outputLabel for="answerInput#{i}" value="#{i}" id="questionNumber#{i}"/>
|
| <s:formattedText value="#{questionText}" id="questionText#{i}"/>
|
| <h:panelGroup>
| <s:decorate>
| <crs:isText>
| <h:inputText id="answerInput#{i}"
| value="#{registrationProcess.pageAnswers[ i].valueString}"
| required="#{required}">
| <a:support event="onblur" reRender="questionErrors#{i}"/>
| </h:inputText>
| </crs:isText>
|
| <crs:isDate>
| <h:inputText id="answerInput#{i}"
| value="#{registrationProcess.pageAnswers[ i].valueDate}"
| required="#{required}">
| <s:convertDateTime pattern="MM/dd/yyyy"/>
| <a:support event="onblur" reRender="questionErrors#{i}"/>
| </h:inputText>
| <s:selectDate for="answerInput#{i}">
| <h:graphicImage url="img/dtpick.gif" style="margin-left:5px"/>
| </s:selectDate>
| </crs:isDate>
|
| <crs:isBoolean>
| <h:selectBooleanCheckbox
| id="answerInput#{i}"
| value="#{registrationProcess.pageAnswers[ i].valueBoolean}"
| required="${required}"/>
| </crs:isBoolean>
|
| <br clear="none"/>
| <a:outputPanel id="questionErrors#{i}">
| <s:message/>
| </a:outputPanel>
| </s:decorate>
| </h:panelGroup>
|
| </crs:customQuestions>
| </h:panelGrid>
| </s:validateAll>
|
And the main taghandler (which I modeled after facelets' ForEachHandler) looks like this:
| public class CustomQuestionTagHandler extends TagHandler {
|
| private final TagAttribute registrationType;
| private final TagAttribute questionTextVar;
| private final TagAttribute questionNumberVar;
| private final TagAttribute requiredVar;
|
| public CustomQuestionTagHandler(TagConfig config) {
| super(config);
| registrationType = getRequiredAttribute("registrationType");
| questionTextVar = getRequiredAttribute("questionTextVar");
| questionNumberVar = getRequiredAttribute("questionNumberVar");
| requiredVar = getRequiredAttribute("requiredVar");
| }
|
| @SuppressWarnings("unchecked")
| public void apply(FaceletContext faceletContext, UIComponent parent) throws IOException, FacesException,
| FaceletException, ELException {
| RegistrationType registrationType = (RegistrationType) this.registrationType.getObject(faceletContext,
| RegistrationType.class);
| assert registrationType != null;
| List<QuestionUsage> questionUsages = registrationType.getQuestionUsages();
| assert questionUsages != null;
|
| String questionTextVar = this.questionTextVar.getValue(faceletContext);
| String questionNumberVar = this.questionNumberVar.getValue(faceletContext);
| String requiredVar = this.requiredVar.getValue(faceletContext);
|
| VariableMapper variables = faceletContext.getVariableMapper();
|
| int i = 1;
| for (QuestionUsage questionUsage : questionUsages) {
| Question question = questionUsage.getQuestion();
| Integer questionNumber = new Integer(i);
|
| ValueExpression questionNumberValueExpression = faceletContext.getExpressionFactory()
| .createValueExpression(questionNumber, Integer.class);
| variables.setVariable(questionNumberVar, questionNumberValueExpression);
|
| ValueExpression questionTextValueExpression = faceletContext.getExpressionFactory().createValueExpression(
| question.getText(), String.class);
| variables.setVariable(questionTextVar, questionTextValueExpression);
|
| Boolean required = questionUsage.isRequired();
| variables.setVariable(requiredVar, faceletContext.getExpressionFactory().createValueExpression(required,
| Boolean.class));
|
|
| faceletContext.setAttribute("questionType", question.getType());
|
| // execute body
| this.nextHandler.apply(faceletContext, parent);
|
| i++;
| }
| }
|
| }
|
This renders fine. But during the onblur ajax validation check, this occurs:
| java.lang.NullPointerException
| at org.jboss.seam.core.Expressions.getValidator(Expressions.java:198)
| at org.jboss.seam.core.Expressions.validate(Expressions.java:182)
| at org.jboss.seam.ui.ModelValidator.validate(ModelValidator.java:25)
| at javax.faces.component._ComponentUtils.callValidators(_ComponentUtils.java:157)
| at javax.faces.component.UIInput.validateValue(UIInput.java:312)
| at javax.faces.component.UIInput.validate(UIInput.java:353)
| at javax.faces.component.UIInput.processValidators(UIInput.java:183)
| at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:624)
| at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:624)
| at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:624)
| at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:624)
| at javax.faces.component.UIForm.processValidators(UIForm.java:70)
| at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:624)
| at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:146)
| at org.ajax4jsf.framework.ajax.AjaxViewRoot.processValidators(AjaxViewRoot.java:389)
| ...
|
It appears that Expressions.validate(...) is trying to evaluate #{registrationProcess.pageAnswers[ i].valueString}, which returns null.
I don't know enough about EL to know why. I suspect either I can't use model validation this way, or I need to do something special in my TagHandler. Does anyone have any recommendations?
Also, a null-check should probably be put in Expressions.java (line 198ish) before calling getValidator().
Thanks!
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4021364#4021364
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4021364
More information about the jboss-user
mailing list