{"action":"created","comment":{"url":"https://api.github.com/repos/dropwizard/dropwizard/pulls/comments/31630100","id":31630100,"diff_hunk":"@@ -0,0 +1,252 @@\n+.. _man-validation:\n+\n+#####################\n+Dropwizard Validation\n+#####################\n+\n+.. highlight:: text\n+\n+.. rubric:: Dropwizard comes with a host of validation tools out of the box to allow endpoints to return meaningful error messages when constraints are violated. Hibernate_ is packaged with Dropwizard, so what can be done in Hibernate, can be done with Dropwizard.\n+\n+.. _Hibernate: http://hibernate.org/validator/\n+\n+.. _man-validation-validations:\n+\n+Validations\n+===========\n+\n+Almost anything can be validated on resource endpoints. To give a quick example, the following\n+endpoint doesn't allow a null or empty ``name`` query parameter.\n+\n+.. code-block:: java\n+\n+    @GET\n+    public String find(@QueryParam(\"name\") @NotEmpty String arg) {\n+        // ...\n+    }\n+\n+If a client sends an empty or nonexistant name query param, Dropwizard will respond with a 400 error\n+code with the error: ``query param name may not be empty``.\n+\n+Additionally, annotations such as ``HeaderParam``, ``CookieParam``, ``FormParam``, etc, can be\n+constrained with violations giving descriptive errors and 400 status codes.\n+\n+.. _man-validation-validations-constraining-entities:\n+\n+Constraining Entities\n+*********************\n+\n+If we're accepting client-provided ``Person``, we probably want to ensure that the ``name`` field of\n+the object isn't ``null`` or blank in the request. We can do this as follows:\n+\n+.. code-block:: java\n+\n+    public class Person {\n+\n+        @NotEmpty // ensure that name isn't null or blank\n+        private final String name;\n+\n+        @JsonCreator\n+        public Person(@JsonProperty(\"name\") String name) {\n+            this.name = name;\n+        }\n+\n+        @JsonProperty(\"name\")\n+        public String getName() {\n+            return name;\n+        }\n+    }\n+\n+Then, in our resource class, we can add the ``@Valid`` or the ``@Validated`` annotation to the\n+``Person`` annotation:\n+\n+.. code-block:: java\n+\n+    @PUT\n+    public Person replace(@Valid Person person) {\n+        // ...\n+    }\n+\n+If the name field is missing, Dropwizard will return a ``422 Unprocessable Entity`` response\n+detailing the validation errors: ``name may not be empty``\n+\n+.. _man-validation-validations-optional-constraints:\n+\n+``Optional<T>`` Constraints\n+***************************\n+\n+When ``Optional<T>`` is constrained, it is the type contained within the ``Optional`` that is\n+constrained. If the ``Optional`` is absent, then the constraints are not applied.\n+\n+.. note::\n+\n+    Be careful when using constraints with ``*Param`` annotations with ``Optional<String>`` types as\n+    there is a subtle, but important distinction between null and empty. If a client requests\n+    ``bar?q=``, ``q`` will evaluate to ``Optional.Of(\"\")``. If you want ``q`` to evaluate to","path":"docs/source/manual/validation.rst","position":85,"original_position":85,"commit_id":"6ab00e39ddee5f2be746860613a5056678495b8e","original_commit_id":"6ab00e39ddee5f2be746860613a5056678495b8e","user":{"login":"nickbabcock","id":2106129,"avatar_url":"https://avatars.githubusercontent.com/u/2106129?v=3","gravatar_id":"","url":"https://api.github.com/users/nickbabcock","html_url":"https://github.com/nickbabcock","followers_url":"https://api.github.com/users/nickbabcock/followers","following_url":"https://api.github.com/users/nickbabcock/following{/other_user}","gists_url":"https://api.github.com/users/nickbabcock/gists{/gist_id}","starred_url":"https://api.github.com/users/nickbabcock/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nickbabcock/subscriptions","organizations_url":"https://api.github.com/users/nickbabcock/orgs","repos_url":"https://api.github.com/users/nickbabcock/repos","events_url":"https://api.github.com/users/nickbabcock/events{/privacy}","received_events_url":"https://api.github.com/users/nickbabcock/received_events","type":"User","site_admin":false},"body":"Absolutely, it should.","created_at":"2015-06-03T14:46:17Z","updated_at":"2015-06-03T14:46:17Z","html_url":"https://github.com/dropwizard/dropwizard/pull/1091#discussion_r31630100","pull_request_url":"https://api.github.com/repos/dropwizard/dropwizard/pulls/1091","_links":{"self":{"href":"https://api.github.com/repos/dropwizard/dropwizard/pulls/comments/31630100"},"html":{"href":"https://github.com/dropwizard/dropwizard/pull/1091#discussion_r31630100"},"pull_request":{"href":"https://api.github.com/repos/dropwizard/dropwizard/pulls/1091"}}},"pull_request":{"url":"https://api.github.com/repos/dropwizard/dropwizard/pulls/1091","id":36773432,"html_url":"https://github.com/dropwizard/dropwizard/pull/1091","diff_url":"https://github.com/dropwizard/dropwizard/pull/1091.diff","patch_url":"https://github.com/dropwizard/dropwizard/pull/1091.patch","issue_url":"https://api.github.com/repos/dropwizard/dropwizard/issues/1091","number":1091,"state":"open","locked":false,"title":"Update Validation Documentation","user":{"login":"nickbabcock","id":2106129,"avatar_url":"https://avatars.githubusercontent.com/u/2106129?v=3","gravatar_id":"","url":"https://api.github.com/users/nickbabcock","html_url":"https://github.com/nickbabcock","followers_url":"https://api.github.com/users/nickbabcock/followers","following_url":"https://api.github.com/users/nickbabcock/following{/other_user}","gists_url":"https://api.github.com/users/nickbabcock/gists{/gist_id}","starred_url":"https://api.github.com/users/nickbabcock/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nickbabcock/subscriptions","organizations_url":"https://api.github.com/users/nickbabcock/orgs","repos_url":"https://api.github.com/users/nickbabcock/repos","events_url":"https://api.github.com/users/nickbabcock/events{/privacy}","received_events_url":"https://api.github.com/users/nickbabcock/received_events","type":"User","site_admin":false},"body":"A hefty chunk of documentation on validation that covers previously undocumented features and updates others. I made it into it's own page due to its length. If this is not desired (due to potentially broken links to the documentation), I can merge it back\r\n\r\n**The documentation is currently not accurate (so it may not be a good idea to merge just yet)**: as\r\n\r\n```java\r\n@PUT\r\n@Valid\r\npublic Person replace(@Valid Person person) {\r\n    // Oops, we got a bug, a person can't have a null name\r\n    return new Person(null);\r\n}\r\n```\r\n\r\nwill return a `200 OK` and not `500 Internal Server Error`. \r\n\r\nLet me know if there are any corrections/suggestions.","created_at":"2015-06-02T20:59:24Z","updated_at":"2015-06-03T14:46:17Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e9970e1b0709e2f8253e3dbbd49467f25cb0b151","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/dropwizard/dropwizard/pulls/1091/commits","review_comments_url":"https://api.github.com/repos/dropwizard/dropwizard/pulls/1091/comments","review_comment_url":"https://api.github.com/repos/dropwizard/dropwizard/pulls/comments{/number}","comments_url":"https://api.github.com/repos/dropwizard/dropwizard/issues/1091/comments","statuses_url":"https://api.github.com/repos/dropwizard/dropwizard/statuses/6ab00e39ddee5f2be746860613a5056678495b8e","head":{"label":"nickbabcock:validation-docs","ref":"validation-docs","sha":"6ab00e39ddee5f2be746860613a5056678495b8e","user":{"login":"nickbabcock","id":2106129,"avatar_url":"https://avatars.githubusercontent.com/u/2106129?v=3","gravatar_id":"","url":"https://api.github.com/users/nickbabcock","html_url":"https://github.com/nickbabcock","followers_url":"https://api.github.com/users/nickbabcock/followers","following_url":"https://api.github.com/users/nickbabcock/following{/other_user}","gists_url":"https://api.github.com/users/nickbabcock/gists{/gist_id}","starred_url":"https://api.github.com/users/nickbabcock/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nickbabcock/subscriptions","organizations_url":"https://api.github.com/users/nickbabcock/orgs","repos_url":"https://api.github.com/users/nickbabcock/repos","events_url":"https://api.github.com/users/nickbabcock/events{/privacy}","received_events_url":"https://api.github.com/users/nickbabcock/received_events","type":"User","site_admin":false},"repo":{"id":18115354,"name":"dropwizard","full_name":"nickbabcock/dropwizard","owner":{"login":"nickbabcock","id":2106129,"avatar_url":"https://avatars.githubusercontent.com/u/2106129?v=3","gravatar_id":"","url":"https://api.github.com/users/nickbabcock","html_url":"https://github.com/nickbabcock","followers_url":"https://api.github.com/users/nickbabcock/followers","following_url":"https://api.github.com/users/nickbabcock/following{/other_user}","gists_url":"https://api.github.com/users/nickbabcock/gists{/gist_id}","starred_url":"https://api.github.com/users/nickbabcock/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nickbabcock/subscriptions","organizations_url":"https://api.github.com/users/nickbabcock/orgs","repos_url":"https://api.github.com/users/nickbabcock/repos","events_url":"https://api.github.com/users/nickbabcock/events{/privacy}","received_events_url":"https://api.github.com/users/nickbabcock/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/nickbabcock/dropwizard","description":"A damn simple library for building production-ready RESTful web services.","fork":true,"url":"https://api.github.com/repos/nickbabcock/dropwizard","forks_url":"https://api.github.com/repos/nickbabcock/dropwizard/forks","keys_url":"https://api.github.com/repos/nickbabcock/dropwizard/keys{/key_id}","collaborators_url":"https://api.github.com/repos/nickbabcock/dropwizard/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/nickbabcock/dropwizard/teams","hooks_url":"https://api.github.com/repos/nickbabcock/dropwizard/hooks","issue_events_url":"https://api.github.com/repos/nickbabcock/dropwizard/issues/events{/number}","events_url":"https://api.github.com/repos/nickbabcock/dropwizard/events","assignees_url":"https://api.github.com/repos/nickbabcock/dropwizard/assignees{/user}","branches_url":"https://api.github.com/repos/nickbabcock/dropwizard/branches{/branch}","tags_url":"https://api.github.com/repos/nickbabcock/dropwizard/tags","blobs_url":"https://api.github.com/repos/nickbabcock/dropwizard/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/nickbabcock/dropwizard/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/nickbabcock/dropwizard/git/refs{/sha}","trees_url":"https://api.github.com/repos/nickbabcock/dropwizard/git/trees{/sha}","statuses_url":"https://api.github.com/repos/nickbabcock/dropwizard/statuses/{sha}","languages_url":"https://api.github.com/repos/nickbabcock/dropwizard/languages","stargazers_url":"https://api.github.com/repos/nickbabcock/dropwizard/stargazers","contributors_url":"https://api.github.com/repos/nickbabcock/dropwizard/contributors","subscribers_url":"https://api.github.com/repos/nickbabcock/dropwizard/subscribers","subscription_url":"https://api.github.com/repos/nickbabcock/dropwizard/subscription","commits_url":"https://api.github.com/repos/nickbabcock/dropwizard/commits{/sha}","git_commits_url":"https://api.github.com/repos/nickbabcock/dropwizard/git/commits{/sha}","comments_url":"https://api.github.com/repos/nickbabcock/dropwizard/comments{/number}","issue_comment_url":"https://api.github.com/repos/nickbabcock/dropwizard/issues/comments{/number}","contents_url":"https://api.github.com/repos/nickbabcock/dropwizard/contents/{+path}","compare_url":"https://api.github.com/repos/nickbabcock/dropwizard/compare/{base}...{head}","merges_url":"https://api.github.com/repos/nickbabcock/dropwizard/merges","archive_url":"https://api.github.com/repos/nickbabcock/dropwizard/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/nickbabcock/dropwizard/downloads","issues_url":"https://api.github.com/repos/nickbabcock/dropwizard/issues{/number}","pulls_url":"https://api.github.com/repos/nickbabcock/dropwizard/pulls{/number}","milestones_url":"https://api.github.com/repos/nickbabcock/dropwizard/milestones{/number}","notifications_url":"https://api.github.com/repos/nickbabcock/dropwizard/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/nickbabcock/dropwizard/labels{/name}","releases_url":"https://api.github.com/repos/nickbabcock/dropwizard/releases{/id}","created_at":"2014-03-25T20:24:18Z","updated_at":"2015-04-17T18:15:07Z","pushed_at":"2015-06-02T20:27:15Z","git_url":"git://github.com/nickbabcock/dropwizard.git","ssh_url":"git@github.com:nickbabcock/dropwizard.git","clone_url":"https://github.com/nickbabcock/dropwizard.git","svn_url":"https://github.com/nickbabcock/dropwizard","homepage":"http://www.dropwizard.io","size":6582,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"dropwizard:master","ref":"master","sha":"398b9c9dc8dfa4ab6d5ef4da2e5ef0fb052413c5","user":{"login":"dropwizard","id":5478557,"avatar_url":"https://avatars.githubusercontent.com/u/5478557?v=3","gravatar_id":"","url":"https://api.github.com/users/dropwizard","html_url":"https://github.com/dropwizard","followers_url":"https://api.github.com/users/dropwizard/followers","following_url":"https://api.github.com/users/dropwizard/following{/other_user}","gists_url":"https://api.github.com/users/dropwizard/gists{/gist_id}","starred_url":"https://api.github.com/users/dropwizard/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dropwizard/subscriptions","organizations_url":"https://api.github.com/users/dropwizard/orgs","repos_url":"https://api.github.com/users/dropwizard/repos","events_url":"https://api.github.com/users/dropwizard/events{/privacy}","received_events_url":"https://api.github.com/users/dropwizard/received_events","type":"Organization","site_admin":false},"repo":{"id":1272129,"name":"dropwizard","full_name":"dropwizard/dropwizard","owner":{"login":"dropwizard","id":5478557,"avatar_url":"https://avatars.githubusercontent.com/u/5478557?v=3","gravatar_id":"","url":"https://api.github.com/users/dropwizard","html_url":"https://github.com/dropwizard","followers_url":"https://api.github.com/users/dropwizard/followers","following_url":"https://api.github.com/users/dropwizard/following{/other_user}","gists_url":"https://api.github.com/users/dropwizard/gists{/gist_id}","starred_url":"https://api.github.com/users/dropwizard/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dropwizard/subscriptions","organizations_url":"https://api.github.com/users/dropwizard/orgs","repos_url":"https://api.github.com/users/dropwizard/repos","events_url":"https://api.github.com/users/dropwizard/events{/privacy}","received_events_url":"https://api.github.com/users/dropwizard/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/dropwizard/dropwizard","description":"A damn simple library for building production-ready RESTful web services.","fork":false,"url":"https://api.github.com/repos/dropwizard/dropwizard","forks_url":"https://api.github.com/repos/dropwizard/dropwizard/forks","keys_url":"https://api.github.com/repos/dropwizard/dropwizard/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dropwizard/dropwizard/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dropwizard/dropwizard/teams","hooks_url":"https://api.github.com/repos/dropwizard/dropwizard/hooks","issue_events_url":"https://api.github.com/repos/dropwizard/dropwizard/issues/events{/number}","events_url":"https://api.github.com/repos/dropwizard/dropwizard/events","assignees_url":"https://api.github.com/repos/dropwizard/dropwizard/assignees{/user}","branches_url":"https://api.github.com/repos/dropwizard/dropwizard/branches{/branch}","tags_url":"https://api.github.com/repos/dropwizard/dropwizard/tags","blobs_url":"https://api.github.com/repos/dropwizard/dropwizard/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dropwizard/dropwizard/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dropwizard/dropwizard/git/refs{/sha}","trees_url":"https://api.github.com/repos/dropwizard/dropwizard/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dropwizard/dropwizard/statuses/{sha}","languages_url":"https://api.github.com/repos/dropwizard/dropwizard/languages","stargazers_url":"https://api.github.com/repos/dropwizard/dropwizard/stargazers","contributors_url":"https://api.github.com/repos/dropwizard/dropwizard/contributors","subscribers_url":"https://api.github.com/repos/dropwizard/dropwizard/subscribers","subscription_url":"https://api.github.com/repos/dropwizard/dropwizard/subscription","commits_url":"https://api.github.com/repos/dropwizard/dropwizard/commits{/sha}","git_commits_url":"https://api.github.com/repos/dropwizard/dropwizard/git/commits{/sha}","comments_url":"https://api.github.com/repos/dropwizard/dropwizard/comments{/number}","issue_comment_url":"https://api.github.com/repos/dropwizard/dropwizard/issues/comments{/number}","contents_url":"https://api.github.com/repos/dropwizard/dropwizard/contents/{+path}","compare_url":"https://api.github.com/repos/dropwizard/dropwizard/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dropwizard/dropwizard/merges","archive_url":"https://api.github.com/repos/dropwizard/dropwizard/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dropwizard/dropwizard/downloads","issues_url":"https://api.github.com/repos/dropwizard/dropwizard/issues{/number}","pulls_url":"https://api.github.com/repos/dropwizard/dropwizard/pulls{/number}","milestones_url":"https://api.github.com/repos/dropwizard/dropwizard/milestones{/number}","notifications_url":"https://api.github.com/repos/dropwizard/dropwizard/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dropwizard/dropwizard/labels{/name}","releases_url":"https://api.github.com/repos/dropwizard/dropwizard/releases{/id}","created_at":"2011-01-19T19:52:29Z","updated_at":"2015-06-03T07:03:56Z","pushed_at":"2015-06-03T08:39:27Z","git_url":"git://github.com/dropwizard/dropwizard.git","ssh_url":"git@github.com:dropwizard/dropwizard.git","clone_url":"https://github.com/dropwizard/dropwizard.git","svn_url":"https://github.com/dropwizard/dropwizard","homepage":"http://www.dropwizard.io","size":29872,"stargazers_count":3350,"watchers_count":3350,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":1380,"mirror_url":null,"open_issues_count":47,"forks":1380,"open_issues":47,"watchers":3350,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/dropwizard/dropwizard/pulls/1091"},"html":{"href":"https://github.com/dropwizard/dropwizard/pull/1091"},"issue":{"href":"https://api.github.com/repos/dropwizard/dropwizard/issues/1091"},"comments":{"href":"https://api.github.com/repos/dropwizard/dropwizard/issues/1091/comments"},"review_comments":{"href":"https://api.github.com/repos/dropwizard/dropwizard/pulls/1091/comments"},"review_comment":{"href":"https://api.github.com/repos/dropwizard/dropwizard/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/dropwizard/dropwizard/pulls/1091/commits"},"statuses":{"href":"https://api.github.com/repos/dropwizard/dropwizard/statuses/6ab00e39ddee5f2be746860613a5056678495b8e"}}}}