Dynamic fielderror struts2 validation - validation

i'm dynamically generating fields (from a hashmap):
<s:iterator value="app.fields" status="field">
<s:set name="findex" value="%{'app.fields[' + #field.index + '].id'}"/>
<s:fielderror value="%{#findex}"/>
<s:textfield name="%{#findex}" />
</s:iterator>
This method sets up the textfield ok:
<input type="text" id="saveapp_app_fields_1__id" value="[DE]Enter an ID" name="app.fields[1].id">
but not the fielderror.
I add the fielderrors manually in the validate method. but all field errors get displayed n times for each fielderror tag. wich implies that what is actually happening is that the #findex seems to evaluate to null and i'm adding n <fielderror/> tags.
I could extract the field errors manulally in the jsp but was hoping for a more elegant solution.
Thanks in advance. Michael.

I've never seen a fielderror declared in that way. Perhaps try:
<s:fielderror>
<s:param value="%{#findex}" />
</s:fielderror>

Related

How can I use Java's constants value as th:value name?

I have a constant for a name.
public static final NAME_SOME = "some"
In my html I tried,
<input th:value="${T(the.package.TheClass).NAME_SOME}"/>
I expected the actual value from the model named by some.
Yet I see value=some.
How can I fix this?
It's a bit unclear what you're asking. The expression <input th:value="${T(the.package.TheClass).NAME_SOME}" /> should indeed evaluate to <input value="some" />. You mean you have a form with a model object and you want to bind it to the expression model.some? You can use preprocessing to do that, I think...
<input th:field="*{__${T(the.package.TheClass).NAME_SOME}__}" />

How to customize Hibernate #Size error message to indicate length of entered field

I would like to customize the error message for text fields to include the actual number of characters that were entered. I've been able to get this to work but am not satisfied with my solution, so I'm wondering what others have done to accomplish this.
Spring 4.1.2
Hibernate 4.3.10
Hibernate Validator 5.1.3
Field Annotation (limited to 10 for testing purposes - actual size is 150)
#Column(name = "NAME", nullable = false)
#Size(max=10)
private String name;
message.properties
Size.person.name=Maximum is {1} characters
JSP code
<spring:bind path="person.name">
<c:set var="nameError">${status.errorMessage}</c:set>
<c:set var="nameDisplayValue">${status.displayValue}</c:set>
<c:set var="nameCode">${status.errorCode}</c:set>
</spring:bind>
<c:if test="${fn:contains(nameCode,'Size')}">
<c:set var="nameLen">${fn:length(nameDisplayValue)}</c:set>
<c:if test="${nameLen gt 0}">
<c:set var="nameError">${nameError += " (you entered " += nameLen += ")"}</c:set>
</c:if>
</c:if>
<div class="form-group col-sm-9 <c:if test="${not empty nameError}">has-error</c:if>">
<label class="control-label" id="nameLabel" for="inputName">Name:<c:if test="${not empty nameError}"> ${nameError}</c:if></label>
<form:input type="text" size="10" class="form-control" id="inputName" placeholder="Name" path="name" autocomplete="off"/>
</div>
Output
This is ok for one field, but the form I'm working on has more than 10 fields that have size validation. Also, the size="10" setting for form:input does not appear to actually do anything, i.e., you can still enter more than 10 characters.
I know one option is to write a custom validator but that seems like overkill for what I want to do. Another would be to catch the error before the form is posted, but I'm trying to keep all of the validation server-side. Any suggestions would be greatly appreciated.
There is a good documentation about interpolating validation messages in the Hibernate documentation: Chapter 4. Interpolating constraint error messages.
If you create a file ValidationMessages.properties in the root of your classpath then you can change all validation messages there:
javax.validation.constraints.Size.message=Please enter at least {min} and at most {max} characters.
The parameters in {...} are just the attribute names of the annotation. That works for nearly every constraint. If you want to reference the validated value, you can use {validatedValue}. You can as well use Formatter to format the value:
... ${formatter.format('...', validatedValue)} ...
Unfortunately there is no format string for length.
So if you really want to have such a message for all #Size, then you will have to implement your own javax.validation.MessageInterpolator (see Custom message interpolation in the link above).
Additional remark: There is a side effect when changing the default validation message: #Size is available for collections as well. And in that case at least my message is not appropriate. I usually create a second validation message for this:
javax.validation.constraints.Size.Collection.message=Please select at least {min} and at most {max} elements.
And use that one in the constraint:
public final class ValidationMessages {
public static final String COLLECTION_SIZE =
"javax.validation.constraints.Size.Collection.message";
}
public class MyClass {
#Size(min = 1, max = 10, message = ValidationMessages.COLLECTION_SIZE)
private Collection<String> elements;
}
With a matching rule in my code style tool I ensure that I don't forget to define the message for #Size annotations on collections.

Validation across multiple fields in JSF/PrimeFaces

