[JBoss Seam] - Re: Feature request - @InOut
by andrew.rw.robinson
I find things defined in XML files to be very hard to maintain and try to stay away from them and use annotations instead. Also putting variables not tied to beans into the request scope also makes it hard to maintain -- as it is hard to determine what bean put them there. I like to "bean qualify" all my EL expressions so it is simple to find the bean and the property that is being used. Also in a large application, it would be a bit of a challenge to ensure unique EL names if many bean properties suddenly became available in the root EL context.
For small applications like those examples seam provides, it is fine, but when you may have hundreds of backing beans and views, it gets a lot harder.
So the reason is so that I can keep the properties of a bean inside that bean and manage the life-cycle of those properties from within that bean (basically encapsulation).
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4021365#4021365
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4021365
19Â years, 2Â months
[JBoss Seam] - NPE in Expressions.java doing model validation
by matt.drees
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
19Â years, 2Â months