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

routing.mddocs/

Routing DSL

Play Framework's Routing DSL provides a fluent API for building type-safe routes programmatically with support for up to 3 parameters. The DSL enables dynamic route creation and HTTP method handling with automatic parameter binding and asynchronous request processing.

Capabilities

Core Routing DSL

Main routing DSL class for creating programmatic routes with fluent method chaining.

/**
 * DSL for building routers with type-safe parameter handling up to 3 parameters
 */
public class RoutingDsl {
    /** Create GET route with path pattern */
    public PathPatternMatcher GET(String pathPattern);
    
    /** Create HEAD route with path pattern */
    public PathPatternMatcher HEAD(String pathPattern);
    
    /** Create POST route with path pattern */
    public PathPatternMatcher POST(String pathPattern);
    
    /** Create PUT route with path pattern */
    public PathPatternMatcher PUT(String pathPattern);
    
    /** Create DELETE route with path pattern */
    public PathPatternMatcher DELETE(String pathPattern);
    
    /** Create PATCH route with path pattern */
    public PathPatternMatcher PATCH(String pathPattern);
    
    /** Create OPTIONS route with path pattern */
    public PathPatternMatcher OPTIONS(String pathPattern);
    
    /** Create route with custom HTTP method */
    public PathPatternMatcher match(String method, String pathPattern);
    
    /** Build the configured router */
    public play.api.routing.Router build();
}

Usage Examples:

import play.routing.RoutingDsl;
import play.mvc.Result;
import static play.mvc.Results.*;

// Basic routing setup
public class MyRoutes {
    
    public Router createRouter() {
        RoutingDsl routingDsl = new RoutingDsl();
        
        return routingDsl
            .GET("/").routeTo(() -> ok("Welcome to my application"))
            .GET("/health").routeTo(() -> ok("OK"))
            .POST("/api/data").routeTo(() -> ok("Data received"))
            .build();
    }
}

// RESTful API routes
public class APIRoutes {
    
    public Router createAPIRouter() {
        RoutingDsl dsl = new RoutingDsl();
        
        return dsl
            // User routes
            .GET("/api/users").routeTo(this::getAllUsers)
            .GET("/api/users/:id").routeTo(this::getUser)
            .POST("/api/users").routeTo(this::createUser)
            .PUT("/api/users/:id").routeTo(this::updateUser)
            .DELETE("/api/users/:id").routeTo(this::deleteUser)
            
            // Product routes
            .GET("/api/products").routeTo(this::getAllProducts)
            .GET("/api/products/:id").routeTo(this::getProduct)
            .POST("/api/products").routeTo(this::createProduct)
            
            // Custom methods
            .match("PATCH", "/api/users/:id/status").routeTo(this::updateUserStatus)
            .build();
    }
    
    private Result getAllUsers() {
        // Implementation
        return ok("All users");
    }
    
    private Result getUser(String id) {
        // Implementation with parameter
        return ok("User: " + id);
    }
    
    // ... other methods
}

Path Pattern Matcher

Route pattern matcher supporting different parameter arities with both synchronous and asynchronous action handling.

/**
 * Route pattern matcher for different parameter arities
 */
public class RoutingDsl.PathPatternMatcher {
    /** Route with no parameters */
    public RoutingDsl routeTo(F.Function0<Result> action);
    
    /** Route with 1 parameter */
    public <A1> RoutingDsl routeTo(F.Function<A1, Result> action);
    
    /** Route with 2 parameters */
    public <A1, A2> RoutingDsl routeTo(F.Function2<A1, A2, Result> action);
    
    /** Route with 3 parameters */
    public <A1, A2, A3> RoutingDsl routeTo(F.Function3<A1, A2, A3, Result> action);
    
    /** Asynchronous route with no parameters */
    public RoutingDsl routeAsync(F.Function0<F.Promise<Result>> action);
    
    /** Asynchronous route with 1 parameter */
    public <A1> RoutingDsl routeAsync(F.Function<A1, F.Promise<Result>> action);
    
    /** Asynchronous route with 2 parameters */
    public <A1, A2> RoutingDsl routeAsync(F.Function2<A1, A2, F.Promise<Result>> action);
    
    /** Asynchronous route with 3 parameters */
    public <A1, A2, A3> RoutingDsl routeAsync(F.Function3<A1, A2, A3, F.Promise<Result>> action);
}

Usage Examples:

// Synchronous routes with parameters
public Router createSyncRoutes() {
    RoutingDsl dsl = new RoutingDsl();
    
    return dsl
        // No parameters
        .GET("/").routeTo(() -> ok("Home"))
        
        // One parameter
        .GET("/users/:id").routeTo((String id) -> 
            ok("User ID: " + id))
        
        // Two parameters
        .GET("/users/:userId/posts/:postId").routeTo((String userId, String postId) ->
            ok("User: " + userId + ", Post: " + postId))
        
        // Three parameters
        .GET("/categories/:cat/products/:prod/reviews/:rev").routeTo(
            (String cat, String prod, String rev) ->
                ok("Category: " + cat + ", Product: " + prod + ", Review: " + rev))
        
        .build();
}

