0
# Server Components
1
2
Cake pattern components for building and configuring Netty servers with dependency injection support and modular architecture.
3
4
## Capabilities
5
6
### NettyServerComponents Trait
7
8
Provides a cake pattern trait for building complete server applications with all necessary dependencies.
9
10
```scala { .api }
11
/**
12
* Cake pattern trait providing NettyServer with dependencies
13
* Mix in with application components to create a complete server
14
*/
15
trait NettyServerComponents {
16
/** Server configuration - override to customize */
17
lazy val serverConfig: ServerConfig = ServerConfig()
18
19
/** The NettyServer instance - automatically configured and started */
20
lazy val server: NettyServer = {
21
Play.start(application)
22
new NettyServer(serverConfig, ApplicationProvider(application), serverStopHook)
23
}
24
25
/** Application environment */
26
lazy val environment: Environment = Environment.simple(mode = serverConfig.mode)
27
28
/** Optional source mapper for development */
29
lazy val sourceMapper: Option[SourceMapper] = None
30
31
/** Web commands for development tools */
32
lazy val webCommands: WebCommands = new DefaultWebCommands
33
34
/** Application configuration */
35
lazy val configuration: Configuration = Configuration(ConfigFactory.load())
36
37
/** Must be implemented - the Play application to serve */
38
def application: Application
39
40
/** Optional hook called when server stops */
41
def serverStopHook: () => Future[Unit] = () => Future.successful(())
42
}
43
```
44
45
**Usage Examples:**
46
47
```scala
48
import play.core.server.NettyServerComponents
49
import play.api.{Application, BuiltInComponents}
50
import play.api.routing.Router
51
import play.api.mvc._
52
53
// Create a complete server application
54
class MyServerApp extends NettyServerComponents with BuiltInComponents {
55
56
// Override server configuration
57
override lazy val serverConfig = ServerConfig(
58
port = Some(9000),
59
mode = play.api.Mode.Prod
60
)
61
62
// Define the application
63
lazy val application = new DefaultApplication(
64
environment,
65
applicationLifecycle,
66
injector,
67
configuration,
68
requestFactory,
69
httpErrorHandler
70
)
71
72
// Define routes
73
lazy val router = Router.from {
74
case GET -> Root / "health" => Action { Ok("OK") }
75
case GET -> Root / "info" => Action {
76
Ok(s"Server running on ${server.mainAddress}")
77
}
78
}
79
80
// Custom stop hook
81
override def serverStopHook = () => {
82
println("Server shutting down...")
83
Future.successful(())
84
}
85
}
86
87
// Start the server
88
val serverApp = new MyServerApp
89
// Server starts automatically via lazy val
90
println(s"Server started on port ${serverApp.server.httpPort}")
91
```
92
93
### NettyServerProvider
94
95
Server provider implementation for creating NettyServer instances in different contexts.
96
97
```scala { .api }
98
/**
99
* Creates NettyServer instances from provider context
100
*/
101
class NettyServerProvider extends ServerProvider {
102
/**
103
* Create NettyServer from context
104
* @param context Provider context with configuration and application
105
* @return Configured NettyServer instance
106
*/
107
def createServer(context: ServerProvider.Context): NettyServer
108
}
109
110
/**
111
* Context for server providers
112
* @param config Server configuration
113
* @param appProvider Application provider
114
* @param actorSystem Actor system for the server
115
* @param stopHook Shutdown callback
116
*/
117
case class ServerProvider.Context(
118
config: ServerConfig,
119
appProvider: ApplicationProvider,
120
actorSystem: akka.actor.ActorSystem,
121
stopHook: () => Future[Unit]
122
)
123
```
124
125
**Usage Examples:**
126
127
```scala
128
import play.core.server.{NettyServerProvider, ServerProvider}
129
130
// Create provider
131
val provider = new NettyServerProvider
132
133
// Create context
134
val context = ServerProvider.Context(
135
config = ServerConfig(port = Some(8080)),
136
appProvider = ApplicationProvider(myApp),
137
actorSystem = myActorSystem,
138
stopHook = () => Future.successful(())
139
)
140
141
// Create server via provider
142
val server = provider.createServer(context)
143
```
144
145
### Built-in Components Integration
146
147
Integrate NettyServerComponents with Play's built-in components for complete applications.
148
149
```scala { .api }
150
// Combine with BuiltInComponents for full Play stack
151
trait BuiltInComponents {
152
def environment: Environment
153
def configuration: Configuration
154
def applicationLifecycle: ApplicationLifecycle
155
def httpErrorHandler: HttpErrorHandler
156
// ... other built-in components
157
}
158
```
159
160
**Usage Examples:**
161
162
```scala
163
import play.api.BuiltInComponents
164
import play.api.routing.Router
165
import play.filters.HttpFiltersComponents
166
167
// Complete application with filters and built-ins
168
class ProductionServer extends NettyServerComponents
169
with BuiltInComponents
170
with HttpFiltersComponents {
171
172
override lazy val serverConfig = ServerConfig(
173
port = Some(sys.env.get("PORT").map(_.toInt).getOrElse(9000)),
174
mode = play.api.Mode.Prod
175
)
176
177
// Router with application logic
178
lazy val router = Router.from {
179
case GET -> Root / "api" / "users" => userController.list
180
case POST -> Root / "api" / "users" => userController.create
181
case GET -> Root / "api" / "users" / Long(id) => userController.show(id)
182
}
183
184
// Application with all components wired
185
lazy val application = Application(
186
environment,
187
applicationLifecycle,
188
injector,
189
configuration,
190
requestFactory,
191
httpErrorHandler
192
)
193
194
// Custom controllers and services
195
lazy val userController = new UserController(userService)
196
lazy val userService = new UserService(database)
197
lazy val database = new DatabaseService(configuration)
198
}
199
200
// Production startup
201
object ProductionMain extends App {
202
val server = new ProductionServer
203
println(s"Production server started on ${server.server.mainAddress}")
204
205
// Graceful shutdown
206
sys.addShutdownHook {
207
server.server.stop()
208
}
209
}
210
```
211
212
### Environment and Configuration
213
214
Environment and configuration management for server components.
215
216
```scala { .api }
217
/**
218
* Application environment configuration
219
* @param rootPath Application root path
220
* @param classLoader Class loader for the application
221
* @param mode Application mode (Dev/Test/Prod)
222
*/
223
case class Environment(
224
rootPath: java.io.File,
225
classLoader: ClassLoader,
226
mode: Mode
227
)
228
229
object Environment {
230
/** Create simple environment for given mode */
231
def simple(
232
path: java.io.File = new java.io.File("."),
233
mode: Mode = Mode.Test
234
): Environment
235
}
236
237
/**
238
* Application configuration wrapper
239
*/
240
case class Configuration(underlying: com.typesafe.config.Config) {
241
def get[A](path: String)(implicit loader: ConfigLoader[A]): A
242
def getOptional[A](path: String)(implicit loader: ConfigLoader[A]): Option[A]
243
// ... other configuration methods
244
}
245
246
object Configuration {
247
/** Load configuration from reference.conf and application.conf */
248
def apply(config: com.typesafe.config.Config): Configuration
249
250
/** Empty configuration */
251
val empty: Configuration
252
}
253
```
254
255
**Usage Examples:**
256
257
```scala
258
import play.api.{Environment, Configuration, Mode}
259
import com.typesafe.config.ConfigFactory
260
261
// Custom environment
262
val environment = Environment.simple(
263
path = new java.io.File("/opt/myapp"),
264
mode = Mode.Prod
265
)
266
267
// Custom configuration
268
val config = Configuration(ConfigFactory.parseString("""
269
app.name = "MyApp"
270
app.version = "1.0.0"
271
database.url = "jdbc:postgresql://localhost/myapp"
272
"""))
273
274
// Access configuration values
275
val appName = config.get[String]("app.name")
276
val dbUrl = config.getOptional[String]("database.url")
277
```