I need to validate across multiple fields in such a way that validation should be violated only when one of the given fields is violated.
It is distinct from cross field validation in which a value of one field is dependent upon the value(s) of one or more of the rest of the fields.
Given below a simple scenario.
<p:inputText id="txt1" value="#{testBean.txt1}" required="false" maxlength="45"/>
<p:inputText id="txt2" value="#{testBean.txt2}" required="false" maxlength="45"/>
<p:inputText id="txt3" value="#{testBean.txt3}" required="false" maxlength="45"/>
<p:commandButton id="btnSubmit" actionListener="#{testBean.insert}"
icon="ui-icon-check" value="Save"/>
In which, validation violation should be occurred only when one of the given three text fields is left blank. If anyone of them is filled with a value then, all should be validated. In which case, validation should not be violated.
How to proceed with this scenario? Does JSF/PrimeFaces provide some way to perform validation in this way?
I have a hard time in wrapping my head around your concrete functional requirement, but I believe you're looking for "all or none" validation. I.e. either all fields should be blank, or all fields should be filled. JSF utility library OmniFaces has a validator for exactly this purpose, the <o:validateAllOrNone>.
Here's how you could use it:
<p:inputText id="txt1" value="#{testBean.txt1}" maxlength="45" />
<p:inputText id="txt2" value="#{testBean.txt2}" maxlength="45" />
<p:inputText id="txt3" value="#{testBean.txt3}" maxlength="45" />
<o:validateAllOrNone components="txt1 txt2 txt3" />
Of course!
Primefaces provide a lot of ways that can satisfact you. First of all, you can make validations in your MBean method. In your case, you're calling insert method, so you can do something like this:
public String insert(){
boolean error = false;
if(txt1.isEmpty()){
error = true;
}
if(txt2.isEmpty()){
error = true;
}
if(txt3.isEmpty()){
error = true;
}
if(error == true){
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN,"Empty fields!", "Insert something in at least one input!"));
return null;
}else{
return "myPage"
}
}
Note that you can improve the validations by yourself, following your needs. You can also change the message from:
FacesMessage.SEVERITY_WARN
to:
FacesMessage.SEVERITY_INFO
FacesMessage.SEVERITY_ERROR
FacesMessage.SEVERITY_FATAL
What can give your application a better error message.
Before this works, add this above your input fields:
<p:messages id="messages" showDetail="true" autoUpdate="true" closable="true" />
Probably this will work like a charm! If you're interested, check the Primefaces Messages showcase, where you can find some examples and understand better how <p:messages> works. Also, feel free to check <p:growl>, that in my opinion is a lot better than simple messages. Check out the growl here.
Hope I helped you (:

spring:bind error using in a List

I have a list containing users. I am trying to print it in JSP but some how I am not able to get it to print it. Getting this exception HTTP Status 500 - javax.servlet.ServletException: javax.servlet.jsp.JspTagException: Neither BindingResult nor plain target object for bean name 'users[0]' available as request attribute
Code in JSP
<c:forEach items="${users}" var="user" varStatus="status">
<spring:bind path="users[${status.index}].name">
<c:out value="${status.value}" />
</spring:bind>
</c:forEach>
Controller
ModelAndView modelAndView = new ModelAndView("go_some_JSP_page");
List<UserEntity> users = userManager.getAllObjects();
modelAndView.addObject("users", users);
BTW, UserEntity has name field. If I remove the binding and try to print the user.name using <c:out value="user.name" /> it prints the value
Where am I going wrong and what do I need to do? Thanks
Not working code below. [I have to invoke formatting on field #NumberFormat so have to try it using status variable]
<spring:bind path="user.name">
<c:out value="${status.value}" />
</spring:bind>
Gets this error --> javax.servlet.ServletException: javax.servlet.jsp.JspTagException: Neither BindingResult nor plain target object for bean name 'user' available as request attribute
So added a bean binding and then I get empty table :(. I believe thats because the instance is empty. So this does not seems like a right approach.
#ModelAttribute("user")
public UserEntity userEntityBinding() {
return UserEntity.newInstance();
}
A working code exists at https://github.com/hth/StatusInvoke.git
Let me know if you face any problem deploying it.
This question has been solved. Thanks for looking at it.
You can try using LazyList instead of simple list. If you want to take a look at the example then you can refer one of my question. In the question statement I have mentioned how to use the LazyList.
Hope that helps you. Cheers.
this, if the modelandview are returned, is the correct way to populate the list
ModelAndView modelAndView = new ModelAndView("go_some_JSP_page");
List<UserEntity> users = userManager.getAllObjects();
modelAndView.addObject("users", users);
And this is the correct way to reference the list
<c:forEach items="${users}" var="user" varStatus="status">
<spring:bind path="user.name">
<c:out value="${status.value}" />
</spring:bind>
</c:forEach>
Your problem must be elsewhere is the name field definitely populated, is the correct jsp being called... the above code is correct and should work.
The correct answer to invoke #NumberFormat annotation is by using spring:eval expression tag
<spring:eval expression="user.balance" />
This invokes the annotation and performs formatting as mentioned in the annotation
I don't think you can use spring:bind in that case, AFAIK it tries to get the variable from the ModelMap, it's not able to get it from the "for" var.

Ajax.BeginForm with Collection

Isn't that possible to use "Ajax.BeginForm" in a collection model? Form repeats itself, Html elements are rendered correctly, values are ok. However, all parameters going through action are being null.
I've realized that, it posts like that:
ProductList[0].Id 501
ProductList[0].quantity 1
However it should be like
Id 501
quantity 1
Any Ideas?
You should use prefix in UpdateModel function:
UpdateModel(MyModel, "MyModel")
I solved by using pure html, thanks anyway.
<input type="hidden" value="#Model.Id" name="Id"/>
<input type="text" value="" name="quantity"/>

Resources