CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-typesafe-play--play-java

Java API for the Play Framework providing web application development capabilities including form handling, validation, dependency injection, and utility libraries

Pending
Overview
Eval results
Files

form-processing.mddocs/

Form Processing

Play Framework's form processing capabilities provide comprehensive support for handling HTML forms, data binding, and form field management. The system supports both dynamic forms for unstructured data and typed forms for model binding with automatic type conversion.

Capabilities

Dynamic Form Handling

Dynamic forms handle unstructured form data using a HashMap-backed approach, ideal for forms with variable fields or when you don't have a predefined model.

/**
 * Dynamic form backed by HashMap for unstructured data binding
 */
public class DynamicForm extends Form<DynamicForm.Dynamic> {
    /** Create empty dynamic form */
    public DynamicForm();
    
    /** Create dynamic form with data and errors */
    public DynamicForm(Map<String,String> data, Map<String,List<ValidationError>> errors, Option<Dynamic> value);
    
    /** Get field value by key */
    public String get(String key);
    
    /** Get all form data as map */
    public Map<String, String> data();
    
    /** Fill form with existing data */
    public DynamicForm fill(Map value);
    
    /** Bind form from HTTP request */
    public DynamicForm bindFromRequest(String... allowedFields);
    
    /** Bind form from data map */
    public DynamicForm bind(Map<String,String> data, String... allowedFields);
    
    /** Get field wrapper by key */
    public Form.Field field(String key);
    
    /** Get validation error for field */
    public ValidationError error(String key);
    
    /** Add validation error */
    public void reject(String key, String error, List<Object> args);
    
    /** Convert key to dynamic form key format */
    static String asDynamicKey(String key);
    
    /** Convert dynamic form key to normal key format */
    static String asNormalKey(String key);
}

/**
 * Data structure for dynamic form data
 */
public static class DynamicForm.Dynamic {
    /** Default constructor */
    public Dynamic();
    
    /** Constructor with initial data */
    public Dynamic(Map data);
    
    /** Get underlying data map */
    public Map getData();
    
    /** Set data map */
    public void setData(Map data);
}

Usage Examples:

import play.data.Form;
import play.data.DynamicForm;

// Create and bind dynamic form
public Result handleContactForm() {
    DynamicForm contactForm = Form.form().bindFromRequest();
    
    if (contactForm.hasErrors()) {
        return badRequest(contactForm.errorsAsJson());
    }
    
    String name = contactForm.get("name");
    String email = contactForm.get("email");
    String message = contactForm.get("message");
    
    // Process form data
    return ok("Thank you " + name + "! We'll contact you at " + email);
}

// Pre-fill dynamic form
public Result editSettings() {
    Map<String, String> existingData = new HashMap<>();
    existingData.put("theme", "dark");
    existingData.put("language", "en");
    
    DynamicForm settingsForm = Form.form().fill(existingData);
    return ok(views.html.settings.render(settingsForm));
}

Typed Form Handling

Typed forms provide strong type safety by binding form data directly to Java model classes with automatic validation and type conversion.

/**
 * Helper to manage HTML form description, submission and validation
 */
public class Form<T> {
    /** Create dynamic form */
    public static DynamicForm form();
    
    /** Create typed form for given class */
    public static <T> Form<T> form(Class<T> clazz);
    
    /** Create named typed form */
    public static <T> Form<T> form(String name, Class<T> clazz);
    
    /** Create typed form with validation group */
    public static <T> Form<T> form(String name, Class<T> clazz, Class<?> group);
    
    /** Bind form from HTTP request */
    public Form<T> bindFromRequest(String... allowedFields);
    
    /** Bind form from HTTP request with explicit request object */
    public Form<T> bindFromRequest(Http.Request request, String... allowedFields);
    
    /** Bind form from request data map */
    public Form<T> bindFromRequest(Map<String,String[]> requestData, String... allowedFields);
    
    /** Bind form from data map */
    public Form<T> bind(Map<String,String> data, String... allowedFields);
    
    /** Bind form from JSON data */
    public Form<T> bind(com.fasterxml.jackson.databind.JsonNode data, String... allowedFields);
    
    /** Fill form with existing model instance */
    public Form<T> fill(T value);
    
    /** Get form data as string map */
    public Map<String,String> data();
    
    /** Get typed form value if no errors */
    public Option<T> value();
    
    /** Get form value, throws if errors exist */
    public T get();
    
    /** Check if form has any validation errors */
    public boolean hasErrors();
    
    /** Check if form has global (non-field) errors */
    public boolean hasGlobalErrors();
    
    /** Get all global errors */
    public List<ValidationError> globalErrors();
    
    /** Get single global error (null if none) */
    public ValidationError globalError();
    
    /** Get all validation errors */
    public Map<String,List<ValidationError>> errors();
    