// Asynchronous routes
public Router createAsyncRoutes() {
    RoutingDsl dsl = new RoutingDsl();
    
    return dsl
        // Async no parameters
        .GET("/async").routeAsync(() -> 
            F.Promise.promise(() -> ok("Async response")))
        
        // Async with parameter
        .GET("/async/users/:id").routeAsync((String id) ->
            userService.findByIdAsync(id)
                .map(user -> ok(Json.toJson(user))))
        
        // Async with multiple parameters
        .GET("/async/search/:type/:query").routeAsync((String type, String query) ->
            searchService.searchAsync(type, query)
                .map(results -> ok(Json.toJson(results))))
        
        .build();
}

Advanced Usage Patterns

Type-Safe Parameter Handling

// Custom parameter binding with type conversion
public class TypeSafeRoutes {
    
    public Router createTypeSafeRouter() {
        RoutingDsl dsl = new RoutingDsl();
        
        return dsl
            // String parameters (default)
            .GET("/users/:id").routeTo(this::getUserString)
            
            // Integer conversion
            .GET("/products/:id").routeTo((String idStr) -> {
                try {
                    Integer id = Integer.parseInt(idStr);
                    return getProduct(id);
                } catch (NumberFormatException e) {
                    return badRequest("Invalid product ID");
                }
            })
            
            // UUID conversion
            .GET("/orders/:uuid").routeTo((String uuidStr) -> {
                try {
                    UUID uuid = UUID.fromString(uuidStr);
                    return getOrder(uuid);
                } catch (IllegalArgumentException e) {
                    return badRequest("Invalid UUID format");
                }
            })
            
            .build();
    }
    
    private Result getUserString(String id) {
        return ok("User: " + id);
    }
    
    private Result getProduct(Integer id) {
        return ok("Product ID: " + id);
    }
    
    private Result getOrder(UUID uuid) {
        return ok("Order UUID: " + uuid);
    }
}

REST API Builder

// Comprehensive REST API builder
public class RESTAPIBuilder {
    
    private final RoutingDsl dsl = new RoutingDsl();
    
    public <T> RESTAPIBuilder resource(String basePath, RESTController<T> controller) {
        dsl.GET(basePath).routeTo(controller::index)
           .GET(basePath + "/:id").routeTo(controller::show)
           .POST(basePath).routeTo(controller::create)
           .PUT(basePath + "/:id").routeTo(controller::update)
           .DELETE(basePath + "/:id").routeTo(controller::delete);
        
        return this;
    }
    
    public <T> RESTAPIBuilder asyncResource(String basePath, AsyncRESTController<T> controller) {
        dsl.GET(basePath).routeAsync(controller::indexAsync)
           .GET(basePath + "/:id").routeAsync(controller::showAsync)
           .POST(basePath).routeAsync(controller::createAsync)
           .PUT(basePath + "/:id").routeAsync(controller::updateAsync)
           .DELETE(basePath + "/:id").routeAsync(controller::deleteAsync);
        
        return this;
    }
    
    public Router build() {
        return dsl.build();
    }
}

// REST controller interface
public interface RESTController<T> {
    Result index();
    Result show(String id);
    Result create();
    Result update(String id);
    Result delete(String id);
}

// Async REST controller interface
public interface AsyncRESTController<T> {
    F.Promise<Result> indexAsync();
    F.Promise<Result> showAsync(String id);
    F.Promise<Result> createAsync();
    F.Promise<Result> updateAsync(String id);
    F.Promise<Result> deleteAsync(String id);
}

// Usage
public Router createRESTAPI() {
    return new RESTAPIBuilder()
        .resource("/api/users", new UserController())
        .resource("/api/products", new ProductController())
        .asyncResource("/api/orders", new OrderController())
        .build();
}

Middleware and Filters

// Route-specific middleware using action composition
public class MiddlewareRoutes {
    
    public Router createProtectedRoutes() {
        RoutingDsl dsl = new RoutingDsl();
        
        return dsl
            // Public routes
            .GET("/").routeTo(() -> ok("Public home"))
            .GET("/login").routeTo(() -> ok("Login page"))
            
            // Protected routes with authentication
            .GET("/dashboard").routeTo(() -> 
                withAuth(() -> ok("Dashboard")))
            
            .GET("/profile/:id").routeTo((String id) ->
                withAuth(() -> getUserProfile(id)))
            
            // Admin routes with role check
            .GET("/admin").routeTo(() ->
                withRole("admin", () -> ok("Admin panel")))
            
            .DELETE("/admin/users/:id").routeTo((String id) ->
                withRole("admin", () -> deleteUser(id)))
            
            .build();
    }
    
    private Result withAuth(Supplier<Result> action) {
        if (isAuthenticated()) {
            return action.get();
        } else {
            return unauthorized("Authentication required");
        }
    }
    
