[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