{"action":"created","issue":{"url":"https://api.github.com/repos/slick/slick/issues/1558","repository_url":"https://api.github.com/repos/slick/slick","labels_url":"https://api.github.com/repos/slick/slick/issues/1558/labels{/name}","comments_url":"https://api.github.com/repos/slick/slick/issues/1558/comments","events_url":"https://api.github.com/repos/slick/slick/issues/1558/events","html_url":"https://github.com/slick/slick/issues/1558","id":164872901,"number":1558,"title":"Transaction (and atomicity) when composing in futures does not work","user":{"login":"bcatarinoyoti","id":16239636,"avatar_url":"https://avatars.githubusercontent.com/u/16239636?v=3","gravatar_id":"","url":"https://api.github.com/users/bcatarinoyoti","html_url":"https://github.com/bcatarinoyoti","followers_url":"https://api.github.com/users/bcatarinoyoti/followers","following_url":"https://api.github.com/users/bcatarinoyoti/following{/other_user}","gists_url":"https://api.github.com/users/bcatarinoyoti/gists{/gist_id}","starred_url":"https://api.github.com/users/bcatarinoyoti/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bcatarinoyoti/subscriptions","organizations_url":"https://api.github.com/users/bcatarinoyoti/orgs","repos_url":"https://api.github.com/users/bcatarinoyoti/repos","events_url":"https://api.github.com/users/bcatarinoyoti/events{/privacy}","received_events_url":"https://api.github.com/users/bcatarinoyoti/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":6,"created_at":"2016-07-11T16:00:00Z","updated_at":"2016-07-13T15:38:20Z","closed_at":null,"body":"I'm having a really hard time to figure out how to properly use transactions at my controller level in slick. I'm finding it hard to believe it's not possible at all, since a lot of real world use cases require that. \r\n\r\nI can understand how composing by query or action is preferable and that transactionality in those cases just works. However, considering code like this:\r\n\r\n```\r\nclass UserController @Inject(userService: UserService) {\r\n  def register(userData: UserData) = {\r\n    userService.save(userData).map(result => Ok(result))\r\n  }\r\n}\r\n\r\nclass UserService @Inject(userDao: UserDao, addressDao: AddressDao) {\r\n  def save(userData: UserData) = {\r\n    for {\r\n      savedUser <- userDao.save(userData.toUser)\r\n// A lot of complex logic that makes checks and validates stuff\r\n      savedAddress <- addressDao.save(userData.addressData.toAddress)\r\n    } yield savedUser.copy(address = savedAddress)\r\n  }\r\n}\r\n\r\nclass SlickUserDao {\r\n  def save(user: User) = {\r\n    db.run((UserSchema.users returning UserSchema.users)).insertOrUpdate(user)\r\n  }\r\n}\r\n```\r\n\r\nUserService calls two Daos to do inserts. I want the execution of my controller to be atomic and both operations should be commited or none at all.\r\n\r\nOn the other hand, UserService is my business layer. I have loads of business logic here (despite the simplified example) and I want it to be just that: business code. I don't want it polluted with framework specific dependencies, such as slick, so return DBActions and explicitly calling `database.run(action)` is not an option. \r\n\r\nI tried to create my own session handling code, despite the fact it forces me to pass my session identifier between methods in my business layer, as well as start and end the transaction, which is also not ideal, but I was hoping to tidy it up a bit more after I got it working.\r\n\r\n```\r\nobject DB {\r\n\r\n  val sessions = Map[String, JdbcBackend.Session]()\r\n\r\n  val nightclub = JdbcBackend.Database.forConfig(\"nightclub\")\r\n\r\n  def createSession(): String = {\r\n    val session = nightclub.createSession()\r\n    session.conn.setAutoCommit(false)\r\n    val uuid = UUID.randomUUID().toString\r\n    sessions += (uuid -> session)\r\n    uuid\r\n  }\r\n\r\n  def execute[R](action: DBIOAction[R, NoStream, Effect.All])(implicit uuidOption: Option[String] = None): Future[R] = {\r\n\r\n    uuidOption match {\r\n      case None => nightclub.run(action)\r\n      case Some(uuid) => sessions.get(uuid) match {\r\n        case None => throw new IllegalStateException(\"No database session opened\")\r\n        case Some(sess) =>\r\n          sess.database.run(action)\r\n      }\r\n    }\r\n  }\r\n\r\n  def closeSession(uuid: String): Unit = {\r\n    sessions.get(uuid) match {\r\n      case Some(session) =>\r\n        sessions -= uuid\r\n        session.close()\r\n    }\r\n  }\r\n}\r\n```\r\n\r\nExcept it doesn't work. It's auto-committing every single `database.run` I do. Is `sess.database.run(action)` not \r\nrunning it within the session? I tried using `withPinnedSession` as well, but it also doesn't work.\r\n\r\nAny help would be welcome. I find hard to believe Slick doesn't provide a way to handle these use cases. Pretty much every other persistence framework I used in the past does, one way or another. I must be missing something.\r\n\r\nThanks"},"comment":{"url":"https://api.github.com/repos/slick/slick/issues/comments/232394955","html_url":"https://github.com/slick/slick/issues/1558#issuecomment-232394955","issue_url":"https://api.github.com/repos/slick/slick/issues/1558","id":232394955,"user":{"login":"cvogt","id":274947,"avatar_url":"https://avatars.githubusercontent.com/u/274947?v=3","gravatar_id":"","url":"https://api.github.com/users/cvogt","html_url":"https://github.com/cvogt","followers_url":"https://api.github.com/users/cvogt/followers","following_url":"https://api.github.com/users/cvogt/following{/other_user}","gists_url":"https://api.github.com/users/cvogt/gists{/gist_id}","starred_url":"https://api.github.com/users/cvogt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cvogt/subscriptions","organizations_url":"https://api.github.com/users/cvogt/orgs","repos_url":"https://api.github.com/users/cvogt/repos","events_url":"https://api.github.com/users/cvogt/events{/privacy}","received_events_url":"https://api.github.com/users/cvogt/received_events","type":"User","site_admin":false},"created_at":"2016-07-13T15:38:20Z","updated_at":"2016-07-13T15:38:20Z","body":"closing in favor of this: #1563"}}
{"actor":{"display_login":"cvogt"}}