New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Lists the Scala Components and introduces DI in scala #559
Conversation
|
||
[CircuitBreakerComponents](api/com/lightbend/lagom/scaladsl/client/CircuitBreakerComponents.html) | ||
|
||
* implementors of a Service Locator will need to extend this to reuse the Circuit Breaker config provided by Lagom. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The section listing StaticServiceLocatorComponents
, ConfigurationServiceLocatorComponents
, RoundRobinServiceLocatorComponents
and CircuitBreakerComponents
could be extracted into a page of its own or merged into a single item of this, already long, list of Components
.
@@ -0,0 +1,96 @@ | |||
# Scala Components | |||
|
|||
The Lagom scaladsl requires building an Application that mixes in all the `Components` that will enable the required features for your code. This means each `Application` will need a specific set of cake slices. Not only that but `Dev` mode and `Prod` mode need adjusting since the environments where the Service is run vary. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should briefly introduce the cake pattern. This might sound strange and confusing to someone who has never encountered it before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, I was on cruise control and thought we had that explained in Implementing Services
already. Just checked and that section is missing a link or an explanation too.
This page looks like an appropriate location for an intro to cake
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think this page would be a better place for it. We also have to consider the order that people will see things in, if they read through the docs linearly.
|
||
@[lagom-application](code/ServiceImplementation.scala) | ||
|
||
That is a simple enough Application but it's not complete for running. It extends [`LagomApplication`](api/com/lightbend/lagom/scaladsl/server/LagomApplication.html) so it has all the basic bits and pieces but you need to specify at least a [[Service Locator|ServiceLocator]] for each environment Lagom supports: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might not be clear that loadDevMode
specifies a ServiceLocator
by way of mixing in LagomDevModeComponents
.
|
||
This is a list of available `Components` you will need to build your application cake. | ||
|
||
[LagomServerComponents](api/com/lightbend/lagom/scaladsl/server/LagomServerComponents.html) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's somewhat inconsistent use of backtick quoting in this file. The usual convention is to use them when quoting code or identifiers used in the code. So, I wouldn't expect "Components" above or "Component" below to be displayed as inline code, because there are no identifiers with those names, but I would expect LagomServerComponents
to be quoted with backticks.
|
||
[LagomServerComponents](api/com/lightbend/lagom/scaladsl/server/LagomServerComponents.html) | ||
|
||
* a main `Component` for any Lagom Service and is already mixed into [`LagomApplication`](api/com/lightbend/lagom/scaladsl/server/LagomApplication.html), you won't need to use it explicitly. Includes [LagomServiceClientComponents](api/com/lightbend/lagom/scaladsl/client/LagomServiceClientComponents.html). See [[Wiring together a Lagom application|ServiceImplementation#Wiring-together-a-Lagom-application]]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the "Wiring together a Lagom application" section will need to be rewritten a bit to refer to this page and remove duplication. I was thinking the outcome of this PR would be to take that section and elevate it to a top-level page that includes all of the details you have here. Then, the section within the "Implementing services" page could just refer to how to register services, leaving most of the rest of the content to this page.
I also think that "Wiring together a Lagom application" (or "Lagom service"? We are inconsistent with our terminology) is a better title for the page than "Scala Components". While "Scala Components" does describe what is in the page, it isn't descriptive to someone who doesn't already know about how Lagom Scala services are assembled. On more reflection, I think a title like "Bootstrapping a Lagom Scala service" or "Dependency Injection in Lagom" might be even better. The rule of thumb I like to use is to imagine the person we want to land on this page, and think about what they might have typed into Google to find it.
|
||
[MetricsServiceComponents](api/com/lightbend/lagom/scaladsl/server/status/MetricsServiceComponents.html) | ||
|
||
* adds a `MetricsService` to your service so you can remotely track the status of the CircuitBreakers on your service. Using this only makes sense when you Application is consuming other services (hence using remote calls protected with Circuit Breakers) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should link to the docs on circuit breakers.
|
||
[ClusterComponents](api/com/lightbend/lagom/scaladsl/cluster/ClusterComponents.html) | ||
|
||
* registers the node to the Akka Cluster. Tha Akka Cluster is required by Pub-Sub and Persistent Entity support and you will rarely need to use it explicitly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it should link to the clustering docs.
|
||
You can mix in `Components` from other frameworks or libraries, for example: | ||
|
||
* [ConductRApplicationComponents](https://github.com/typesafehub/conductr-lib/blob/master/lagom1-scala-conductr-bundle-lib/src/main/scala/com/typesafe/conductr/bundlelib/lagom/scaladsl/ConductRApplicationComponents.scala) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we link to documentation that describes how to use this? Maybe http://www.lagomframework.com/documentation/1.3.x/scala/ConductR.html
You can mix in `Components` from other frameworks or libraries, for example: | ||
|
||
* [ConductRApplicationComponents](https://github.com/typesafehub/conductr-lib/blob/master/lagom1-scala-conductr-bundle-lib/src/main/scala/com/typesafe/conductr/bundlelib/lagom/scaladsl/ConductRApplicationComponents.scala) | ||
* [AhcWSComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.libs.ws.ahc.AhcWSComponents): provides Async HTTP communication |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not clear when users would need to bring this in... from what I can see, in practice all Lagom services include it.
This is a bit tangential to this PR, but it makes me wonder if we should be extending it in LagomApplication
or LagomClientComponents
. It seems like an implementation detail that we shouldn't expose to end users. The only other implementation I can find is the deprecated NingWSComponents
. WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure, I've thought about doing this a number of times, but there's every chance that Play will soon add an Akka HTTP implementation, and maybe users might want to select that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But shouldn't LagomApplication
have AhcWSClient
(or other) as default and let users override that at will. LagomApplication
requires a WSClient
in any case.
* [DBComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.db.DBComponents) | ||
* [HikariCPComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.db.HikariCPComponents) | ||
|
||
You can find a complete list of inherited `Components` in [Play docs](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.db.HikariCPComponents). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the right link?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to use https://www.playframework.com/documentation/2.5.x/api/scala/play/api/db/HikariCPComponents.html
, scaladoc automatically redirects to the frames version, but using the direct link has two advantages, it means our external link validation task (not run by CI but can be run manually) will pick up if the link is wrong, and also improves SEO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant more that it links directly to HikariCPComponents
, but the surrounding text talks about a complete list of components. Looks like a mistaken copy/paste from the previous link, but I'm not sure what a better link is, since there's no supertype for all of the components traits, and scaladoc doesn't seem to generate permalinks for searches. Maybe it should just go to the index?
* [ConductRApplicationComponents](https://github.com/typesafehub/conductr-lib/blob/master/lagom1-scala-conductr-bundle-lib/src/main/scala/com/typesafe/conductr/bundlelib/lagom/scaladsl/ConductRApplicationComponents.scala) | ||
* [AhcWSComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.libs.ws.ahc.AhcWSComponents): provides Async HTTP communication | ||
* [DBComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.db.DBComponents) | ||
* [HikariCPComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.db.HikariCPComponents) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When would you want to bring these in explicitly? DBComponents
is implicitly included by JdbcPersistenceComponents
.
Is HikariCPComponents
required when using it? Should we include it implicitly, too? We don't really have any good examples of Scala + JDBC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if HikariCPComponents
should be included implicitly - the question is whether we want to allow users to pull in a different connection pool. If it gets included implicitly, then it makes that impossible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TBH, I added this too after seeing some issues related to that on support channels. IIUC it's necessary to include DBComponents
and/or HikariCPComponents
to complete the cake correctly.
I didn't to raise this discussion but it's interesting.
Fixes #558 |
|
||
[LagomServiceClientComponents](api/com/lightbend/lagom/scaladsl/client/LagomServiceClientComponents.html) | ||
|
||
* a main `Component` for any Lagom Service or application consuming Lagom Services. It is already mixed into [`LagomClientApplication`](api/com/lightbend/lagom/scaladsl/client/LagomClientApplication.html), you won't need to use it explicitly. See [[Binding a service client|ServiceClients#Binding-a-service-client]]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually there are a number of use cases for using in explicitly. See:
Often you may want to break your cake up into isolated layers that can be independently tested. In the example above, I've created a trait called ItemComponents
which contains everything necessary to implement ItemServiceImpl
. What it doesn't do is subscribe to the bidding service, that's done in ItemApplication
. This allows me to use ItemComponents
to instantiate ItemServiceImpl
in tests, without needing to worry about mocking the BiddingService
.
* [ConductRApplicationComponents](https://github.com/typesafehub/conductr-lib/blob/master/lagom1-scala-conductr-bundle-lib/src/main/scala/com/typesafe/conductr/bundlelib/lagom/scaladsl/ConductRApplicationComponents.scala) | ||
* [AhcWSComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.libs.ws.ahc.AhcWSComponents): provides Async HTTP communication | ||
* [DBComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.db.DBComponents) | ||
* [HikariCPComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.db.HikariCPComponents) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if HikariCPComponents
should be included implicitly - the question is whether we want to allow users to pull in a different connection pool. If it gets included implicitly, then it makes that impossible.
You can mix in `Components` from other frameworks or libraries, for example: | ||
|
||
* [ConductRApplicationComponents](https://github.com/typesafehub/conductr-lib/blob/master/lagom1-scala-conductr-bundle-lib/src/main/scala/com/typesafe/conductr/bundlelib/lagom/scaladsl/ConductRApplicationComponents.scala) | ||
* [AhcWSComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.libs.ws.ahc.AhcWSComponents): provides Async HTTP communication |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure, I've thought about doing this a number of times, but there's every chance that Play will soon add an Akka HTTP implementation, and maybe users might want to select that?
* [DBComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.db.DBComponents) | ||
* [HikariCPComponents](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.db.HikariCPComponents) | ||
|
||
You can find a complete list of inherited `Components` in [Play docs](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.db.HikariCPComponents). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to use https://www.playframework.com/documentation/2.5.x/api/scala/play/api/db/HikariCPComponents.html
, scaladoc automatically redirects to the frames version, but using the direct link has two advantages, it means our external link validation task (not run by CI but can be run manually) will pick up if the link is wrong, and also improves SEO.
**TODO** There's still a couple of comments to be addressed: * whether `wiring together a lagom app` should be removed and merged with this. * whether db and hikari components should be refactored and/or listed here.
deefebe
to
8f3e2ba
Compare
TODO There's still a couple of discussions to be addressed:
|
I've reformatted the content to group the Components into categories mirroring the contents of the Reference Guide and reordered to keep a similar order too. |
Applied comments (fixed links and added content as commented)
Hi Ignasi,
Sorry, but I couldn't figure out how to attach these complicated comments
to the PR. Below, text in green shading was copied from PR, the gray
shading includes my questions/suggestions:
+The Lagom scaladsl requires building an Application that mixes in all the
Components that will enable the required features for your code. This means
each Application will need a specific set of cake slices. Not only that but
`Dev` mode and `Prod` mode need adjusting the cake since the environments
where the Service is run will vary.
A few questions:
- Not sure what the scaldsl is, is there a different name for it, or could
you explain what it is?
- Would the following intro make sense instead:
"Lagom offers several service components that you can include in your
application. When using using one of these components, you also need to
provide any functionality that it requires. Since the development and
production environments are often quite different, you need to make sure
that both environments have met dependencies in the correct way. One way to
do this is to use the "cake pattern".
<then I would remove the subhead and just follow with your next para>
+The cake pattern is a design pattern for Dependency Injection in scala
where an application (the cake) is built as by mixing in several traits
(the cake slices). Each trait may declare unimplemented `def` methods
stating what it requires to run. Each trait may provide implementations the
final application will need. To present an example, many Lagom Components
(or cake layers) declare a need for a `ServiceLocator` and as a developer
you are required to provide one when using one of those Components. If you
don't fulfill all the declared requirements for the cake slices you mix
into your cake, it will be incomplete and compilation will fail.
<suggested edit to prev para - note that I changed slices to layers, but if
this is incorrect, please fix>
+The cake pattern is a design pattern used in a number of languages,
including Scala. The cake pattern offers a good model for Dependency
Injection. Think of an application as if it were a layered cake. To build
the cake, you add layers. In the code, unimplemented `def` methods state
what is required. Scala traits define a particular requirement for running
the application. Each trait may provide implementations the final
application will need. For example, many Lagom Components (or cake layers)
declare a need for a `ServiceLocator`. You are required to provide the
trait that you want to use in each environment. If you don't fulfill all of
the declared requirements for the layers you want in the cake, it will be
incomplete and will not compile.
Then, I pull your example out into a separate file:
# Application cake pattern example
Then, the list of available components would immediately follow the
introduction.
This is a list of available `Components` you may use to build your
application cake. This list contains Components provided by Lagom, Play and
other projects or libraries. You may develop your own Components and use
those instead of the provided on this list as long as the contracts are
fulfilled.
This section lists `Components` provided by Lagom, Play and other projects
that you can use to build your application cake. You can also develop and
use your own components as long as you fulfill the contracts.
Available components are grouped into the following categories (with x-ref
to the tables if possible):
- Service
- Persistence and Cluster
- Broker API
- Service Locator
- External (I would put the list you have at the bottom in a table too and
above it put the x-ref to the Play components page)
Hope this is useful!
cheers,
Ruth
…On Tue, Mar 7, 2017 at 11:22 AM, Ignasi Marimon-Clos < ***@***.***> wrote:
Formatted the groups into tables:
[image: screen shot 2017-03-07 at 18 21 22]
<https://cloud.githubusercontent.com/assets/762126/23668941/f0e9c9bc-0362-11e7-89d1-c054c49b5124.png>
[image: screen shot 2017-03-07 at 18 21 30]
<https://cloud.githubusercontent.com/assets/762126/23668942/f0ea5b48-0362-11e7-9dc2-0a11e2540f33.png>
—
You are receiving this because your review was requested.
Reply to this email directly, view it on GitHub
<#559 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AV1DeyU2MmDYClAOwFC4pIS4eT4OMxwwks5rjZJAgaJpZM4MOqMX>
.
--
Ruth Stento
User Experience Lead
Lightbend
512-818-6459
<http://lightbend.com>
|
I think we can take refactoring out of scope for this pull request. We should list them in the meantime.
I think we should do this as part of this change, as otherwise this page does not make much sense on its own, especially if people read through the docs linearly and encounter this page before the service implementation page.
👍
Sure thing, but I'm conscious of the fact that if we put this out into the world, and then rename later, it could just mean more broken links.
There's not a whole lot we can do... no way to redirect an anchor. The best we could do, if this is a big concern, is leave the heading in the original page (perhaps moving it to the end) with a link back to this new page.
After thinking about it more, I think we should name the page "Dependency injection in Lagom". I think the term "dependency injection" is probably more familiar and more Google-friendly than "wiring together", and it sidesteps the entire application/service issue while still being clear. 😄 It also subtly emphasizes that this is a cross-cutting concern, rather than something specific to the service API. |
Also, WRT the title "Dependency injection in Lagom", we should also create an analogous page in the Java documentation that gives an overview of how Guice is used. I think it can be a separate PR. |
@rstento I'll chime in with comments since @ignasi35 is probably offline for the day.
That's Lagom's Scala API. The package name in the code is
I think it's an improvement. I wonder if we should go even more fundamental. Can we assume that everyone is familiar with dependency injection as a general pattern? I don't want to distract with too much detail, but maybe we should link to http://di-in-scala.github.io/ and perhaps quote or paraphrase a few excerpts. Here's my take: When building services in Lagom, your code will have dependencies on Lagom APIs and other services that need to be satisfied by concrete implementations at runtime. Often, the specific implementations will vary between development, test and production environments, so it's important not to couple your code tightly to a concrete implementation class. A class can declare constructor parameters with the abstract types of its dependencies --- usually represented by traits in Scala --- allowing the concrete implementations to be provided when the class is constructed. This pattern is called "dependency injection" and is fundamental to the way Lagom applications are assembled. Read "Dependency Injection in Scala using MacWire" for more background on this pattern and its benefits. Your service's dependencies will have their own dependencies on other APIs in turn. Taken all together, these form a dependency graph that must be constructed when your application starts up. This process is called "wiring" your application, and is performed by creating a subclass of
👍
Reading through all of "DI in Scala", Jonas's original cake pattern article and Martin's "Scalable Component Abstractions" paper, none of them either "slice" or "layer" in this context. I think "layer" is a more accurate description, but I'm wary of introducing terminology if it isn't in common use and doesn't correspond to the naming conventions in the API, which always uses "component".
I'm pretty sure it's specific to Scala. Have you found references to it being used in other languages? In any case, it's a bit immaterial to this page, so I think we should keep something closer to the original wording here.
I think the original metaphor was more about mixing ingredients together. I think we should avoid metaphors, though, as in this context I don't think they'll help developers understand what they need to do in their code. In fact, the more I read about this, the more I think that we should mostly avoid calling this the "cake pattern" and generally avoid using cake metaphors throughout the documentation. The pattern we have adopted is fairly different from the cake pattern as originally described by Jonas, which relied on self types and nested traits. What we're using is closer to the "thin cake" pattern as described by Adam Warski in "DI in Scala" and his earlier blog post. Some influential people even call the cake pattern an anti-pattern, but this is referring to the original cake pattern, not the thin cake pattern we have adopted. A Quora answer for "What is the Scala Cake Pattern?" even says "Now it’s considered an anti-pattern and its usage is discouraged. I would recommend checking MacWire or Scaldi if you need dependency injection." This could easily confuse people, since we do use MacWire and not the version of the cake pattern that he is calling an anti-pattern. So, my recommendation is that we should strike "cake pattern" from our vocabulary in favor of more specific descriptions of what to do in Lagom, and refer only in passing to the "thin cake pattern" that Warski describes, just so that people can understand the relationship to the "DI in Scala" site (I suggest) we reference earlier.
I think "abstract methods" would be a more conventional and accurate way to refer to these.
Here's my suggested version of the paragraph: It is common to have clusters of interdependent classes that together form a larger logical component. It can be useful to modularize wiring code in a way that reflects these groupings. You can do so in Scala by defining a "component" In "Dependency Injection in Scala using MacWire" this method of mixing components together to form an application is referred to as the "thin cake pattern". I think this would be a good place to bring over some of the content from "Implementing services" and introduce MacWire. I agree with the rest of your suggestions, Ruth. |
* [DBComponents](https://www.playframework.com/documentation/2.5.x/api/scala/play/api/db/DBComponents.html) | ||
* [HikariCPComponents](https://www.playframework.com/documentation/2.5.x/api/scala/play/api/db/HikariCPComponents.html) | ||
|
||
You can find a complete list of inherited `Components` in [Play docs](https://www.playframework.com/documentation/2.5.x/api/scala/index.html#play.api.db.HikariCPComponents). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copying this comment so it doesn't get lost in the outdated diff:
I meant more that it links directly to HikariCPComponents
, but the surrounding text talks about a complete list of components. Looks like a mistaken copy/paste from the previous link, but I'm not sure what a better link is, since there's no supertype for all of the components traits, and scaladoc doesn't seem to generate permalinks for searches. Maybe it should just go to the index?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't understand your comment the first time. ;-)
|
||
|
||
|
||
You can mix in `Components` from other frameworks or libraries, for example: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment from the previous iteration is still not fully addressed:
There's somewhat inconsistent use of backtick quoting in this file. The usual convention is to use them when quoting code or identifiers used in the code. So, I wouldn't expect "Components" above or "Component" below to be displayed as inline code, because there are no identifiers with those names, but I would expect LagomServerComponents to be quoted with backticks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
slipped through the cracks.
|
||
This is a list of available `Components` you may use to build your application cake. This list contains Components provided by Lagom, Play and other projects or libraries. You may develop your own Components and use those instead of the provided on this list as long as the contracts are fulfilled. | ||
|
||
| Service Components || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The table headers should be broken out of the table and rendered as markdown headings, so that they have individual anchors, and also because they logically don't form part of the table data.
|
||
## Components | ||
|
||
This is a list of available `Components` you may use to build your application cake. This list contains Components provided by Lagom, Play and other projects or libraries. You may develop your own Components and use those instead of the provided on this list as long as the contracts are fulfilled. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really just provided by Lagom, Play and ConductR.
|
||
#### Building a cake step by step | ||
|
||
`LagomServerComponents` and `LagomServiceClientComponents` are a bit special because they are already mixed into `LagomApplication` and `LagomClientApplication` respectively so you will rarely need to explicitly mix either of them into your Application. The reason why `LagomServerComponents` and `LagomServiceClientComponents` exist is so that you can build your Application cake as the sum of middle-sized portions. Instead of creating a single `abstract class` where you mix in all the Componenets, you may create one trait `MyPartialFooTrait` where you mix in `LagomServerComponents` and parts of your logic and then you could create `MyPartialBarTrait` with some other parts. Then you would build a `MyApplication` mixing in `MyPartialFooTrait` and `MyPartialBarTrait`. so far it's not very different from having a single Application where all Components are mixed. The key advantage of partially creating your cake is that you can use `MyPartialTrait` in isolation in your tests (instead of using a complete `MyApplication`) which will be lighter and provide decoupling. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This paragraph seems strangely stuck in the middle of the reference tables. I think it could be moved up and titled something like "Defining your own components traits". It should start with the "why" — what is the problem to be solved — and then continue on to the "how".
I would recommend naming examples with the Components
suffix rather than Trait
, since that's the established convention.
I'm also not a big fan of using "Foo" and "Bar" as example names, as it can make it difficult to comprehend what a realistic example might be. Better to elaborate a real-world use case for the technique and use meaningful names in that context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a great idea. I didn't like how it was breaking the flow but wanted to present LagomServerComponents
and LagomServiceClientComponents
first.
Starting with the why is exactly what I needed.
Will think of a replacement for Foo and Bar.
I think using the word thin cake pattern is fine, and I agree that we shouldn't push the metaphor too hard, or even at all. The big question that this leaves is, what do we call it when you add a components trait to your application? Should it be just that? "To use Kafka, you need to add the KafkaComponents trait to your application"? Is that descriptive enough? Currently, the documentation says things like "To use Kafka, you need to mix the KafkaComponents trait into your application cake". This is more specific. The nice thing about calling it a cake is that we have a name for it that we can unambiguously refer to throughout the documentation, "mix X into your cake" is something that very quickly a Lagom developer will become familiar with and know exactly what that means. Without having a name, it will become more ambiguous, and if a developer jumps into a part of the docs that tells them to add KafkaComponents to their application, but they don't understand what that means, what do they search for on the docs/google/stack overflow/mailing list to find out? So I think in this case, there is enough value to introduce a name for the pattern that is being implemented, so my preference would be to simply use it as a name, and not to go into too much detail about the meaning of the name (we can link to other resources such as Warski's blog post). Also something to note, I think over time, the thin cake pattern will become known as the cake pattern, and the "original" cake pattern will be forgotten. Play refers to it as the cake pattern, we discuss it as the cake pattern everywhere. I think over time the issues of the original cake pattern will not be a problem. We can aid this by publishing blog posts, contributing to existing stack overflow questions about it, updating resources that mention it, etc. |
OK, yeah, that's a good point. I don't mind this specific use and agree that it makes things clearer. That said, to pick on a specific point:
My feeling is that everywhere in the docs where we talk about adding some trait to your application cake, we should link back to this page as background information. In general, I like liberal use of links both within the documentation and to external references. People shouldn't have to Google things to understand what they mean. Agree with your overall conclusion. |
I ended up splitting the page in two as suggested. It was getting too big anyway. |
* moved 'wiring a lagom app' into DependencyInjection
In "[Dependency Injection in Scala: guide](http://di-in-scala.github.io/#modules)" this method of mixing components together to form an application is referred to as the "thin cake pattern". The guide also introduces [Macwire](http://di-in-scala.github.io/#macwire) which we'll use in the next steps. | ||
|
||
## Wiring together a Lagom application | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved Wiring together a lagom app
and merged it with content on DI.
@@ -0,0 +1,43 @@ | |||
# Scala Components | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A page of it's own.
* [[Persistence and Cluster Components|ScalaComponents#Persistence-and-Cluster-Components]] | ||
* [[Broker API Components|ScalaComponents#Broker-API-Components]] | ||
* [[Service Locator Components|ScalaComponents#Service-Locator-Components]] | ||
* [[Third party Components|ScalaComponents#Third-party-Components]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As @rstento suggested, the DI page ends on a list of quick links to each group of components. Since this is already provided I made it so the next: of DI would be Service Metadata
(instead of Scala Components
.
Reading the guide top to bottom (or in the right-hand side index) the user will see:
- Service descriptors
- Implementing services
- Dependency Injection
- Scala Components
- Service Metadata
- Consuming services
- Testing Services
- Message serializers
- Header Filters
- Error handling
But in the index.toc
I set it so Dependency Injection
's next was not Scala Components
but Service Metadata
.
@@ -1,5 +1,7 @@ | |||
ServiceDescriptors:Service descriptors | |||
ServiceImplementation:Implementing services | |||
DependencyInjection:Dependency Injection;next=ServiceInfo | |||
ScalaComponents:Scala Components | |||
ServiceInfo:Service Metadata |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comment above.
@ignasi35 do you think we should backport this to 1.3.x? |
Sure, on it. |
* Lists the components available to build the Application cake in scaladsl * Fixed `other other` * Introduce the cake pattern. Categorise and display in tables. **TODO** There's still a couple of comments to be addressed: * whether `wiring together a lagom app` should be removed and merged with this. * whether db and hikari components should be refactored and/or listed here. * Fix some PR comments (table title, 'define your components', ...). WIP * Improves DI and moves it into a separate page * Moves ScalaComponents and DependencyInjection into services/. * moved 'wiring a lagom app' into DependencyInjection * Final cleanup. Remove dead code and docs duplicates.
backport to 1.3.x f2d5274 |
Provides a summary of available Components and introduces briefly the cake pattern and how to use it to create an Application and an ApplicationLoader.
Each item of the list has a brief definition, link to scaladocs and, when possible, an x-ref to a refguide page.