{"id":21541794,"url":"https://github.com/sandratraniaina/ember-mvc","last_synced_at":"2025-10-09T14:18:27.834Z","repository":{"id":238713596,"uuid":"797072772","full_name":"sandratraniaina/ember-mvc","owner":"sandratraniaina","description":"Ember MVC is a lightweight, annotation-based Model-View-Controller (MVC) framework for building Java web applications","archived":false,"fork":false,"pushed_at":"2025-04-04T04:58:51.000Z","size":859,"stargazers_count":7,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-04T05:27:34.466Z","etag":null,"topics":["framework","java","servlet-mvc"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sandratraniaina.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-05-07T06:31:40.000Z","updated_at":"2025-04-04T04:58:52.000Z","dependencies_parsed_at":"2024-06-14T17:28:15.597Z","dependency_job_id":"3c9cc14c-c3f8-4821-ba71-b7749e994f38","html_url":"https://github.com/sandratraniaina/ember-mvc","commit_stats":null,"previous_names":["sandratraniaina/ember-mvc"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandratraniaina%2Fember-mvc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandratraniaina%2Fember-mvc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandratraniaina%2Fember-mvc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandratraniaina%2Fember-mvc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sandratraniaina","download_url":"https://codeload.github.com/sandratraniaina/ember-mvc/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248155829,"owners_count":21056715,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["framework","java","servlet-mvc"],"created_at":"2024-11-24T05:07:41.019Z","updated_at":"2025-10-09T14:18:22.789Z","avatar_url":"https://github.com/sandratraniaina.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ember MVC Framework\n\n**Ember MVC** is a lightweight, annotation-based Model-View-Controller (MVC) framework for building Java web applications. It simplifies request handling, validation, and routing with a minimal setup, making it ideal for developers seeking a flexible yet powerful solution.\n\n**Version**: 1.0.0  \n**License**: MIT  \n**Documentation**: [Javadoc](https://sandratraniaina.github.io/ember-mvc/)  \n**Releases**: [GitHub Releases](https://github.com/sandratraniaina/ember-mvc/releases)\n\n## Features\n\n- **Annotation-Based Routing**: Use `@Get`, `@Post`, and `@Url` to map HTTP requests to methods.\n- **Validation**: Built-in annotations like `@Numeric`, `@Required`, and `@Length` for input validation (See the [Javadoc](https://sandratraniaina.github.io/ember-mvc/) for more validation).\n- **Flexible Response Handling**: Return `ModelView` objects for views or JSON for REST APIs.\n- **Session Management**: Built-in support for session handling using the `Session` class.\n- **Role-Based Access Control**: Secure endpoints with the `@RequiredRole` annotation.\n- **File Uploads**: Easy file handling with built-in support for multipart requests.\n- **Lightweight**: Minimal dependencies (Servlet API, Gson).\n\n## Installation\n\n### Prerequisites\n\n- Java 17 or higher\n- A servlet container (e.g., Apache Tomcat 10.x)\n- Git (optional, for cloning)\n\n### Steps\n\n1. **Download the JAR**:\n   - Get `ember-mvc-1.0.0.jar` from the [Releases](https://github.com/sandratraniaina/ember-mvc/releases) page.\n   - Alternatively, clone and build from source:\n\n     ```bash\n     git clone https://github.com/sandratraniaina/ember-mvc.git\n     cd ember-mvc\n     ./build.bat  # This script builds the project into a jar file\n     ```\n\n2. **Add to Your Project**:\n   - Copy `ember-mvc-1.0.0.jar` to your project's `WEB-INF/lib/` directory.\n   - Ensure dependencies are included:\n     - `jakarta.servlet-api-6.0.0.jar` (provided by your servlet container).\n     - `gson-2.10.1.jar` (download from [Maven Central](https://mvnrepository.com/artifact/com.google.code.gson/gson)).\n\n3. **Configure Your Servlet Container**:\n   - See \"Project Configuration\" below.\n\n## Project Configuration\n\nConfigure Ember MVC in your web application via `web.xml` or annotations (if using a Servlet 3.0+ container).\n\n### Using `web.xml`\n\nAdd the following to `WEB-INF/web.xml`:\n\n```xml\n\u003cweb-app xmlns=\"https://jakarta.ee/xml/ns/jakartaee\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd\"\n         version=\"6.0\"\u003e\n\n    \u003c!-- FrontController Servlet --\u003e\n    \u003cservlet\u003e\n        \u003cservlet-name\u003eFrontController\u003c/servlet-name\u003e\n        \u003cservlet-class\u003emg.emberframework.core.FrontController\u003c/servlet-class\u003e\n        \u003cload-on-startup\u003e1\u003c/load-on-startup\u003e\n        \u003cinit-param\u003e\n            \u003cparam-name\u003epackage_name\u003c/param-name\u003e\n            \u003cparam-value\u003emg.myapp.controllers\u003c/param-value\u003e \u003c!-- Your controller package --\u003e\n        \u003c/init-param\u003e\n        \u003cmultipart-config /\u003e \u003c!-- Enable file uploads --\u003e\n    \u003c/servlet\u003e\n    \u003cservlet-mapping\u003e\n        \u003cservlet-name\u003eFrontController\u003c/servlet-name\u003e\n        \u003curl-pattern\u003e/\u003c/url-pattern\u003e \u003c!-- Route all requests --\u003e\n    \u003c/servlet-mapping\u003e\n\u003c/web-app\u003e\n```\n\n### Initialization Parameters\n\n- `package_name`: The package containing your controllers (required).\n- `error_param_name`: Attribute name for validation errors (optional, defaults to `\"errors\"`).\n- `error_redirection_param_name`: Parameter for error redirect URL (optional, defaults to `\"error-url\"`).\n- `role_attribute_name`: Session attribute for user roles (optional, defaults to `\"role\"`).\n- `custom_error_page`: Custom error page display (optional, defaults to `Ember MCV` error page).\n\n## Usage Examples\n\n### Example 1: Basic Controller\n\nCreate a controller to handle a GET request:\n\n```java\npackage mg.myapp.controllers;\n\nimport mg.emberframework.annotation.http.Get;\nimport mg.emberframework.annotation.http.Url;\nimport mg.emberframework.core.data.ModelView;\n\n@Url(\"/home\")\npublic class HomeController {\n    @Get\n    public ModelView index() {\n        ModelView mv = new ModelView();\n        mv.setUrl(\"index.jsp\");\n        mv.addObject(\"message\", \"Welcome to Ember MVC!\");\n        return mv;\n    }\n}\n```\n\n- **Request**: `GET /home`\n- **Result**: Renders `index.jsp` with `message` available as a request attribute.\n\n**`index.jsp`**:\n\n```jsp\n\u003chtml\u003e\n\u003cbody\u003e\n    \u003ch1\u003e${message}\u003c/h1\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n### Example 2: REST API Endpoint\n\nReturn JSON data with `@RestApi`:\n\n```java\npackage mg.myapp.controllers;\n\nimport mg.emberframework.annotation.http.Get;\nimport mg.emberframework.annotation.http.RestApi;\nimport mg.emberframework.annotation.http.Url;\n\nimport mg.emberframework.core.data.ModelView;\n\n@Url(\"/api/users\")\npublic class UserController {\n    @Get\n    @RestApi\n    @Url\n    public ModelView getUsers() {\n        ModelView mv = new ModelView();\n\n        mv.addObject(\"users\", new String[]{\"Alice\", \"Bob\"});\n\n        return mv;\n    }\n}\n```\n\n- **Request**: `GET /api/users`\n- **Response**: `{data:{users:[\"Alice\", \"Bob\"]}}` (JSON).\n\n### Example 3: Form Validation\n\nValidate form input with annotations:\n\n```java\npackage mg.myapp.controllers;\n\nimport mg.emberframework.annotation.http.Post;\nimport mg.emberframework.annotation.http.RequestParameter;\nimport mg.emberframework.annotation.http.Url;\nimport mg.emberframework.annotation.validation.Numeric;\nimport mg.emberframework.annotation.validation.Required;\nimport mg.emberframework.core.data.ModelView;\n\n@Url(\"/submit\")\npublic class FormController {\n    @Post\n    public ModelView processForm(\n        @RequestParameter(\"name\") @Required String name,\n        @RequestParameter(\"age\") @Numeric int age\n    ) {\n        ModelView mv = new ModelView();\n        mv.setUrl(\"result.jsp\");\n        mv.addObject(\"name\", name);\n        mv.addObject(\"age\", age);\n        return mv;\n    }\n}\n```\n\n- **Request**: `POST /submit` with `name=John\u0026age=25`\n- **Result**: Renders `result.jsp` if valid; otherwise, errors are set in the `errors` attribute.\n\n### Example 4: Model Validation\n\nUse validation annotations directly on model classes:\n\n```java\npackage model;\n\nimport mg.emberframework.annotation.validation.Numeric;\nimport mg.emberframework.annotation.validation.Required;\n\npublic class User {\n    @Required\n    private String name;\n    \n    @Numeric\n    private int age;\n    \n    // Getters and setters\n    public String getName() {\n        return name;\n    }\n    \n    public void setName(String name) {\n        this.name = name;\n    }\n    \n    public int getAge() {\n        return age;\n    }\n    \n    public void setAge(int age) {\n        this.age = age;\n    }\n}\n```\n\nController to handle user data:\n\n```java\npackage controller;\n\nimport mg.emberframework.annotation.http.Controller;\nimport mg.emberframework.annotation.http.Get;\nimport mg.emberframework.annotation.http.Url;\nimport mg.emberframework.core.data.ModelView;\nimport model.User;\nimport winter.data.annotation.http.RequestParam;\n\n@Controller\n@Url(\"/users\")\npublic class UserController {\n    @Url(\"/user\")\n    @Get\n    public ModelView showUser(@RequestParam(\"user\") User user) {\n        ModelView mv = new ModelView();\n        mv.setUrl(\"user-details.jsp\");\n        mv.addObject(\"user\", user);\n        return mv;\n    }\n}\n```\n\nJSP page to display validation errors:\n\n```jsp\n\u003c%@ page import =\"java.util.*\" %\u003e\n\u003c%@ page import =\"model.*\" %\u003e\n\u003c%@ page import =\"mg.emberframework.core.data.*\" %\u003e\n\u003c%\n    ModelValidationResults result = (ModelValidationResults)request.getAttribute(\"errors\");\n%\u003e\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n    \u003ctitle\u003eUser Form\u003c/title\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n    \u003ch1\u003eUser Registration\u003c/h1\u003e\n    \u003cform action=\"./users/user\" method=\"get\"\u003e\n        \u003cdiv\u003e\n            \u003clabel for=\"user.name\"\u003eName:\u003c/label\u003e\n            \u003cinput type=\"text\" name=\"user.name\" id=\"name\" value=\"\u003c%= result.getFieldExceptionValue(\"user.name\") %\u003e\"\u003e\n            \u003c%= result.getFieldExceptionMessage(\"user.name\") %\u003e\n        \u003c/div\u003e\n        \u003cdiv\u003e\n            \u003clabel for=\"user.age\"\u003eAge:\u003c/label\u003e\n            \u003cinput type=\"text\" name=\"user.age\" id=\"age\" value=\"\u003c%= result.getFieldExceptionValue(\"user.age\") %\u003e\"\u003e\n            \u003c%= result.getFieldExceptionMessage(\"user.age\", \"\u003cbr\u003e\") %\u003e\n        \u003c/div\u003e\n        \u003cinput type=\"hidden\" name=\"error-url\" value=\"/user-form\"\u003e\n        \u003cbutton type=\"submit\"\u003eSubmit\u003c/button\u003e\n    \u003c/form\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n### Example 5: Session Management\n\nUse the `Session` class for persistent data across requests:\n\n```java\npackage controller;\n\nimport mg.emberframework.annotation.http.Controller;\nimport mg.emberframework.annotation.http.Get;\nimport mg.emberframework.annotation.http.Post;\nimport mg.emberframework.annotation.http.Url;\nimport mg.emberframework.core.Session;\nimport mg.emberframework.core.data.ModelView;\nimport mg.emberframework.annotation.http.RequestParameter;\nimport model.User;\n\n@Controller\n@Url(\"/auth\")\npublic class AuthController {\n    // Method 1: Inject Session as parameter\n    @Post\n    @Url(\"/login\")\n    public ModelView login(\n        @RequestParameter(\"username\") String username,\n        @RequestParameter(\"password\") String password,\n        Session session\n    ) {\n        ModelView mv = new ModelView();\n        \n        // Authentication logic here\n        if (authenticateUser(username, password)) {\n            User user = getUserData(username);\n            // Store user in session\n            session.add(\"currentUser\", user);\n            session.add(\"role\", \"ADMIN\");\n            mv.setUrl(\"dashboard.jsp\");\n        } else {\n            mv.setUrl(\"login.jsp\");\n            mv.addObject(\"error\", \"Invalid credentials\");\n        }\n        \n        return mv;\n    }\n    \n    // Method 2: Session as controller field with getter/setter\n    private Session session;\n    \n    public Session getSession() {\n        return session;\n    }\n    \n    public void setSession(Session session) {\n        this.session = session;\n    }\n    \n    @Get\n    @Url(\"/profile\")\n    public ModelView viewProfile() {\n        ModelView mv = new ModelView();\n        \n        // Get user from session\n        User user = (User) session.get(\"currentUser\");\n        \n        if (user != null) {\n            mv.setUrl(\"profile.jsp\");\n            mv.addObject(\"user\", user);\n        } else {\n            mv.setUrl(\"login.jsp\");\n            mv.addObject(\"error\", \"Please log in first\");\n        }\n        \n        return mv;\n    }\n    \n    @Get\n    @Url(\"/logout\")\n    public ModelView logout() {\n        // Clear session\n        session.clear();\n        \n        ModelView mv = new ModelView();\n        mv.setUrl(\"login.jsp\");\n        mv.addObject(\"message\", \"You have been logged out\");\n        return mv;\n    }\n    \n    // Helper methods\n    private boolean authenticateUser(String username, String password) {\n        // Authentication logic\n        return true; // Dummy implementation\n    }\n    \n    private User getUserData(String username) {\n        // Get user data from database\n        User user = new User();\n        user.setName(username);\n        user.setAge(30);\n        return user;\n    }\n}\n```\n\n### Example 6: Role-Based Access Control\n\nUse the `@RequiredRole` annotation to restrict access to specific roles:\n\n```java\npackage controller;\n\nimport mg.emberframework.annotation.http.Controller;\nimport mg.emberframework.annotation.http.Get;\nimport mg.emberframework.annotation.http.RequiredRole;\nimport mg.emberframework.annotation.http.Url;\nimport mg.emberframework.core.data.ModelView;\n\n@Controller\n@Url(\"/admin\")\n@RequiredRole(values = {\"ADMIN\"}) // Restrict entire controller to ADMIN role\npublic class AdminController {\n    \n    @Get\n    @Url(\"/dashboard\")\n    public ModelView dashboard() {\n        ModelView mv = new ModelView();\n        mv.setUrl(\"admin/dashboard.jsp\");\n        mv.addObject(\"title\", \"Admin Dashboard\");\n        return mv;\n    }\n    \n    @Get\n    @Url(\"/users\")\n    public ModelView manageUsers() {\n        ModelView mv = new ModelView();\n        mv.setUrl(\"admin/users.jsp\");\n        mv.addObject(\"title\", \"User Management\");\n        return mv;\n    }\n    \n    @Get\n    @Url(\"/reports\")\n    @RequiredRole(values = {\"ADMIN\", \"ANALYST\"}) // Allow both ADMIN and ANALYST roles\n    public ModelView viewReports() {\n        ModelView mv = new ModelView();\n        mv.setUrl(\"admin/reports.jsp\");\n        mv.addObject(\"title\", \"Reports\");\n        return mv;\n    }\n}\n```\n\n```java\npackage controller;\n\nimport mg.emberframework.annotation.http.Controller;\nimport mg.emberframework.annotation.http.Get;\nimport mg.emberframework.annotation.http.RequiredRole;\nimport mg.emberframework.annotation.http.Url;\nimport mg.emberframework.core.data.ModelView;\n\n@Controller\n@Url(\"/user-management\")\npublic class UserManagementController {\n    \n    // Accessible to all users\n    @Get\n    @Url(\"/view-profile\")\n    public ModelView viewProfile() {\n        ModelView mv = new ModelView();\n        mv.setUrl(\"user/profile.jsp\");\n        return mv;\n    }\n    \n    // Only accessible to users with MANAGER role\n    @Get\n    @Url(\"/team-members\")\n    @RequiredRole(values = {\"MANAGER\"})\n    public ModelView viewTeamMembers() {\n        ModelView mv = new ModelView();\n        mv.setUrl(\"user/team.jsp\");\n        return mv;\n    }\n    \n    // Only accessible to users with either ADMIN or MANAGER roles\n    @Get\n    @Url(\"/department-stats\")\n    @RequiredRole(values = {\"ADMIN\", \"MANAGER\"})\n    public ModelView viewDepartmentStats() {\n        ModelView mv = new ModelView();\n        mv.setUrl(\"user/department-stats.jsp\");\n        return mv;\n    }\n}\n```\n\n**Note**: The role value is checked against the session attribute specified by the `role_attribute_name` in the servlet configuration (defaults to \"role\").\n\n### Example 7: File Uploads\n\nHandle file uploads using the `File` class:\n\n```java\npackage controller;\n\nimport mg.emberframework.annotation.http.Controller;\nimport mg.emberframework.annotation.http.Post;\nimport mg.emberframework.annotation.http.Url;\nimport mg.emberframework.core.data.ModelView;\nimport mg.emberframework.core.File;\nimport winter.data.annotation.http.RequestParam;\n\n@Controller\n@Url(\"/upload\")\npublic class FileUploadController {\n    @Post\n    @Url\n    public ModelView uploadFile(@RequestParam(\"profile_picture\") File file) {\n        ModelView mv = new ModelView();\n        \n        try {\n            // Get the file bytes\n            byte[] data = file.getBytes();\n            \n            // Save to disk (example)\n            String savePath = \"/path/to/uploads/\";\n            file.writeTo(savePath);\n            \n            mv.addObject(\"success\", \"File uploaded successfully\");\n            mv.addObject(\"fileName\", fileName);\n            mv.addObject(\"fileType\", contentType);\n            mv.addObject(\"fileSize\", size);\n        } catch (Exception e) {\n            mv.addObject(\"error\", \"Error uploading file: \" + e.getMessage());\n        }\n    \n        mv.setUrl(\"upload-result.jsp\");\n        return mv;\n    }\n}\n```\n\nHTML form for file upload:\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n    \u003ctitle\u003eFile Upload\u003c/title\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n    \u003ch1\u003eUpload Profile Picture\u003c/h1\u003e\n    \u003cform action=\"./upload\" method=\"post\" enctype=\"multipart/form-data\"\u003e\n        \u003cdiv\u003e\n            \u003clabel for=\"profile_picture\"\u003eSelect Image:\u003c/label\u003e\n            \u003cinput type=\"file\" name=\"profile_picture\" id=\"profile_picture\"\u003e\n        \u003c/div\u003e\n        \u003cinput type=\"hidden\" name=\"error-url\" value=\"/upload-form\"\u003e\n        \u003cbutton type=\"submit\"\u003eUpload\u003c/button\u003e\n    \u003c/form\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n### Example 8: Custom Error Page\n\nConfigure a custom error page to handle exceptions gracefully instead of the default Ember MVC error page:\n\n#### Configuration\n\nAdd the `custom_error_page` parameter in `web.xml`:\n\n```xml\n\u003cservlet\u003e\n    \u003cservlet-name\u003eFrontController\u003c/servlet-name\u003e\n    \u003cservlet-class\u003emg.emberframework.core.FrontController\u003c/servlet-class\u003e\n    \u003cload-on-startup\u003e1\u003c/load-on-startup\u003e\n    \u003cinit-param\u003e\n        \u003cparam-name\u003epackage_name\u003c/param-name\u003e\n        \u003cparam-value\u003emg.myapp.controllers\u003c/param-value\u003e\n    \u003c/init-param\u003e\n    \u003cinit-param\u003e\n        \u003cparam-name\u003ecustom_error_page\u003c/param-name\u003e\n        \u003cparam-value\u003e/error.jsp\u003c/param-value\u003e \u003c!-- Custom error page location --\u003e\n    \u003c/init-param\u003e\n    \u003cmultipart-config /\u003e\n\u003c/servlet\u003e\n```\n\n#### Custom Error Page (`error.jsp`)\n\nCreate `error.jsp` in your webapp root to display error details:\n\n```jsp\n\u003c%@ page isErrorPage=\"true\" %\u003e\n\u003chtml\u003e\n\u003chead\u003e\n    \u003ctitle\u003eError - Ember MVC\u003c/title\u003e\n    \u003cstyle\u003e\n        body { font-family: Arial, sans-serif; background-color: #f4f4f4; padding: 20px; }\n        .container { max-width: 600px; margin: 0 auto; background: white; padding: 20px; border-radius: 5px; box-shadow: 0 0 10px rgba(0,0,0,0.1); }\n        h1 { color: #d9534f; }\n        .status { font-size: 1.2em; color: #5bc0de; }\n        .message { font-weight: bold; }\n        pre { background: #f8f8f8; padding: 10px; border: 1px solid #ddd; overflow-x: auto; }\n    \u003c/style\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n    \u003cdiv class=\"container\"\u003e\n        \u003ch1\u003eError Occurred\u003c/h1\u003e\n        \u003cp class=\"status\"\u003eStatus Code: \u003c%= request.getAttribute(\"status-code\") %\u003e\u003c/p\u003e\n        \u003cp class=\"message\"\u003eMessage: \u003c%= request.getAttribute(\"message\") %\u003e\u003c/p\u003e\n        \u003ch3\u003eDetails:\u003c/h3\u003e\n        \u003cpre\u003e\n            \u003c% \n                Exception e = (Exception) request.getAttribute(\"exception\");\n                if (e != null) {\n                    e.printStackTrace(new java.io.PrintWriter(out));\n                }\n            %\u003e\n        \u003c/pre\u003e\n        \u003cp\u003e\u003ca href=\"/\"\u003eReturn to Home\u003c/a\u003e\u003c/p\u003e\n    \u003c/div\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n#### Controller to Trigger an Error\n\nTest the custom error page with a controller that throws an exception:\n\n```java\npackage mg.myapp.controllers;\n\nimport mg.emberframework.annotation.http.Get;\nimport mg.emberframework.annotation.http.Url;\nimport mg.emberframework.core.data.ModelView;\n\n@Url(\"/test\")\npublic class TestController {\n    @Get\n    @Url(\"/error\")\n    public ModelView triggerError() throws Exception {\n        // Simulate an error\n        throw new Exception(\"This is a test error!\");\n    }\n}\n```\n\n- **Request:** `GET /test/error`\n- **Result:** Redirects to `error.jsp`, displaying the status code (500), message (\"This is a test error!\"), and stack trace.\n\n**Note:** The `ExceptionHandler` forwards to the custom error page if `custom_error_page` is set, overriding the default HTML error page. Attributes like `exception`, `status-code`, and `message` are available in the request scope for use in your JSP.\n\n## Contributing\n\nContributions are welcome! Please:\n\n- Fork the repo.\n- Create a feature branch (`git checkout -b feature/my-feature`).\n- Submit a pull request.\n\n## License\n\nReleased under the MIT License. See [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsandratraniaina%2Fember-mvc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsandratraniaina%2Fember-mvc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsandratraniaina%2Fember-mvc/lists"}