|
| 1 | +--- |
| 2 | +lang: en |
| 3 | +title: 'Application' |
| 4 | +keywords: LoopBack 4.0, LoopBack 4 |
| 5 | +tags: |
| 6 | +sidebar: lb4_sidebar |
| 7 | +permalink: /doc/en/lb4/Application.html |
| 8 | +summary: |
| 9 | +--- |
| 10 | + |
| 11 | +## What is an Application? |
| 12 | + |
| 13 | +In LoopBack 4, the [`Application`](http://apidocs.strongloop.com/@loopback%2fcore/#Application) |
| 14 | +class is the central class for setting up all of your module's components, |
| 15 | +controllers, servers and bindings. The `Application` class extends |
| 16 | +[Context](Context.md), and provides the controls for starting and stopping |
| 17 | +itself and its associated servers. |
| 18 | + |
| 19 | +When using LoopBack 4, we strongly encourage you to create your own subclass |
| 20 | +of `Application` to better organize your configuration and setup. |
| 21 | + |
| 22 | +## Making your own application class |
| 23 | + |
| 24 | +By making your own application class, you can perform several additional |
| 25 | +tasks as a part of your setup: |
| 26 | +- Pass configuration into the base class constructor |
| 27 | +- Perform some asynchronous wireup before application start |
| 28 | +- Perform some graceful cleanup on application stop |
| 29 | + |
| 30 | +{% include code-caption.html content="src/widget-application.ts" %} |
| 31 | +```ts |
| 32 | +import {Application} from '@loopback/core'; |
| 33 | +import {RestComponent, RestServer} from '@loopback/rest'; |
| 34 | +import {SamoflangeController, DoohickeyController} from './controllers'; |
| 35 | +import {WidgetApi} from './apidef/'; |
| 36 | + |
| 37 | +export class WidgetApplication extends Application { |
| 38 | + constructor() { |
| 39 | + // This is where you would pass configuration to the base constructor |
| 40 | + // (as well as handle your own!) |
| 41 | + super(); |
| 42 | + const app = this; // For clarity. |
| 43 | + // You can bind to the Application-level context here. |
| 44 | + // app.bind('foo').to(bar); |
| 45 | + app.component(RestComponent); |
| 46 | + app.controller(SamoflangeController); |
| 47 | + app.controller(DoohickeyController); |
| 48 | + } |
| 49 | + |
| 50 | + async start() { |
| 51 | + // This is where you would asynchronously retrieve servers, providers and |
| 52 | + // other components to configure them before launch. |
| 53 | + const server = await app.getServer(RestServer); |
| 54 | + server.bind('rest.port').to(8080); |
| 55 | + server.api(WidgetApi); |
| 56 | + // The superclass start method will call start on all servers that are |
| 57 | + // bound to the application. |
| 58 | + return await super.start(); |
| 59 | + } |
| 60 | + |
| 61 | + async stop() { |
| 62 | + // This is where you would do whatever is necessary before stopping your |
| 63 | + // app (graceful closing of connections, flushing buffers, etc) |
| 64 | + console.log('Widget application is shutting down...') |
| 65 | + // The superclass stop method will call stop on all servers that are |
| 66 | + // bound to the application. |
| 67 | + await super.stop(); |
| 68 | + } |
| 69 | +} |
| 70 | + |
| 71 | +``` |
| 72 | + |
| 73 | +## Configuring your application |
| 74 | +Your application can be configured with constructor arguments, bindings, or |
| 75 | +a combination of both. |
| 76 | + |
| 77 | +### Binding configuration |
| 78 | +Binding is the most commonly-demonstrated form of application configuration |
| 79 | +throughout our examples, and is the recommended method for setting up your |
| 80 | +application. |
| 81 | + |
| 82 | +In addition to the binding functions provided by [Context](Context.md), |
| 83 | +the `Application` class also provides some sugar functions for commonly used |
| 84 | +bindings, like `component`, `server` and `controller`: |
| 85 | + |
| 86 | +```ts |
| 87 | +export class MyApplication extends Application { |
| 88 | + constructor() { |
| 89 | + super(); |
| 90 | + this.component(MagicSuite); |
| 91 | + this.server(RestServer, 'public'); |
| 92 | + this.server(RestServer, 'private'); |
| 93 | + |
| 94 | + this.controller(FooController); |
| 95 | + this.controller(BarController); |
| 96 | + this.controller(BazController); |
| 97 | + } |
| 98 | +} |
| 99 | +``` |
| 100 | + |
| 101 | +You can find a complete list of these functions on the |
| 102 | +[`Application`](http://apidocs.loopback.io/@loopback%2fcore/#Application) API |
| 103 | +docs page. |
| 104 | + |
| 105 | +Additionally, you can use more advanced forms of binding to fine-tune your |
| 106 | +application's configuration: |
| 107 | + |
| 108 | +```ts |
| 109 | +export class MyApplication extends Application { |
| 110 | + constructor() { |
| 111 | + super(); |
| 112 | + this.server(RestServer); |
| 113 | + this.controller(FooController); |
| 114 | + this.bind('fooCorp.logger').toProvider(LogProvider); |
| 115 | + this.bind('repositories.widget') |
| 116 | + .toClass(WidgetRepository) |
| 117 | + .inScope(BindingScope.SINGLETON); |
| 118 | + } |
| 119 | +} |
| 120 | +``` |
| 121 | +In the above example: |
| 122 | +- injection calls for `fooCorp.logger` will be handled by the `LogProvider` |
| 123 | + class. |
| 124 | +- injection calls for `repositories.widget` will be handled by a singleton |
| 125 | +instance of the `WidgetRepository` class. |
| 126 | + |
| 127 | +#### Components |
| 128 | +```ts |
| 129 | +app.component(MyComponent); |
| 130 | +app.component(RestComponent); |
| 131 | +``` |
| 132 | +The `component` function allows binding of component constructors within |
| 133 | +your `Application` instance's context. |
| 134 | + |
| 135 | +For more information on how to make use of components, |
| 136 | +see [Using Components](Using-components.md). |
| 137 | + |
| 138 | +#### Controllers |
| 139 | +```ts |
| 140 | +app.controller(FooController); |
| 141 | +app.controller(BarController); |
| 142 | +``` |
| 143 | +Much like the component function, the `controller` function allows |
| 144 | +binding of [Controllers](Controllers.md) to the `Application` context. |
| 145 | + |
| 146 | +#### Servers |
| 147 | +```ts |
| 148 | +app.server(RestServer); |
| 149 | +app.servers([MyServer, GrpcServer]); |
| 150 | +``` |
| 151 | +The `server` function is much like the previous functions, but |
| 152 | +with [Servers](server.md) bulk bindings are possible through the function |
| 153 | +`servers`. |
| 154 | + |
| 155 | +```ts |
| 156 | +const app = new Application(); |
| 157 | +app.server(RestServer, 'public'); // {'public': RestServer} |
| 158 | +app.server(RestServer, 'private'); // {'private': RestServer} |
| 159 | +``` |
| 160 | +In the above example, the two server instances would be bound to the Application |
| 161 | +context under the keys `servers.public`, and `servers.private` respectively. |
| 162 | + |
| 163 | +### Constructor configuration |
| 164 | + |
| 165 | +The `Application` class constructor also accepts an |
| 166 | +[`ApplicationConfig`](http://apidocs.strongloop.com/@loopback%2fcore/#ApplicationConfig) |
| 167 | +object which contains component-level configurations such as |
| 168 | +[`RestServerConfig`](http://apidocs.strongloop.com/@loopback%2frest/#RestServerConfig). |
| 169 | +It will automatically create bindings for these configurations and later be injected |
| 170 | +through dependency injections. Visit [Dependency Injection](Dependency-injection.md) |
| 171 | +for more details. |
| 172 | + |
| 173 | +{% include note.html content=" |
| 174 | + Binding configuration such as component binding, provider binding, or binding scopes |
| 175 | + are not possible with the constructor-based configuration approach. |
| 176 | +" %} |
| 177 | + |
| 178 | +```ts |
| 179 | +export class MyApplication extends RestApplication { |
| 180 | + constructor() { |
| 181 | + super({ |
| 182 | + rest: { |
| 183 | + port: 4000, |
| 184 | + host: 'my-host' |
| 185 | + } |
| 186 | + }) |
| 187 | + } |
| 188 | +} |
| 189 | +``` |
| 190 | + |
| 191 | +## Tips for application setup |
| 192 | +Here are some tips to help avoid common pitfalls and mistakes. |
| 193 | + |
| 194 | +### Use unique bindings |
| 195 | +Use binding names that are prefixed with a unique string that does not overlap |
| 196 | +with loopback's bindings. As an example, if your application is built for |
| 197 | +your employer FooCorp, you can prefix your bindings with `fooCorp`. |
| 198 | +```ts |
| 199 | +// This is unlikely to conflict with keys used by other component developers |
| 200 | +// or within loopback itself! |
| 201 | +app.bind('fooCorp.widgetServer.config').to(widgetServerConfig); |
| 202 | +``` |
| 203 | + |
| 204 | +### Avoid use of `getSync` |
| 205 | +We provide the [`getSync`](http://apidocs.loopback.io/@loopback%2fcontext/#getSync) |
| 206 | +function for scenarios where you cannot asynchronously retrieve your bindings, |
| 207 | +such as in constructor bodies. |
| 208 | + |
| 209 | +However, the number of scenarios in which you must do this are limited, and you |
| 210 | +should avoid potential race conditions and retrieve your bindings asynchronously |
| 211 | +using the [`get`](http://apidocs.loopback.io/@loopback%2fcontext/#get) function |
| 212 | +whenever possible. |
| 213 | + |
| 214 | +### Use caution with singleton binding scopes |
| 215 | +By default, bindings for controllers will instantiate a new instance whenever |
| 216 | +they are injected or retrieved from their binding. Your application should only |
| 217 | +set singleton binding scopes on controllers when it makes sense to do so. |
0 commit comments