{"action":"created","comment":{"url":"https://api.github.com/repos/playframework/playframework/pulls/comments/92428553","pull_request_review_id":12942441,"id":92428553,"diff_hunk":"@@ -76,58 +77,85 @@ public EntityManager em(String name) {\n     }\n \n     /**\n-     * Get the EntityManager for a particular persistence unit for this thread.\n-     *\n-     * @return EntityManager for the specified persistence unit name\n-     */\n-    public EntityManager em() {\n-        return entityManagerContext.em();\n-    }\n-\n-    /**\n-     * Run a block of code with the EntityManager for the named Persistence Unit.\n+     * Run a block of code with a newly created EntityManager.\n      *\n      * @param block Block of code to execute\n      * @param <T> type of result\n      * @return code execution result\n      */\n+    @Override\n     public <T> T withTransaction(Function<EntityManager, T> block) {\n-        return withTransaction(\"default\", false, block);\n+        return withTransaction(\"default\", block);\n     }\n \n     /**\n-     * Run a block of code with the EntityManager for the named Persistence Unit.\n+     * Run a block of code with a newly created EntityManager for the named Persistence Unit.\n      *\n      * @param name The persistence unit name\n      * @param block Block of code to execute\n      * @param <T> type of result\n      * @return code execution result\n      */\n+    @Override\n     public <T> T withTransaction(String name, Function<EntityManager, T> block) {\n         return withTransaction(name, false, block);\n     }\n \n     /**\n-     * Run a block of code with the EntityManager for the named Persistence Unit.\n+     * Run a block of code with a newly created EntityManager for the named Persistence Unit.\n      *\n      * @param name The persistence unit name\n      * @param readOnly Is the transaction read-only?\n      * @param block Block of code to execute\n      * @param <T> type of result\n      * @return code execution result\n      */\n+    @Override\n     public <T> T withTransaction(String name, boolean readOnly, Function<EntityManager, T> block) {\n+        return withTransaction(name, readOnly, null, block);\n+    }\n+    \n+    /**\n+     * Run a block of code with a newly created EntityManager for the named Persistence Unit.\n+     *\n+     * @param name The persistence unit name\n+     * @param readOnly Is the transaction read-only?\n+     * @param ctx Store the entity manager in this context?\n+     * @param block Block of code to execute\n+     * @param <T> type of result\n+     * @return code execution result\n+     */\n+    @Override\n+    public <T> T withTransaction(String name, boolean readOnly, Http.Context ctx, Function<EntityManager, T> block) {\n+        return withTransaction(name, readOnly, ctx, false, block);\n+    }\n+    \n+    /**\n+     * Run a block of code with a newly created EntityManager for the named Persistence Unit.\n+     *\n+     * @param name The persistence unit name\n+     * @param readOnly Is the transaction read-only?\n+     * @param ctx Store the entity manager in this context?\n+     * @param keepTransactionOpen Don't commit nor rollback transaction. Also keeps the active entity manager stored in the given ctx (if supplied).\n+     * @param block Block of code to execute\n+     * @param <T> type of result\n+     * @return code execution result\n+     */\n+    @Override\n+    public <T> T withTransaction(String name, boolean readOnly, Http.Context ctx, boolean keepTransactionOpen, Function<EntityManager, T> block) {","path":"framework/src/play-java-jpa/src/main/java/play/db/jpa/DefaultJPAApi.java","position":143,"original_position":143,"commit_id":"4750f1fa71eddafab011c9ab186c2c1a1f653c72","original_commit_id":"4750f1fa71eddafab011c9ab186c2c1a1f653c72","user":{"login":"marcospereira","id":4576,"avatar_url":"https://avatars.githubusercontent.com/u/4576?v=3","gravatar_id":"","url":"https://api.github.com/users/marcospereira","html_url":"https://github.com/marcospereira","followers_url":"https://api.github.com/users/marcospereira/followers","following_url":"https://api.github.com/users/marcospereira/following{/other_user}","gists_url":"https://api.github.com/users/marcospereira/gists{/gist_id}","starred_url":"https://api.github.com/users/marcospereira/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/marcospereira/subscriptions","organizations_url":"https://api.github.com/users/marcospereira/orgs","repos_url":"https://api.github.com/users/marcospereira/repos","events_url":"https://api.github.com/users/marcospereira/events{/privacy}","received_events_url":"https://api.github.com/users/marcospereira/received_events","type":"User","site_admin":false},"body":"I think we are mixing layers here. We now have the (lower) Persistence layer depending on the (higher) HTTP layer. One implication here is now that to test a model/service object, I will need a `Http.Context`.","created_at":"2016-12-14T16:16:34Z","updated_at":"2016-12-14T16:48:56Z","html_url":"https://github.com/playframework/playframework/pull/6777#discussion_r92428553","pull_request_url":"https://api.github.com/repos/playframework/playframework/pulls/6777","_links":{"self":{"href":"https://api.github.com/repos/playframework/playframework/pulls/comments/92428553"},"html":{"href":"https://github.com/playframework/playframework/pull/6777#discussion_r92428553"},"pull_request":{"href":"https://api.github.com/repos/playframework/playframework/pulls/6777"}}},"pull_request":{"url":"https://api.github.com/repos/playframework/playframework/pulls/6777","id":96568539,"html_url":"https://github.com/playframework/playframework/pull/6777","diff_url":"https://github.com/playframework/playframework/pull/6777.diff","patch_url":"https://github.com/playframework/playframework/pull/6777.patch","issue_url":"https://api.github.com/repos/playframework/playframework/issues/6777","number":6777,"state":"open","locked":false,"title":"Refactoring play-jpa - Got rid of ThreadLocal","user":{"login":"mkurz","id":644927,"avatar_url":"https://avatars.githubusercontent.com/u/644927?v=3","gravatar_id":"","url":"https://api.github.com/users/mkurz","html_url":"https://github.com/mkurz","followers_url":"https://api.github.com/users/mkurz/followers","following_url":"https://api.github.com/users/mkurz/following{/other_user}","gists_url":"https://api.github.com/users/mkurz/gists{/gist_id}","starred_url":"https://api.github.com/users/mkurz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mkurz/subscriptions","organizations_url":"https://api.github.com/users/mkurz/orgs","repos_url":"https://api.github.com/users/mkurz/repos","events_url":"https://api.github.com/users/mkurz/events{/privacy}","received_events_url":"https://api.github.com/users/mkurz/received_events","type":"User","site_admin":false},"body":"Replaces #6013\r\n\r\nAs we know to run code within a JPA transaction the preferred way is to call\r\n```java\r\n// inject jpaApi\r\njpaApi.withTransaction(em -> ...)\r\n```\r\nWith this PR an entity manager now **always** gets passed to all the various `withTransaction` methods. The em doesn't get stored in a `ThreadLocal` anymore.\r\n\r\nOnly when using `@Transactional` the entity manager still will be stored in the `Http.Context` so we can access and (re-)use it later from within the controller's action methods. But I did change how this happens. Instead of just accessing `Http.Context.current()` you now have to explicitly pass the `context` in which the em should get stored to `withTransaction` (happens in `TransactionalAction.java`).\r\nEventually, to retrieve the em we now have to pass a context to `JPA.em(ctx)`.\r\n\r\nWith this changes `JPAEntityManagerContext` is becoming \"just\" a simple helper class which just makes it easier to store and read entity managers from a http context.\r\n\r\nIn future we can remove `JPA.em()` (it's deprecated now) in favor of `JPA.em(ctx)` - actually it's just a shortcut for `JPAEntityManagerContext.em(ctx)`.\r\n\r\nThis should make `play-jpa` ready for the removal of the http context threadlocal which I think is targeted for a future play version. (It should work nicely with the changes in #6473 done by @gmethvin)\r\n\r\nOne more thing:\r\nIn `@TransactionalAction` we tell `withTransaction` to keep the em and transaction open so it doesn't get closed immediately but only after the future has completed. I am not entirely sure if this should be managed here or if I should add a `withTransaction` that returns a `CompletionStage<T>` and manage it there. Related to #6489","created_at":"2016-12-05T17:02:50Z","updated_at":"2016-12-14T16:48:56Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a27ffe989a80fcf0be3271f0d17b6ef9efb80124","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/playframework/playframework/pulls/6777/commits","review_comments_url":"https://api.github.com/repos/playframework/playframework/pulls/6777/comments","review_comment_url":"https://api.github.com/repos/playframework/playframework/pulls/comments{/number}","comments_url":"https://api.github.com/repos/playframework/playframework/issues/6777/comments","statuses_url":"https://api.github.com/repos/playframework/playframework/statuses/4750f1fa71eddafab011c9ab186c2c1a1f653c72","head":{"label":"mkurz:jpaRefactor","ref":"jpaRefactor","sha":"4750f1fa71eddafab011c9ab186c2c1a1f653c72","user":{"login":"mkurz","id":644927,"avatar_url":"https://avatars.githubusercontent.com/u/644927?v=3","gravatar_id":"","url":"https://api.github.com/users/mkurz","html_url":"https://github.com/mkurz","followers_url":"https://api.github.com/users/mkurz/followers","following_url":"https://api.github.com/users/mkurz/following{/other_user}","gists_url":"https://api.github.com/users/mkurz/gists{/gist_id}","starred_url":"https://api.github.com/users/mkurz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mkurz/subscriptions","organizations_url":"https://api.github.com/users/mkurz/orgs","repos_url":"https://api.github.com/users/mkurz/repos","events_url":"https://api.github.com/users/mkurz/events{/privacy}","received_events_url":"https://api.github.com/users/mkurz/received_events","type":"User","site_admin":false},"repo":{"id":17720374,"name":"playframework","full_name":"mkurz/playframework","owner":{"login":"mkurz","id":644927,"avatar_url":"https://avatars.githubusercontent.com/u/644927?v=3","gravatar_id":"","url":"https://api.github.com/users/mkurz","html_url":"https://github.com/mkurz","followers_url":"https://api.github.com/users/mkurz/followers","following_url":"https://api.github.com/users/mkurz/following{/other_user}","gists_url":"https://api.github.com/users/mkurz/gists{/gist_id}","starred_url":"https://api.github.com/users/mkurz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mkurz/subscriptions","organizations_url":"https://api.github.com/users/mkurz/orgs","repos_url":"https://api.github.com/users/mkurz/repos","events_url":"https://api.github.com/users/mkurz/events{/privacy}","received_events_url":"https://api.github.com/users/mkurz/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mkurz/playframework","description":"Play Framework","fork":true,"url":"https://api.github.com/repos/mkurz/playframework","forks_url":"https://api.github.com/repos/mkurz/playframework/forks","keys_url":"https://api.github.com/repos/mkurz/playframework/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mkurz/playframework/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mkurz/playframework/teams","hooks_url":"https://api.github.com/repos/mkurz/playframework/hooks","issue_events_url":"https://api.github.com/repos/mkurz/playframework/issues/events{/number}","events_url":"https://api.github.com/repos/mkurz/playframework/events","assignees_url":"https://api.github.com/repos/mkurz/playframework/assignees{/user}","branches_url":"https://api.github.com/repos/mkurz/playframework/branches{/branch}","tags_url":"https://api.github.com/repos/mkurz/playframework/tags","blobs_url":"https://api.github.com/repos/mkurz/playframework/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mkurz/playframework/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mkurz/playframework/git/refs{/sha}","trees_url":"https://api.github.com/repos/mkurz/playframework/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mkurz/playframework/statuses/{sha}","languages_url":"https://api.github.com/repos/mkurz/playframework/languages","stargazers_url":"https://api.github.com/repos/mkurz/playframework/stargazers","contributors_url":"https://api.github.com/repos/mkurz/playframework/contributors","subscribers_url":"https://api.github.com/repos/mkurz/playframework/subscribers","subscription_url":"https://api.github.com/repos/mkurz/playframework/subscription","commits_url":"https://api.github.com/repos/mkurz/playframework/commits{/sha}","git_commits_url":"https://api.github.com/repos/mkurz/playframework/git/commits{/sha}","comments_url":"https://api.github.com/repos/mkurz/playframework/comments{/number}","issue_comment_url":"https://api.github.com/repos/mkurz/playframework/issues/comments{/number}","contents_url":"https://api.github.com/repos/mkurz/playframework/contents/{+path}","compare_url":"https://api.github.com/repos/mkurz/playframework/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mkurz/playframework/merges","archive_url":"https://api.github.com/repos/mkurz/playframework/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mkurz/playframework/downloads","issues_url":"https://api.github.com/repos/mkurz/playframework/issues{/number}","pulls_url":"https://api.github.com/repos/mkurz/playframework/pulls{/number}","milestones_url":"https://api.github.com/repos/mkurz/playframework/milestones{/number}","notifications_url":"https://api.github.com/repos/mkurz/playframework/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mkurz/playframework/labels{/name}","releases_url":"https://api.github.com/repos/mkurz/playframework/releases{/id}","deployments_url":"https://api.github.com/repos/mkurz/playframework/deployments","created_at":"2014-03-13T17:52:40Z","updated_at":"2016-02-26T09:30:55Z","pushed_at":"2016-12-13T17:03:10Z","git_url":"git://github.com/mkurz/playframework.git","ssh_url":"git@github.com:mkurz/playframework.git","clone_url":"https://github.com/mkurz/playframework.git","svn_url":"https://github.com/mkurz/playframework","homepage":"http://www.playframework.com/","size":84304,"stargazers_count":0,"watchers_count":0,"language":"Scala","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"playframework:master","ref":"master","sha":"f4e84ba984da9e309f2d9481ab6cf3e9f03a0206","user":{"login":"playframework","id":319107,"avatar_url":"https://avatars.githubusercontent.com/u/319107?v=3","gravatar_id":"","url":"https://api.github.com/users/playframework","html_url":"https://github.com/playframework","followers_url":"https://api.github.com/users/playframework/followers","following_url":"https://api.github.com/users/playframework/following{/other_user}","gists_url":"https://api.github.com/users/playframework/gists{/gist_id}","starred_url":"https://api.github.com/users/playframework/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/playframework/subscriptions","organizations_url":"https://api.github.com/users/playframework/orgs","repos_url":"https://api.github.com/users/playframework/repos","events_url":"https://api.github.com/users/playframework/events{/privacy}","received_events_url":"https://api.github.com/users/playframework/received_events","type":"Organization","site_admin":false},"repo":{"id":2340549,"name":"playframework","full_name":"playframework/playframework","owner":{"login":"playframework","id":319107,"avatar_url":"https://avatars.githubusercontent.com/u/319107?v=3","gravatar_id":"","url":"https://api.github.com/users/playframework","html_url":"https://github.com/playframework","followers_url":"https://api.github.com/users/playframework/followers","following_url":"https://api.github.com/users/playframework/following{/other_user}","gists_url":"https://api.github.com/users/playframework/gists{/gist_id}","starred_url":"https://api.github.com/users/playframework/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/playframework/subscriptions","organizations_url":"https://api.github.com/users/playframework/orgs","repos_url":"https://api.github.com/users/playframework/repos","events_url":"https://api.github.com/users/playframework/events{/privacy}","received_events_url":"https://api.github.com/users/playframework/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/playframework/playframework","description":"Play Framework","fork":false,"url":"https://api.github.com/repos/playframework/playframework","forks_url":"https://api.github.com/repos/playframework/playframework/forks","keys_url":"https://api.github.com/repos/playframework/playframework/keys{/key_id}","collaborators_url":"https://api.github.com/repos/playframework/playframework/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/playframework/playframework/teams","hooks_url":"https://api.github.com/repos/playframework/playframework/hooks","issue_events_url":"https://api.github.com/repos/playframework/playframework/issues/events{/number}","events_url":"https://api.github.com/repos/playframework/playframework/events","assignees_url":"https://api.github.com/repos/playframework/playframework/assignees{/user}","branches_url":"https://api.github.com/repos/playframework/playframework/branches{/branch}","tags_url":"https://api.github.com/repos/playframework/playframework/tags","blobs_url":"https://api.github.com/repos/playframework/playframework/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/playframework/playframework/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/playframework/playframework/git/refs{/sha}","trees_url":"https://api.github.com/repos/playframework/playframework/git/trees{/sha}","statuses_url":"https://api.github.com/repos/playframework/playframework/statuses/{sha}","languages_url":"https://api.github.com/repos/playframework/playframework/languages","stargazers_url":"https://api.github.com/repos/playframework/playframework/stargazers","contributors_url":"https://api.github.com/repos/playframework/playframework/contributors","subscribers_url":"https://api.github.com/repos/playframework/playframework/subscribers","subscription_url":"https://api.github.com/repos/playframework/playframework/subscription","commits_url":"https://api.github.com/repos/playframework/playframework/commits{/sha}","git_commits_url":"https://api.github.com/repos/playframework/playframework/git/commits{/sha}","comments_url":"https://api.github.com/repos/playframework/playframework/comments{/number}","issue_comment_url":"https://api.github.com/repos/playframework/playframework/issues/comments{/number}","contents_url":"https://api.github.com/repos/playframework/playframework/contents/{+path}","compare_url":"https://api.github.com/repos/playframework/playframework/compare/{base}...{head}","merges_url":"https://api.github.com/repos/playframework/playframework/merges","archive_url":"https://api.github.com/repos/playframework/playframework/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/playframework/playframework/downloads","issues_url":"https://api.github.com/repos/playframework/playframework/issues{/number}","pulls_url":"https://api.github.com/repos/playframework/playframework/pulls{/number}","milestones_url":"https://api.github.com/repos/playframework/playframework/milestones{/number}","notifications_url":"https://api.github.com/repos/playframework/playframework/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/playframework/playframework/labels{/name}","releases_url":"https://api.github.com/repos/playframework/playframework/releases{/id}","deployments_url":"https://api.github.com/repos/playframework/playframework/deployments","created_at":"2011-09-07T09:24:08Z","updated_at":"2016-12-14T15:58:29Z","pushed_at":"2016-12-14T15:20:19Z","git_url":"git://github.com/playframework/playframework.git","ssh_url":"git@github.com:playframework/playframework.git","clone_url":"https://github.com/playframework/playframework.git","svn_url":"https://github.com/playframework/playframework","homepage":"http://www.playframework.com/","size":84793,"stargazers_count":8729,"watchers_count":8729,"language":"Scala","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":3008,"mirror_url":null,"open_issues_count":249,"forks":3008,"open_issues":249,"watchers":8729,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/playframework/playframework/pulls/6777"},"html":{"href":"https://github.com/playframework/playframework/pull/6777"},"issue":{"href":"https://api.github.com/repos/playframework/playframework/issues/6777"},"comments":{"href":"https://api.github.com/repos/playframework/playframework/issues/6777/comments"},"review_comments":{"href":"https://api.github.com/repos/playframework/playframework/pulls/6777/comments"},"review_comment":{"href":"https://api.github.com/repos/playframework/playframework/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/playframework/playframework/pulls/6777/commits"},"statuses":{"href":"https://api.github.com/repos/playframework/playframework/statuses/4750f1fa71eddafab011c9ab186c2c1a1f653c72"}}}}
{"actor":{"display_login":"marcospereira"}}