{"action":"created","comment":{"url":"https://api.github.com/repos/lagom/lagom/pulls/comments/90790705","pull_request_review_id":11306299,"id":90790705,"diff_hunk":"@@ -0,0 +1,109 @@\n+# Implementing services\n+\n+Services are implemented by providing an implementation of the service descriptor trait, implementing each call specified by that descriptor.\n+\n+For example, here's an implementation of the `HelloService` descriptor:\n+\n+@[hello-service-impl](code/ServiceImplementation.scala)\n+\n+As you can see, the `sayHello` method is implemented using the `apply` factory method on [`ServiceCall`](api/com/lightbend/lagom/scaladsl/api/ServiceCall$.html). This takes a function of `Request => Future[Response]` and returns a [`ServiceCall`](api/com/lightbend/lagom/scaladsl/api/ServiceCall.html) whose `invoke` method simply delegates to that function.  An important thing to realise here is that the invocation of `sayHello` itself does not execute the call, it only returns the service call to be executed.  The advantage here is that when it comes to composing the call with other cross cutting concerns, such as authentication, this can easily be done using ordinary function based composition.\n+\n+Let's have a look at our [`ServiceCall`](api/com/lightbend/lagom/scaladsl/api/ServiceCall.html) interface again:\n+\n+@[service-call](code/ServiceDescriptors.scala)\n+\n+It will take the request, and return the response as a [`Future`](http://www.scala-lang.org/api/2.12.x/scala/concurrent/Future.html).  If you've never seen `Future` before, it is a value that may not be available until later.  When an API returns a future, that value might not yet be computed, but the API promises that at some point in future, it will be.  Since the value isn't computed yet, you can't interact with it immediately.  What you can do though is attach callbacks that transform the promise to a promise of a new value, using the `map` and `flatMap` methods.  `Future` with its `map` and `flatMap` methods are fundamental building blocks for doing reactive programming in Scala, they allow your code to be asynchronous, not waiting for things to happen, but attaching callbacks that react to computations being completed.\n+\n+Of course, a simple hello world computation is not asynchronous, all it needs is to do is build a String, and that returns immediately.  In this case, we need to wrap the result of that in a `Future`.  This can be done by calling `Future.successful()`, which returns a future that has an immediately available value.\n+\n+## Wiring together a Lagom application\n+\n+Having provided an implementation of the service, we can now register that with the Lagom framework.  Lagoms Scala API is built on top of Play Framework, and uses Play's [compile time dependency injection support](https://www.playframework.com/documentation/2.5.x/ScalaCompileTimeDependencyInjection) to wire together a Lagom application.\n+\n+Although it's not strictly necessary, we recommend that you use [Macwire](https://github.com/adamw/macwire) to assist in wiring dependencies together. Macwire provides some very lightweight macros that locate dependencies for the components you wish to create so that you don't have to manually wire them together yourself. Macwire can be added to your service by adding the following to your service implementations dependencies:\n+\n+@[macwire](code/macwire.sbt)\n+\n+Next we need to create an application cake. The simplest way of doing this is by creating an abstract class that extends [`LagomApplication`](api/com/lightbend/lagom/scaladsl/server/LagomApplication.html):\n+\n+@[lagom-application](code/ServiceImplementation.scala)\n+\n+The important method to implement here is the `lagomServer` method. Lagom will use this to discover your service bindings and create a Play router for handling your service calls. You can see that we've bound one service descriptor, the `HelloService`, to our `HelloServiceImpl` implementation. We've used Macwire's `wire` macro to wire the dependencies - at the moment our service actually has no dependencies so we could just construct it manually ourselves, but it's not likely that a real service implementation would have no dependencies.\n+\n+You can see that we've also mixed in the Play `AhcWSComponents` trait. Play's HTTP client, the WS API, which is used by Lagom for making service calls, is pluggable, and so an implementation needs to be selected when we wire our application together. We've selected Play's async-http-client implementation, provided by `AhcWSComponents`.\n+\n+The `HelloApplication` is an abstract class, the reason for this is that there is still one method that hasn't been implemented, the `serviceLocator` method. A typically application will use different service locators in different environments, in development, it will use the service locator provided by the Lagom development environment, while in production it will use whatever is appropriate for your production environment, such as the `ConductR` service locator implementation. So our main application cake leaves this method abstract so that it can mix in the right one depending on which mode it is in when the application gets loaded.","path":"docs/manual/scala/guide/services/ServiceImplementation.md","position":35,"original_position":35,"commit_id":"6f463c56db381e3e9e7ca6caa0fc1881ace9dfcc","original_commit_id":"6f463c56db381e3e9e7ca6caa0fc1881ace9dfcc","user":{"login":"jroper","id":105833,"avatar_url":"https://avatars.githubusercontent.com/u/105833?v=3","gravatar_id":"","url":"https://api.github.com/users/jroper","html_url":"https://github.com/jroper","followers_url":"https://api.github.com/users/jroper/followers","following_url":"https://api.github.com/users/jroper/following{/other_user}","gists_url":"https://api.github.com/users/jroper/gists{/gist_id}","starred_url":"https://api.github.com/users/jroper/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jroper/subscriptions","organizations_url":"https://api.github.com/users/jroper/orgs","repos_url":"https://api.github.com/users/jroper/repos","events_url":"https://api.github.com/users/jroper/events{/privacy}","received_events_url":"https://api.github.com/users/jroper/received_events","type":"User","site_admin":false},"body":"yep.","created_at":"2016-12-05T00:11:11Z","updated_at":"2016-12-05T00:11:11Z","html_url":"https://github.com/lagom/lagom/pull/317#discussion_r90790705","pull_request_url":"https://api.github.com/repos/lagom/lagom/pulls/317","_links":{"self":{"href":"https://api.github.com/repos/lagom/lagom/pulls/comments/90790705"},"html":{"href":"https://github.com/lagom/lagom/pull/317#discussion_r90790705"},"pull_request":{"href":"https://api.github.com/repos/lagom/lagom/pulls/317"}}},"pull_request":{"url":"https://api.github.com/repos/lagom/lagom/pulls/317","id":96196669,"html_url":"https://github.com/lagom/lagom/pull/317","diff_url":"https://github.com/lagom/lagom/pull/317.diff","patch_url":"https://github.com/lagom/lagom/pull/317.patch","issue_url":"https://api.github.com/repos/lagom/lagom/issues/317","number":317,"state":"open","locked":false,"title":"Added Scala implementing services documentation","user":{"login":"jroper","id":105833,"avatar_url":"https://avatars.githubusercontent.com/u/105833?v=3","gravatar_id":"","url":"https://api.github.com/users/jroper","html_url":"https://github.com/jroper","followers_url":"https://api.github.com/users/jroper/followers","following_url":"https://api.github.com/users/jroper/following{/other_user}","gists_url":"https://api.github.com/users/jroper/gists{/gist_id}","starred_url":"https://api.github.com/users/jroper/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jroper/subscriptions","organizations_url":"https://api.github.com/users/jroper/orgs","repos_url":"https://api.github.com/users/jroper/repos","events_url":"https://api.github.com/users/jroper/events{/privacy}","received_events_url":"https://api.github.com/users/jroper/received_events","type":"User","site_admin":false},"body":null,"created_at":"2016-12-02T00:04:16Z","updated_at":"2016-12-05T00:11:11Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2ae3c186be044e0025ba2d9c763937ac6b759a34","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/lagom/lagom/pulls/317/commits","review_comments_url":"https://api.github.com/repos/lagom/lagom/pulls/317/comments","review_comment_url":"https://api.github.com/repos/lagom/lagom/pulls/comments{/number}","comments_url":"https://api.github.com/repos/lagom/lagom/issues/317/comments","statuses_url":"https://api.github.com/repos/lagom/lagom/statuses/6f463c56db381e3e9e7ca6caa0fc1881ace9dfcc","head":{"label":"jroper:scala-implementing-services-docs","ref":"scala-implementing-services-docs","sha":"6f463c56db381e3e9e7ca6caa0fc1881ace9dfcc","user":{"login":"jroper","id":105833,"avatar_url":"https://avatars.githubusercontent.com/u/105833?v=3","gravatar_id":"","url":"https://api.github.com/users/jroper","html_url":"https://github.com/jroper","followers_url":"https://api.github.com/users/jroper/followers","following_url":"https://api.github.com/users/jroper/following{/other_user}","gists_url":"https://api.github.com/users/jroper/gists{/gist_id}","starred_url":"https://api.github.com/users/jroper/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jroper/subscriptions","organizations_url":"https://api.github.com/users/jroper/orgs","repos_url":"https://api.github.com/users/jroper/repos","events_url":"https://api.github.com/users/jroper/events{/privacy}","received_events_url":"https://api.github.com/users/jroper/received_events","type":"User","site_admin":false},"repo":{"id":53542964,"name":"lagom","full_name":"jroper/lagom","owner":{"login":"jroper","id":105833,"avatar_url":"https://avatars.githubusercontent.com/u/105833?v=3","gravatar_id":"","url":"https://api.github.com/users/jroper","html_url":"https://github.com/jroper","followers_url":"https://api.github.com/users/jroper/followers","following_url":"https://api.github.com/users/jroper/following{/other_user}","gists_url":"https://api.github.com/users/jroper/gists{/gist_id}","starred_url":"https://api.github.com/users/jroper/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jroper/subscriptions","organizations_url":"https://api.github.com/users/jroper/orgs","repos_url":"https://api.github.com/users/jroper/repos","events_url":"https://api.github.com/users/jroper/events{/privacy}","received_events_url":"https://api.github.com/users/jroper/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jroper/lagom","description":"Reactive Microservices for the JVM","fork":true,"url":"https://api.github.com/repos/jroper/lagom","forks_url":"https://api.github.com/repos/jroper/lagom/forks","keys_url":"https://api.github.com/repos/jroper/lagom/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jroper/lagom/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jroper/lagom/teams","hooks_url":"https://api.github.com/repos/jroper/lagom/hooks","issue_events_url":"https://api.github.com/repos/jroper/lagom/issues/events{/number}","events_url":"https://api.github.com/repos/jroper/lagom/events","assignees_url":"https://api.github.com/repos/jroper/lagom/assignees{/user}","branches_url":"https://api.github.com/repos/jroper/lagom/branches{/branch}","tags_url":"https://api.github.com/repos/jroper/lagom/tags","blobs_url":"https://api.github.com/repos/jroper/lagom/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jroper/lagom/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jroper/lagom/git/refs{/sha}","trees_url":"https://api.github.com/repos/jroper/lagom/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jroper/lagom/statuses/{sha}","languages_url":"https://api.github.com/repos/jroper/lagom/languages","stargazers_url":"https://api.github.com/repos/jroper/lagom/stargazers","contributors_url":"https://api.github.com/repos/jroper/lagom/contributors","subscribers_url":"https://api.github.com/repos/jroper/lagom/subscribers","subscription_url":"https://api.github.com/repos/jroper/lagom/subscription","commits_url":"https://api.github.com/repos/jroper/lagom/commits{/sha}","git_commits_url":"https://api.github.com/repos/jroper/lagom/git/commits{/sha}","comments_url":"https://api.github.com/repos/jroper/lagom/comments{/number}","issue_comment_url":"https://api.github.com/repos/jroper/lagom/issues/comments{/number}","contents_url":"https://api.github.com/repos/jroper/lagom/contents/{+path}","compare_url":"https://api.github.com/repos/jroper/lagom/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jroper/lagom/merges","archive_url":"https://api.github.com/repos/jroper/lagom/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jroper/lagom/downloads","issues_url":"https://api.github.com/repos/jroper/lagom/issues{/number}","pulls_url":"https://api.github.com/repos/jroper/lagom/pulls{/number}","milestones_url":"https://api.github.com/repos/jroper/lagom/milestones{/number}","notifications_url":"https://api.github.com/repos/jroper/lagom/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jroper/lagom/labels{/name}","releases_url":"https://api.github.com/repos/jroper/lagom/releases{/id}","deployments_url":"https://api.github.com/repos/jroper/lagom/deployments","created_at":"2016-03-10T00:47:27Z","updated_at":"2016-03-10T00:47:30Z","pushed_at":"2016-12-02T00:04:12Z","git_url":"git://github.com/jroper/lagom.git","ssh_url":"git@github.com:jroper/lagom.git","clone_url":"https://github.com/jroper/lagom.git","svn_url":"https://github.com/jroper/lagom","homepage":"","size":2686,"stargazers_count":0,"watchers_count":0,"language":"Scala","has_issues":false,"has_downloads":true,"has_wiki":true,"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":"lagom:master","ref":"master","sha":"086075ea2dde3fd7fbd090316f2b09b2523d986c","user":{"login":"lagom","id":17168851,"avatar_url":"https://avatars.githubusercontent.com/u/17168851?v=3","gravatar_id":"","url":"https://api.github.com/users/lagom","html_url":"https://github.com/lagom","followers_url":"https://api.github.com/users/lagom/followers","following_url":"https://api.github.com/users/lagom/following{/other_user}","gists_url":"https://api.github.com/users/lagom/gists{/gist_id}","starred_url":"https://api.github.com/users/lagom/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lagom/subscriptions","organizations_url":"https://api.github.com/users/lagom/orgs","repos_url":"https://api.github.com/users/lagom/repos","events_url":"https://api.github.com/users/lagom/events{/privacy}","received_events_url":"https://api.github.com/users/lagom/received_events","type":"Organization","site_admin":false},"repo":{"id":52320967,"name":"lagom","full_name":"lagom/lagom","owner":{"login":"lagom","id":17168851,"avatar_url":"https://avatars.githubusercontent.com/u/17168851?v=3","gravatar_id":"","url":"https://api.github.com/users/lagom","html_url":"https://github.com/lagom","followers_url":"https://api.github.com/users/lagom/followers","following_url":"https://api.github.com/users/lagom/following{/other_user}","gists_url":"https://api.github.com/users/lagom/gists{/gist_id}","starred_url":"https://api.github.com/users/lagom/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lagom/subscriptions","organizations_url":"https://api.github.com/users/lagom/orgs","repos_url":"https://api.github.com/users/lagom/repos","events_url":"https://api.github.com/users/lagom/events{/privacy}","received_events_url":"https://api.github.com/users/lagom/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/lagom/lagom","description":"Reactive Microservices for the JVM","fork":false,"url":"https://api.github.com/repos/lagom/lagom","forks_url":"https://api.github.com/repos/lagom/lagom/forks","keys_url":"https://api.github.com/repos/lagom/lagom/keys{/key_id}","collaborators_url":"https://api.github.com/repos/lagom/lagom/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/lagom/lagom/teams","hooks_url":"https://api.github.com/repos/lagom/lagom/hooks","issue_events_url":"https://api.github.com/repos/lagom/lagom/issues/events{/number}","events_url":"https://api.github.com/repos/lagom/lagom/events","assignees_url":"https://api.github.com/repos/lagom/lagom/assignees{/user}","branches_url":"https://api.github.com/repos/lagom/lagom/branches{/branch}","tags_url":"https://api.github.com/repos/lagom/lagom/tags","blobs_url":"https://api.github.com/repos/lagom/lagom/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/lagom/lagom/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/lagom/lagom/git/refs{/sha}","trees_url":"https://api.github.com/repos/lagom/lagom/git/trees{/sha}","statuses_url":"https://api.github.com/repos/lagom/lagom/statuses/{sha}","languages_url":"https://api.github.com/repos/lagom/lagom/languages","stargazers_url":"https://api.github.com/repos/lagom/lagom/stargazers","contributors_url":"https://api.github.com/repos/lagom/lagom/contributors","subscribers_url":"https://api.github.com/repos/lagom/lagom/subscribers","subscription_url":"https://api.github.com/repos/lagom/lagom/subscription","commits_url":"https://api.github.com/repos/lagom/lagom/commits{/sha}","git_commits_url":"https://api.github.com/repos/lagom/lagom/git/commits{/sha}","comments_url":"https://api.github.com/repos/lagom/lagom/comments{/number}","issue_comment_url":"https://api.github.com/repos/lagom/lagom/issues/comments{/number}","contents_url":"https://api.github.com/repos/lagom/lagom/contents/{+path}","compare_url":"https://api.github.com/repos/lagom/lagom/compare/{base}...{head}","merges_url":"https://api.github.com/repos/lagom/lagom/merges","archive_url":"https://api.github.com/repos/lagom/lagom/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/lagom/lagom/downloads","issues_url":"https://api.github.com/repos/lagom/lagom/issues{/number}","pulls_url":"https://api.github.com/repos/lagom/lagom/pulls{/number}","milestones_url":"https://api.github.com/repos/lagom/lagom/milestones{/number}","notifications_url":"https://api.github.com/repos/lagom/lagom/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/lagom/lagom/labels{/name}","releases_url":"https://api.github.com/repos/lagom/lagom/releases{/id}","deployments_url":"https://api.github.com/repos/lagom/lagom/deployments","created_at":"2016-02-23T01:51:06Z","updated_at":"2016-12-03T13:48:24Z","pushed_at":"2016-12-02T00:04:16Z","git_url":"git://github.com/lagom/lagom.git","ssh_url":"git@github.com:lagom/lagom.git","clone_url":"https://github.com/lagom/lagom.git","svn_url":"https://github.com/lagom/lagom","homepage":"https://lightbend.com/lagom","size":3031,"stargazers_count":987,"watchers_count":987,"language":"Scala","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":160,"mirror_url":null,"open_issues_count":59,"forks":160,"open_issues":59,"watchers":987,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/lagom/lagom/pulls/317"},"html":{"href":"https://github.com/lagom/lagom/pull/317"},"issue":{"href":"https://api.github.com/repos/lagom/lagom/issues/317"},"comments":{"href":"https://api.github.com/repos/lagom/lagom/issues/317/comments"},"review_comments":{"href":"https://api.github.com/repos/lagom/lagom/pulls/317/comments"},"review_comment":{"href":"https://api.github.com/repos/lagom/lagom/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/lagom/lagom/pulls/317/commits"},"statuses":{"href":"https://api.github.com/repos/lagom/lagom/statuses/6f463c56db381e3e9e7ca6caa0fc1881ace9dfcc"}}}}
{"actor":{"display_login":"jroper"}}