    /** Get errors as JSON */
    public com.fasterxml.jackson.databind.JsonNode errorsAsJson();
    
    /** Get errors as JSON with specific language */
    public com.fasterxml.jackson.databind.JsonNode errorsAsJson(play.i18n.Lang lang);
    
    /** Get field wrapper by key */
    public Field field(String key);
    
    /** Get field wrapper by key (alias for field) */
    public Field apply(String key);
    
    /** Get form name */
    public String name();
    
    /** Discard errors and return clean form */
    public Form<T> discardErrors();
    
    /** Add global validation error */
    public void reject(String error);
    
    /** Add field-specific validation error */
    public void reject(String key, String error);
}

Usage Examples:

import play.data.Form;
import play.data.validation.Constraints.*;

// Model class with validation annotations
public class User {
    @Required
    @MinLength(2)
    public String name;
    
    @Required
    @Email
    public String email;
    
    @Min(18)
    public Integer age;
    
    public String bio;
}

// Controller using typed form
public class UserController extends Controller {
    
    public Result showCreateForm() {
        Form<User> userForm = Form.form(User.class);
        return ok(views.html.createUser.render(userForm));
    }
    
    public Result createUser() {
        Form<User> userForm = Form.form(User.class).bindFromRequest();
        
        if (userForm.hasErrors()) {
            return badRequest(views.html.createUser.render(userForm));
        }
        
        User user = userForm.get();
        // Save user to database
        userRepository.save(user);
        
        return redirect(routes.UserController.showUser(user.id));
    }
    
    public Result editUser(Long id) {
        User existingUser = userRepository.findById(id);
        Form<User> userForm = Form.form(User.class).fill(existingUser);
        return ok(views.html.editUser.render(userForm));
    }
}

Form Field Management

Form fields provide detailed access to field values, validation errors, and metadata.

/**
 * Represents a form field with value and validation information
 */
public static class Form.Field {
    /** Get field name */
    public String name();
    
    /** Get field value */
    public String value();
    
    /** Get field value or default if empty */
    public String valueOr(String or);
    
    /** Get validation errors for this field */
    public List<ValidationError> errors();
    
    /** Get field constraints */
    public List<Tuple<String,List<Object>>> constraints();
    
    /** Get field format information */
    public Tuple<String,List<Object>> format();
    
    /** Get indexes for repeated fields */
    public List<Integer> indexes();
    
    /** Get sub-field by key */
    public Field sub(String key);
}

Form Display Configuration

Configure form element display names and attributes using annotations.

/**
 * Annotation to define display properties for form elements
 */
@interface Form.Display {
    /** Display name for the field */
    String name();
    
    /** Additional display attributes */
    String[] attributes() default {};
}

Usage Examples:

public class Product {
    @Form.Display(name = "Product Name")
    @Required
    public String name;
    
    @Form.Display(name = "Price (USD)", attributes = {"currency", "decimal"})
    @Min(0)
    public BigDecimal price;
}

// Accessing field information in templates
public Result showProductForm() {
    Form<Product> productForm = Form.form(Product.class);
    Form.Field nameField = productForm.field("name");
    
    String displayName = nameField.name(); // Gets display name from annotation
    List<ValidationError> errors = nameField.errors();
    
    return ok(views.html.productForm.render(productForm));
}

Advanced Usage Patterns

Partial Field Binding

Control which fields are bound from requests for security and data integrity.

// Only bind specific fields from request
Form<User> userForm = Form.form(User.class)
    .bindFromRequest("name", "email"); // Only these fields will be bound

// Useful for preventing mass assignment vulnerabilities
Form<User> userForm = Form.form(User.class)
    .bindFromRequest("name", "email", "bio"); // Admin fields excluded

JSON Data Binding

Bind forms directly from JSON data for API endpoints.

public Result createUserFromJson() {
    JsonNode json = request().body().asJson();
    Form<User> userForm = Form.form(User.class).bind(json);
    
    if (userForm.hasErrors()) {
        return badRequest(userForm.errorsAsJson());
    }
    
    User user = userForm.get();
    return created(Json.toJson(user));
}

Custom Error Handling

Add custom validation errors programmatically.

public Result validateUser() {
    Form<User> userForm = Form.form(User.class).bindFromRequest();
    
    // Custom validation logic
    if (userService.emailExists(userForm.field("email").value())) {
        userForm.reject("email", "This email is already registered");
    }
    
    if (userForm.hasErrors()) {
        return badRequest(views.html.createUser.render(userForm));
    }
    
    return ok("User is valid");
}

Install with Tessl CLI

npx tessl i tessl/maven-com-typesafe-play--play-java

docs

dependency-injection.md

form-processing.md

formatting.md

index.md

routing.md

streaming.md

utilities.md

validation.md

tile.json