Do you think IIT Guwahati certified course can help you in your career?
No
Introduction
Form validation is the process through which an online form determines if the data entered by a user is accurate or not. Either the form will alarm the user that they made a mistake and must correct it before continuing, or the form will be verified, and the user will be able to finish the registration process. We will discover how to complete this task using the Play framework in this blog.
Handling form submission
Enabling/Disabling the forms module
By default, Play has the Java forms module (play-java-forms) when enabling the PlayJava sbt plugin, so there is nothing to enable if you already contain enablePlugins(PlayJava) on your project.
The forms module is also in PlayImport as javaForms, which can be used with libraryDependencies += javaForms in your build.sbt.
Defining a form
The play.data package have several helpers to handle HTTP form data submission and validation. The simplest way to handle a form submission is to define a play.data.Form that wraps an existing class:
import play.libs.Files.TemporaryFile;
import play.mvc.Http.MultipartFormData.FilePart;
public class User {
protected String email;
protected String password;
protected FilePart<TemporaryFile> profilePicture;
public void setEmail(String email) {
this.email = email;
}
public String getEmail() {
return email;
}
public void setPassword(String password) {
this.password = password;
}
public String getPassword() {
return password;
}
public FilePart<TemporaryFile> getProfilePicture() {
return profilePicture;
}
public void setProfilePicture(FilePart<TemporaryFile> pic) {
this.profilePicture = pic;
}
}
You can also try this code with Online Java Compiler
Play’s built-in validation module uses Hibernate Validator under the hood. This means we can take advantage of features defined in the JSR-380 (Bean Validation 2.0).
Cross-field validation
To check the state of an entire object, we can use class-level constraints.
To free us from the burden of implementing your class-level constraint(s), Play out-of-the-box already gives a generic implementation of such constraints, which should cover at least the most common use cases.
Now let us see how this works:
To define an ad-hoc validation, all we need to do is annotate our form class with Play's class-level constraint (@Validate) and implement the corresponding interface ( Validatable<String>) - which forces you to override a validate method:
import play.data.validation.Constraints;
import play.data.validation.Constraints.Validate;
import play.data.validation.Constraints.Validatable;
@Validate
public class User implements Validatable<String> {
@Constraints.Required protected String email;
protected String password;
@Override
public String validate() {
if (authenticate(email, password) == null) {
// You could also return a key defined in conf/messages
return "Invalid email or password";
}
return null;
}
// getters and setters
You can also try this code with Online Java Compiler
The message returned in the above example will become a global error. Errors are defined as play.data.validation.ValidationError.
Also be aware that in this example the validate method and the @Constraints.Required constraint will be called simultaneously - so the validate method will be called no matter if @Constraints.Required was successful or not (and vice versa). You will learn how to introduce an order later on.
As you can see the Validatable<T> interface takes a type parameter which determines the return type of the validate() method.
So depending if you want to be able to add a single global error, one error (which could be global as well) or multiple (maybe global) errors to a form via validate(), you have to use either a String, a ValidationError or a List<ValidationError> as type argument. Any other return types of the validate method will be ignored by Play.
If validation passes inside a validate() method you must return null or an empty List. Returning any other non-null value (including empty string) is treated as failed validation.
Returning a ValidationError object may be useful when you have additional validations for a specific field:
import play.data.validation.Constraints.Validate;
import play.data.validation.Constraints.Validatable;
import play.data.validation.ValidationError;
@Validate
public static class LoginForm implements Validatable<ValidationError> {
// fields, getters, setters, etc.
@Override
public ValidationError validate() {
if (authenticate(email, password) == null) {
// Error will be displayed for the email field:
return new ValidationError("email", "Invalid credentials");
}
return null;
}
}
You can also try this code with Online Java Compiler
There may be situations where you just want to validate a subset of the restrictions when a user submits a form. Consider a UI wizard, for instance, where a specific subset of constraints should be validated at each step.
Or consider the registration and login procedures for an online application. The user should typically submit both a password and an email address for both processes. As a result, these procedures would call for nearly identical forms, with the exception that throughout the sign-up process, the user must additionally confirm their password. Let's say, for the sake of argument, that a user can additionally modify his user information on a settings page while already logged in, which would require a third form.
Since you would already be using the same constraint annotations for most of the form fields, using three different forms in this situation isn't a good idea. What happens if you set a name field's maximum length constraint to 255 but then decide you want a 100-character limit? This would need to be modified for each form. This would be a mistake-prone situation if you forgot to update one of the forms, as you could expect.
Fortunately, we can easily group restrictions:
import play.data.validation.Constraints;
import play.data.validation.Constraints.Validate;
import play.data.validation.Constraints.Validatable;
import play.data.validation.ValidationError;
import javax.validation.groups.Default;
@Validate(groups = {SignUpCheck.class})
public class PartialUserForm implements Validatable<ValidationError> {
@Constraints.Required(groups = {Default.class, SignUpCheck.class, LoginCheck.class})
@Constraints.Email(groups = {Default.class, SignUpCheck.class})
private String email;
@Constraints.Required private String firstName;
@Constraints.Required private String lastName;
@Constraints.Required(groups = {SignUpCheck.class, LoginCheck.class})
private String password;
@Constraints.Required(groups = {SignUpCheck.class})
private String repeatPassword;
@Override
public ValidationError validate() {
if (!checkPasswords(password, repeatPassword)) {
return new ValidationError("repeatPassword", "Passwords do not match");
}
return null;
}
// getters and setters
You can also try this code with Online Java Compiler
A security flaw known as cross-site request forgery (CSRF) allows an attacker to mislead a victim's browser into sending a request while the victim is still logged in to the site. Since the session token is provided with every request, an attacker can initiate requests on behalf of the victim if they can force the browser to do so.
Play’s CSRF protection
Play supports multiple methods for verifying that a request is not a CSRF request. The primary mechanism is a CSRF token. This token gets placed either in the query string or body of every form submitted, and also gets placed in the users session. Play then verifies that both tokens are present and match.
To allow simple protection for non browser requests, Play checks requests with Cookie or Authorization headers by default. You can configure play.filters.csrf.header.protectHeaders to define headers that must be present to perform the CSRF check. If you are making requests with AJAX, you can place the CSRF token in the HTML page, and then add it to the request using the Csrf-Token header.
Applying a global CSRF filter
Play provides a global CSRF filter that can be used for all requests. This is the easiest way to add CSRF protection to an application. To include the filter manually, add it to the application.conf:
Global CSRF filtering may not always be suitable, such as when a program wants to let some cross-origin form submissions. Some non-session-based protocols, including OpenID 2.0, require form submission in server-to-server RPC connections or cross-site form posting.
In these cases, Play provides 2 actions that can be composed with your applications actions.
@RequireCSRFCheck
public Result save() {
// Handle body
return ok();
}
You can also try this code with Online Java Compiler
Play provides several helpers to help you render form fields in HTML templates.
Creating a <form> tag
The first helper creates the <form> tag. It is a pretty simple helper that automatically sets the action and method tag parameters according to the reverse route you pass in:
There are many input helpers in views.html.helper package. You give them a form field, and they display the corresponding HTML form control, with a populated value, constraints, and errors:
Open-source web application framework, Play Framework uses the model-view-controller design principle. It was created in Scala and may be used with other programming languages, such as Java, that are compiled to JVM bytecode.
How do you run a Play project?
Pick Open from the welcome screen. Alternately, choose File, then Open from the main menu.
Find your project in the window that appears, click Open, then, if it's a sbt project, pick the build sbt file.
Click Open as Project in the dialogue box that appears.
How do I validate a form before submitting it?
To validate a form before submitting it, follow the below steps,
Call each function to validate email, username, password, and confirm password fields.
Use the && operator to check if the form is valid. The form is valid only if every field is valid.
At last, submit data to the server if the form validifies the isFormValid flag.
Conclusion
In this blog, we discussed the Java form submission and validation. We have used the play framework for this purpose. We learned about different types of handling methods, protection against CSRF, and working with template helpers. In the end, we saw some advanced concepts of handling forms.