    private Result withRole(String role, Supplier<Result> action) {
        if (isAuthenticated() && hasRole(role)) {
            return action.get();
        } else {
            return forbidden("Insufficient permissions");
        }
    }
    
    private boolean isAuthenticated() {
        // Check authentication
        return true; // Placeholder
    }
    
    private boolean hasRole(String role) {
        // Check user role
        return true; // Placeholder
    }
    
    private Result getUserProfile(String id) {
        return ok("Profile for user: " + id);
    }
    
    private Result deleteUser(String id) {
        return ok("Deleted user: " + id);
    }
}

Dynamic Route Generation

// Dynamic route generation based on configuration
public class DynamicRoutes {
    
    public Router createDynamicRouter(Configuration config) {
        RoutingDsl dsl = new RoutingDsl();
        
        // Load route configurations
        List<RouteConfig> routeConfigs = loadRouteConfigs(config);
        
        for (RouteConfig routeConfig : routeConfigs) {
            addRouteFromConfig(dsl, routeConfig);
        }
        
        return dsl.build();
    }
    
    private void addRouteFromConfig(RoutingDsl dsl, RouteConfig config) {
        PathPatternMatcher matcher;
        
        switch (config.method.toUpperCase()) {
            case "GET":
                matcher = dsl.GET(config.pattern);
                break;
            case "POST":
                matcher = dsl.POST(config.pattern);
                break;
            case "PUT":
                matcher = dsl.PUT(config.pattern);
                break;
            case "DELETE":
                matcher = dsl.DELETE(config.pattern);
                break;
            default:
                matcher = dsl.match(config.method, config.pattern);
        }
        
        // Add route handler based on parameter count
        switch (config.parameterCount) {
            case 0:
                matcher.routeTo(() -> handleRoute(config));
                break;
            case 1:
                matcher.routeTo((String p1) -> handleRoute(config, p1));
                break;
            case 2:
                matcher.routeTo((String p1, String p2) -> handleRoute(config, p1, p2));
                break;
            case 3:
                matcher.routeTo((String p1, String p2, String p3) -> handleRoute(config, p1, p2, p3));
                break;
        }
    }
    
    private List<RouteConfig> loadRouteConfigs(Configuration config) {
        // Load from configuration
        return new ArrayList<>(); // Placeholder
    }
    
    private Result handleRoute(RouteConfig config, String... params) {
        // Dynamic route handling logic
        return ok("Handled route: " + config.pattern + " with params: " + Arrays.toString(params));
    }
    
    private static class RouteConfig {
        String method;
        String pattern;
        int parameterCount;
        String handler;
    }
}

Error Handling and Validation

// Route-level error handling and validation
public class ValidatedRoutes {
    
    public Router createValidatedRouter() {
        RoutingDsl dsl = new RoutingDsl();
        
        return dsl
            // Validated single parameter
            .GET("/users/:id").routeTo((String id) ->
                validateAndHandle(id, this::isValidUserId, this::getUser))
            
            // Validated multiple parameters
            .GET("/posts/:userId/:postId").routeTo((String userId, String postId) ->
                validateAndHandle2(userId, postId, 
                    this::isValidUserId, this::isValidPostId, 
                    this::getPost))
            
            // Async validation
            .GET("/async/validate/:id").routeAsync((String id) ->
                validateAsync(id)
                    .thenCompose(valid -> {
                        if (valid) {
                            return F.Promise.promise(() -> ok("Valid: " + id));
                        } else {
                            return F.Promise.promise(() -> badRequest("Invalid: " + id));
                        }
                    }))
            
            .build();
    }
    
    private Result validateAndHandle(String param, Predicate<String> validator, 
                                   Function<String, Result> handler) {
        if (validator.test(param)) {
            try {
                return handler.apply(param);
            } catch (Exception e) {
                return internalServerError("Error processing: " + e.getMessage());
            }
        } else {
            return badRequest("Invalid parameter: " + param);
        }
    }
    
    private Result validateAndHandle2(String param1, String param2,
                                    Predicate<String> validator1, Predicate<String> validator2,
                                    BiFunction<String, String, Result> handler) {
        if (validator1.test(param1) && validator2.test(param2)) {
            try {
                return handler.apply(param1, param2);
            } catch (Exception e) {
                return internalServerError("Error processing: " + e.getMessage());
            }
        } else {
            return badRequest("Invalid parameters");
        }
    }
    
    private F.Promise<Boolean> validateAsync(String param) {
        return F.Promise.promise(() -> {
            // Async validation logic
            Thread.sleep(100); // Simulate async operation
            return param != null && param.matches("\\d+");
        });
    }
    
    private boolean isValidUserId(String id) {
        return id != null && id.matches("\\d+");
    }
    
    private boolean isValidPostId(String id) {
        return id != null && id.matches("\\d+");
    }
    
    private Result getUser(String id) {
        return ok("User: " + id);
    }
    
    private Result getPost(String userId, String postId) {
        return ok("User: " + userId + ", Post: " + postId);
    }
}

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