I am using struts 2.2.3 in web application. I want to use struts2 annotations based validations for the form data submitted from UI. The scenario is:
User fills all the form fields and click on submit button.
I have created a Person class for storing registration form data and RegistrationAction which triggers the logic for registration. RegistrationAction holds reference to person object with respected getters/setters.
Please suggest how to validate individual fields of Person class after form submission, using struts 2 annotations.
Thanks.
Try to make it using the fieldName property of the Validations annotation. Something like the following:
#Validations(
requiredFields =
{#RequiredFieldValidator(type = ValidatorType.SIMPLE, fieldName = "person.name", message = "You must enter a value name.")}
)
Please refer the below link for further reference:
Struts2 Validation-annotation
On the setter method use
#RequiredFieldValidator(type=ValidatorType.FIELD, message="your message here")
#Validator of #Validations(...) not necessary
Have you tried the Struts2 Validation Annotation.Its quite simple and Straight forward all you need is to define the #Validation() annotation at Class level and Apply standard or custom annotations as per your use-case.
Refer official Annotation based Validation document.
Validation-Annotation
You mention a separate Person class, so I am guessing that this is a model-driven Action or using a function like setPerson in the Action class. If you want to validate the individual fields within Person, you will need to use a VisitorFieldValidator in the relevant Action method, and then put field validations on the Person object itself.
For example in the Action
#VisitorFieldValidator(message = "")
public void setPerson(Person person) {
this.person = person;
}
and in Person
#RequiredFieldValidator(message = "Last name is required.")
public void setLastName(String lastName) {
this.lastName = lastName;
}
Related
When you generate grails views, grails looks at your relationships and generates the right html for your form data to be automatically binded to the back end domain. For one to one associations grails creates a drop down list.
However, you might not want to present that property as a drop down list but something more custom (for example a text field with autocomplete). As soon as you do that the value that comes to the controller from that field, comes in as a String and you have to first:
Clear errors
Perform a findBy based on a given param and assign it to the property of the domain
I really want to avoid doing findBys in the controller as much as possible because it seems like I am doing logic/things that should not go there. The controller should delegate to the Service layer. It is not clear to me from the grails documentation how would I do that by using bindData which seems to work really well with String, date, Integer properties etc.. but I do not see how bindData is used for properties that are other domains.
I also really want to avoid passing the params object to the Service layer as it seems less reusable (or maybe not, correct me if I am wrong). I guess that I do not like how it looks semantically. I would prefer the first over the second:
#Transactional
class WithdrawService {
def addWithdraw(Withdraw withdraw) {
//perform business logic here
}
def createWithdraw(Map params){
//perform business logic here
}
}
Let's take the following example:
class Withdraw {
Person person
Date withdrawDate
}
and the parent lookup table
class Person {
String name
String lastName
static constraints = {
}
#Override
public String toString() {
return "$name $lastName"
}
}
In order for the bind to happen automatically without any extra work grails passes in the following request params to automatically bind the one to one:
person.id
a person map with the id.
[person.id:2, person:[id:2], withdrawDate:date.struct, withdrawDate_month:11, create:Create, withdrawDate_year:2015, withdrawDate_day:10, action:save, format:null, controller:withdraw]
What is the best way to go about this?
Pass two hidden fields that look exactly like this: person.id:2, person:[id:2] that get populated as a result of the Ajax call that populates the autocomplete?
In the controller do a Person.findBySomeKnownProperty(params.someKnownValue)
Or any other approach?
I'm beginner in Grails and I have a problem when I try to save a POGO
I have created 1 domain class
class Book {
String title
}
Then, I have generated the controller and view automatically.
Now, I want to be able to create a book with the code by clicking "create" (I know it is possible directly with the code generated but for my example I want to do it by the code). To do this, I have modified the method 'save(Book bookInstance)' in the controller like this
#Transactional
def save(Book bookInstance) {
def book = new Book(title:"New Grails Book").save()
But, when I go to the URL localhost:8080/myApp/book/create and then I click "Create", I have the error
message -> /myApp/WEB-INF/grails-app/views/book/save.jsp
description -> The requested resource is not available.
When I put this code in bootStrap, it is OK, so I don't understand why it is not in the controller
When you have a hasMany property in a domain class, Grails adds a Set property to the domain class with an AST transformation (so it's actually there in the bytecode, and it's visiable to Java) to represent the collection, and when you add a belongsTo a field of that type is added. So it's as if you had this code:
class Author {
Set<Book> books
static hasMany = [books: Book]
String name
}
and
class Book {
Author author
static belongsTo = [author: Author]
String title
}
The AST xform uses the map key as the field name, so you can use any valid field name, but the convention is to do what you did.
Properties are nullable:false by default, so your code doesn't save the Book instance because you didn't set the author property. When doing this explicitly you typically don't create the Book directly, but instead add it to the Author's collection using the dynamic addToBooks method. This sets the author field back-reference and when you save the author, the book is transitively validated and saved. This is all handled for you when you have code like new Book(params).save(), and you can do it directly, e.g.
Author author = ...
def book = new Book(title:"New Grails Book", author: author).save()
If you're using a generated controller and GSPs, there should be an author id in the params map, it'll likely be author.id, so that first line would be
Author author = Author.get(params['author.id'])
but you can add
println params
at the top of the action method to see all of the submitted params.
In general you don't want to look at the return value of the save call, since it will be null if there's a validation error and there's no way to retrieve the errors. So change
def book = new Book(...).save()
to
def book = new Book(...)
book.save()
and now you can call book.hasErrors(), book.getErrors(), book.errors, etc. to see if it was successful and if not, what went wrong.
But that's not the exact problem you're seeing, just one you will when you fix your problem. There's no save.gsp, and Grails also looks for save.jsp and confusingly includes that name in the not-found message. The save method is accessed via a POST request, typically from the form generated by the create action, and it either re-displays create.gsp with the submitted data and error messages when validation fails, or redirects to the view action when the save succeeds. There's no need for a save.gsp when using the generated code.
I have a User class with multiple string properties, all of them required. The properties are used for different actions, like Create and Update.
In my form, on create action, i am using only a part of these properties, and, because of this, the ModelState is invalid.
Is there a way to specify to the ModelState that it should validate only the properties that are included in the POST data (inside the form) ? So the missing properties are ignored?
You can create different models for user creation and other actions with different sets of validation attributes.
Yea, you should create different view models for each specific action method ( if they have specific requirements ).
You can use the RequiredIf attribute from Foolproof to achieve this:
using Foolproof;
[RequiredIf("Tab", "Information")]
public bool UW_AgentCreditReportsAknowlegement { get; set; }
Just use one of the attributes and set the appropriate condition.
I am using MVC3 and in certain locations in the code I am using the System.ComponentModel.DataAnnotations.DataType.EmailAddress attribute and letting MVCs Model validation do the validation for me.
However, I would now like to validate an email address in a different section of code where I am not using a model. I would like to use the same method that is already being used by MVC, however I was unable to find any information on how to do so.
EDIT - Sorry if my question was unclear. I will attempt to clarify.
Here is a snippet from the RegisterModel that is included with the default MVC template:
public class RegisterModel
{
...
[Required]
[DataType(DataType.EmailAddress)]
[DisplayName("Email address")]
public string Email { get; set; }
...
}
These attributes instruct mvcs model validation on how to validate this model.
However, I have a string that should contain an email address. I would like to validate the email address the same way that mvc is doing it.
string email = "noone#nowhere.com";
bool isValid = SomeMethodForValidatingTheEmailAddressTheSameWayMVCDoes(email);
As others have said, the DataType attribute doesn't actually do any validation. I would recommend you to look at Data Annotations Extensions which includes already written validation extensions for a variety of things, including Email.
It is also possible to do model validation on your full model explicitly: Manual Validation with Data Annotations.
If you want to do per attribute validation for a specific field/property, you can also look at the tests for DataAnnotationExtensions which should give you what you want:
[TestMethod]
public void IsValidTests()
{
var attribute = new EmailAttribute();
Assert.IsTrue(attribute.IsValid(null)); // Don't check for required
Assert.IsTrue(attribute.IsValid("foo#bar.com"));
..
}
Have a look at this blog post by Scott Guthrie, which shows how to implement validation of an email address using a custom attribute (based on the RegularExpressionAttribute).
You can reuse that logic if you need to validate the email address somewhere else.
You may want to look at this question: Is the DataTypeAttribute validation working in MVC2?
To summarize, [DataType(DataType.EmailAddress)] doesn't actually validate anything, it just says "hey, this property is supposed to be an e-mail address". Methods like Html.DisplayFor() will check for this and render it as foo, but the IsValid() method is pretty much a simple return true;.
You'll have to roll your own code to actually perform validation. The question linked above has some sample code you can use as a starting point.
I have a class set up to hold values on a registration form (VB.NET, MVC), and among the properties is a Password property:
Public Class RegisterModel
...
Private _password As String
<DisplayName("Password:"), Required(), ValidatePasswordLength(), DataType(DataType.Password)> _
Public Property Password() As String
Get
Return _password
End Get
Set(ByVal value As String)
_password = value
End Set
End Property
This works great when registering a new user, but I'd like to use the same class to update existing users. (Note: this app is run by an admin who is in charge of registering individuals and assigning passwords.) The way I'd like it to behave is if the admin leaves the password blank, then the password is not changed, but the rest of the information is. If I use this class, the password can't be left blank because it fails on the Required() and ValidatePasswordLength() calls.
Is there a way to use this class but tell the model to ignore these particular validations? Even if I leave the password field off my edit form, it still fails. Do I need to create a whole duplicate class without these restrictions on the password field? There must be a better way.
You could implement IDataErrorInfo and have a flag set on the model which indicates whether it is being used by an admin or not - you could then validate conditionally.
But overall, I'd say this is a bit of a code smell. You're using a model for two different, incompatible purposes. It'd be better to use a separate view model.
I'd recommend using the FluentValidation library. It's a fantastic way to separate the concerns of your view (view model) and the actual validation you want to perform. You could pass parameters into it to drive different behavior. Check out When/Unless conditions or just writing completely custom validation methods with the Must operator.
public class RegisterModelValidator: AbstractValidator<RegisterModel>
{
public RegisterModelValidator(bool isAdmin)
{
RuleFor(x => x.Password).NotEmpty().Unless(isAdmin);
...
}
}
As long as your view model would have identical properties in both scenarios, you should use the one view model and one validation class. If the model varies at all I'd use two view models as David recommends.
You can do this in 2 ways:
1: add the [ValidateInput(false )] attribute to the action
or
2: Add a new property to the Register Model
public bool IsNewUser {get;}
3: Create a new class level attribute that takes IsNewUser into account when validating