{"id":42949954,"url":"https://github.com/prime-framework/prime-mvc-example","last_synced_at":"2026-01-30T21:07:12.315Z","repository":{"id":227724229,"uuid":"771585029","full_name":"prime-framework/prime-mvc-example","owner":"prime-framework","description":"A boiler plate example of prime-mvc","archived":false,"fork":false,"pushed_at":"2025-01-17T15:21:14.000Z","size":57,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-01-17T15:49:23.577Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/prime-framework.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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-03-13T15:10:45.000Z","updated_at":"2025-01-17T15:21:16.000Z","dependencies_parsed_at":null,"dependency_job_id":"788e9cbb-c3f1-4393-991a-70d0f6710617","html_url":"https://github.com/prime-framework/prime-mvc-example","commit_stats":null,"previous_names":["prime-framework/prime-mvc-example"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/prime-framework/prime-mvc-example","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prime-framework%2Fprime-mvc-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prime-framework%2Fprime-mvc-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prime-framework%2Fprime-mvc-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prime-framework%2Fprime-mvc-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/prime-framework","download_url":"https://codeload.github.com/prime-framework/prime-mvc-example/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prime-framework%2Fprime-mvc-example/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28919418,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-30T20:25:28.696Z","status":"ssl_error","status_checked_at":"2026-01-30T20:25:13.426Z","response_time":66,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":[],"created_at":"2026-01-30T21:07:11.676Z","updated_at":"2026-01-30T21:07:12.310Z","avatar_url":"https://github.com/prime-framework.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pre-reqs\n\nSavant installed\nJDK installed\n\n# Assumptions\n\n1. You can get familiar with Freemarker Template basics elsewhere\n1. You can figure out how to run this outside of an IDE elsewhere, since it's just executing a Java class with a main method.\n\n# Running\n\n## Run from command line\n\n`sb clean app start`\n\nThe web server should now be running on port 8080.\n\n## Run via IntelliJ\nTo ensure your dependencies are fetched, before opening IntelliJ\n\n`sb clean idea`\n\nThen open the project in IntelliJ\n\nNavigate to the `ExamplePrimeMain` class and run it as a Java application.\n\nThe web server should now be running on port 8080.\n\n# Sample URLs to access\n\n## /\n\n```shell\n# (goes to `IndexAction`)\ncurl -v http://localhost:8080\n```\n\n## /page-that-requires-auth\n\nIf you go here, you'll see a redirect to `/login` (keep reading for why).\n\n```shell\ncurl -v http://localhost:8080/page-that-requires-auth\n```\n\nSample output:\n\n```\n*   Trying [::1]:8080...\n* Connected to localhost (::1) port 8080\n\u003e GET /page-that-requires-auth HTTP/1.1\n\u003e Host: localhost:8080\n\u003e User-Agent: curl/8.4.0\n\u003e Accept: */*\n\u003e \n\u003c HTTP/1.1 302 \n\u003c set-cookie: prime-mvc-saved-request=QkJCAwUi8e1Fw4rBpC3SRqnJ0ah6qu9DFUBigwt0vxv2dh8_77s9lK3u9cweEQZ5x6bsSQyPVxFK5M9Ult6PvgSlL3inue5pPvsbXHDtRatALu5VMFzFA1q42HxdItqkDfy3MA==; HttpOnly; Path=/; SameSite=Strict\n\u003c content-length: 0\n\u003c location: /login\n\u003c connection: keep-alive\n\u003c cache-control: no-cache\n\u003c \n* Connection #0 to host localhost left intact\n```\n\nThe redirect to `/login` happens because:\n\n1. We are not authenticated.\n2. The `PageThatRequiresAuthAction` action class has an `@Action` annotation has `requiresAuthentication = true`\n3. `BaseAction` has this annotation: `@SaveRequest(uri = \"/login\")`\n\nThe latter causes a redirect to occur if an action fails due to an `unauthenticated` response code. It also saves the original URL the user was attempting to access such that if the login is successful, they can be sent back there.\n\nIf the cookie is present and the login succeeds, code such as `SavedRequestWorkflow` and `ReexecuteSavedRequestResult` will send the user back to the page they attempted to access.\n\nYou can try this by entering any username in the login form and submitting. It will establish a session and redirect you back to where you started.\n\nIn this example, we are using the `BaseUserIdCookieSecurityContext` to keep track of who is logged in (a session). That\nbase class serializes the User ID, login time, and a session ID into an encrypted cookie.\nThere are other options as well (JWT, etc.).\n\n## /foobar\n\nPrime uses our `MissingAction` to handle this one. This is because the `missingPath` on the `MVCConfiguration` interface is set to `/missing`.\n\n## /form\n\nShows using a form control. The form:\n\n1. Has validation to ensure you supply the required name field.\n2. The controls handle populating the form fields with data based on the `FormAction` class fields.\n3. The controls also populate the `FormAction` class fields with data when the Freemarker templates are rendered (could be on any of action methods).\n4. If you include the word `crash` in your name, you will see how an exception is handled (`BaseAction` has the code `error` mapped).\n5. If you visit `/login` first and login/establish a session, then PMVC's Freemarker form control (see `[@control.form` in `form.ftl`) will include a CSRF token like this that is validated on POST requests only:\n\n```html\n\u003cinput type=\"hidden\" name=\"primeCSRFToken\" value=\"QkJCAYS8c-DFoBAd02ReblqfhEKQXD3DeZ77s_z046IHzuNu71_5t2wqZ9zeYyKfOQrqhoF-u9pm0GfRWUW4e3bgIpk4j3YzKxMz4j699_su984E3tCgZGT4uM_XoI3G5qtTag==\"/\u003e\n```\n\n# What else is in here?\n\n* 2 templates for those actions in `src/main/web/templates`.\n* `ExamplePrimeMain` class to bootstrap HTTP server and supply the correct Guice modules.\n* Basic Guice module `ExampleModule` to wire up the minimum Prime dependencies.\n* Configuration classes\n  * `ExamplePrimeConfig` is the main one - controls paths (which affect template resolution), cookie settings, CSRF settings\n  * `ExampleCORSProvider` is the CORS policy config class\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprime-framework%2Fprime-mvc-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprime-framework%2Fprime-mvc-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprime-framework%2Fprime-mvc-example/lists"}